首页 > 解决方案 > 未设置 canvas.height 时,在画布上将音频绘制为条形音箱不会覆盖上一次绘制

问题描述

我有以下内容,其中我得到了一个 audioBuffer 音频剪辑,然后我画了一圈条形音箱来可视化它:

const { audioContext, analyser } = this.getAudioContext();
const source = audioContext.createBufferSource();
source.buffer = this.props.audioBuffer;
analyser.fftSize = 256;
source.connect(analyser).connect(audioContext.destination);

source.start();

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext("2d");

// find the center of the window
let center_x = canvas.width / 2;
let center_y = canvas.height / 2;
let  radius = 150;

const frequency_array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(frequency_array);

const bars = analyser.frequencyBinCount;
const bar_width = 2;

animationLooper();

function animationLooper(){
    //canvas.height = window.innerHeight;

    // find the center of the window
    center_x = canvas.width / 2;
    center_y = canvas.height / 2;
    radius = 50;

    analyser.getByteFrequencyData(frequency_array);
    for(let i = 0; i < bars; i++){

        //divide a circle into equal parts
        let rads = Math.PI * 2 / bars;

        const bar_height = frequency_array[i] / 2;

        // set coordinates
        let x = center_x + Math.cos(rads * i) * (radius);
        let y = center_y + Math.sin(rads * i) * (radius);
        const x_end = center_x + Math.cos(rads * i)*(radius + bar_height);
        const y_end = center_y + Math.sin(rads * i)*(radius + bar_height);

        //draw a bar
        drawBar(x, y, x_end, y_end, bar_width);

    }
    window.requestAnimationFrame(animationLooper);
}

function drawBar(x1, y1, x2, y2, width){
    ctx.strokeStyle = "#1890ff";
    ctx.lineWidth = width;
    ctx.beginPath();
    ctx.moveTo(x1,y1);
    ctx.lineTo(x2,y2);
    ctx.stroke();
}

HTML:

<canvas id="canvas" width="400" height="400"  />

这会在音频播放完毕和绘图完成后产生。它应该恢复到没有蓝线。

错误的SoundBars

但是,如果我在该行中发表评论

canvas.height = window.innerHeight;

然后它正确地可视化音频,最后蓝线消失。但我想要画布的固定高度和宽度。最终结果应该是从中心圆出来的线条/条形音箱。

有谁知道为什么当我没有评论那条线时,当音频播放完毕时蓝线不会消失?

标签: javascriptreactjshtml5-canvasaudiocontext

解决方案


是的,如果您没有其他元素可以在每个帧的同一画布上绘制,则 clearRect 效果很好。但是,如果您只想删除画布上的一个元素,它将不起作用。

ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);

另一个问题是您可能需要某些类型的事务效果(例如音频条淡出)通过某个元素的帧。如果您继续为一个元素绘制效果,它可以清除这些帧期间的所有其他元素。

我想出的解决方案是将所有元素保存在一个数组中。然后使用布尔标记绘制数组,该标记决定是否为某个元素绘制。


推荐阅读