【问题标题】:HTML5 Canvas draw lines in a circle and move with music?HTML5 Canvas 画一个圆圈并随着音乐移动?
【发布时间】:2020-09-06 05:44:45
【问题描述】:

我可以在圆圈周围画线。我有 AudioContext API 设置的基本实现。

我面临的问题是当调用lineTo 时,这条线只会增长但不会缩小。我受到https://www.kkhaydarov.com/audio-visualizer/ 的启发。我正在将此代码翻译成 https://codesandbox.io/s/hungry-tereshkova-1pf0c?runonclick=1&file=/src/Visualizer.js:713-725,这是一个 React.js 版本。

如果您运行该代码,您将看到音乐播放,然后这些条会增长一次,然后它们会粘住。他们拒绝缩小然后随着节拍成长。

我不确定我哪里出错了或者我在该代码中缺少什么。它似乎与示例中的其他代码非常相似。

这是 Visualizer 组件的完整代码。

import React, { useEffect, useRef } from "react";

let frequencyArray = [];
let analyser;

const Visualizer = () => {
  const canvasRef = useRef(null);
  const requestRef = useRef(null);

  useEffect(() => {
    initAudio();
    requestRef.current = requestAnimationFrame(drawCanvas);
    return () => cancelAnimationFrame(requestRef.current);

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const initAudio = () => {
    const audio = new Audio();
    audio.src =
      "https://s3.us-west-2.amazonaws.com/storycreator.uploads/ck9kpb5ss0xf90132mgf8z893?client_id=d8976b195733c213f3ead34a2d95d1c1";
    audio.crossOrigin = "anonymous";
    audio.load();

    const context = new (window.AudioContext || window.webkitAudioContext)();
    analyser = context.createAnalyser();
    const source = context.createMediaElementSource(audio);

    source.connect(analyser);
    analyser.connect(context.destination);

    frequencyArray = new Uint8Array(analyser.frequencyBinCount);
    audio.play();
  };

  // draw the whole thing
  const drawCanvas = () => {
    if (canvasRef.current) {
      const canvas = canvasRef.current;
      const ctx = canvas.getContext("2d");
      const radius = 200;
      const bars = 100;

      drawCircle(canvas, ctx, radius);

      analyser.getByteFrequencyData(frequencyArray);

      for (var i = 0; i < bars; i++) {
        const height = frequencyArray[i] * 0.3;

        drawLine(
          {
            i,
            bars,
            height,
            radius
          },
          canvas,
          ctx
        );
      }

      requestRef.current = requestAnimationFrame(drawCanvas);
    }
  };

  // draw the main circle
  const drawCircle = (canvas, ctx, radius) => {
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;

    ctx.save();
    ctx.beginPath();
    ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
    ctx.fillStyle = "white";
    ctx.fill();
    ctx.strokeStyle = "#dddddd";
    ctx.lineWidth = 5;
    ctx.stroke();
    ctx.restore();
  };

  // dray lines around the circle
  const drawLine = (opts, canvas, ctx) => {
    const { i, radius, bars, height } = opts;
    const centerX = canvas.width / 2;
    const centerY = canvas.height / 2;
    const lineWidth = 10;
    const rads = (Math.PI * 2) / bars;

    const x = centerX + Math.cos(rads * i) * (radius + lineWidth);
    const y = centerY + Math.sin(rads * i) * (radius + lineWidth);
    const endX = centerX + Math.cos(rads * i) * (radius + height);
    const endY = centerY + Math.sin(rads * i) * (radius + height);

    // draw the bar
    ctx.strokeStyle = "#ddd";
    ctx.lineWidth = lineWidth;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(endX, endY);
    ctx.stroke();
  };

  return (
    <canvas
      ref={canvasRef}
      style={{ background: "#f5f5f5" }}
      width={window.innerWidth}
      height={window.innerHeight}
    />
  );
};

export default Visualizer;

【问题讨论】:

    标签: javascript html reactjs canvas


    【解决方案1】:

    您只是在代码中错过了clearRect...
    没有它,我们看到线条的增长只是因为任何后面的较短的线条都不会覆盖前面的线条,它们仍然被绘制,只是我们没有看到它。

    这里是工作代码:

    https://codesandbox.io/s/dry-cdn-ghu4m?file=/src/Visualizer.js:1247-1276

    我硬编码了一个 ctx.clearRect(0,0, 1000,1000) 只是为了向您展示它的工作原理,但您应该使用那里的画布尺寸,其他一切看起来都不错。

    唯一的建议是以某种方式移动:

    const canvas = canvasRef.current;
    const ctx = canvas.getContext("2d");
    

    drawCanvas 函数之外的全局位置,
    这些在每次运行时都不会改变,最好只设置一次。

    【讨论】:

    • ?‍♂️哇,它有效。谢谢!我刚刚回到 Canvas 代码。出于某种原因,在您的 fork 中,我没有看到 ctx.clearRect(0,0, 1000,1000) 的代码。你说得对,我想清理这段代码。我目前正在反复试验。很好的反馈!
    • 基于浏览器的代码编辑器很棘手。老实说,我对codeandbox印象深刻,不能100%完美。我把它放在drawCanvas 的顶部,效果很好。棒极了。感谢您指出。
    • 一切基于浏览器的东西都很棘手......或者只是简单的困难,有时甚至令人费解......请工作安全鼓。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    • 2016-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多