Рисование звуковых полос вокруг холста - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть следующее, что др aws частота аудиоклипа в качестве звуковых панелей:

const drawSinewave = function() {
    requestAnimationFrame(drawSinewave);

    analyser.getByteFrequencyData(sinewaveDataArray);

    canvasCtx.fillStyle = 'white';
    canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
    canvasCtx.lineWidth = 2;
    canvasCtx.strokeStyle = "#40a9ff";
    canvasCtx.beginPath();

    const sliceWidth = canvas.width * 1.0 / analyser.fftSize;
    let x = 0;

    var barWidth = (canvas.width  / analyser.fftSize) * 2.5;
    var barHeight;

    for(let i = 0; i < analyser.fftSize; i++) {
        barHeight = sinewaveDataArray[i];

        canvasCtx.fillStyle = 'rgb(' + (barHeight+100) + ',50,50)';
        canvasCtx.fillRect(x,canvas.height-barHeight/2,barWidth,barHeight);

        x += barWidth + 1;
    }

    canvasCtx.lineTo(canvas.width, canvas.height / 2);
    canvasCtx.stroke();
};

Это выглядит так: soundbars line

Тем не менее, я хотел бы нарисовать это вокруг круга, так, как если бы полосы появлялись как лучи от границы круга. Я не смог понять это. Может ли кто-нибудь помочь мне?

1 Ответ

1 голос
/ 26 апреля 2020

Простой метод - нарисовать одну полосу на своей стороне, смещенную от центра круга. перед тем, как нарисовать полосу, поверните текущее преобразование в правильную позицию для полосы.

В примере используются некоторые случайные тестовые данные, так как меня не беспокоит настройка анализатора

const steps = 100;
const testData = [];

const ctx = canvas.getContext("2d");
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const innerRadius = Math.min(canvas.width, canvas.height) / 2 * (3/4);
const outerRadius = Math.min(canvas.width, canvas.height) / 2 - 20;
const barHeight = outerRadius - innerRadius;
const angStep = (Math.PI * 2) / steps;
const barWidth = (innerRadius * Math.PI * 2 / steps) * 0.9;
const barWidthHalf= barWidth * 0.5;
const startAngle = -Math.PI / 2; // 12 oclock
requestAnimationFrame(drawBars)

function drawBars() {
    const color = h => 'rgb(' + (100+h*150) + ',' + (50+h*100) + ',' + (100+h*40) + ')';

    //analyser.getByteFrequencyData(sinewaveDataArray);
    //const steps = analyser.fftSize;
    animateTestData();
    
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    ctx.lineWidth = 2;
    ctx.strokeStyle = "#40a9ff";
    ctx.beginPath();
    ctx.arc(centerX, centerY, innerRadius - 4, 0, Math.PI * 2);
    ctx.stroke();

    for(let i = 0; i < steps; i++) {
        const h = testData[i];
        const ang = i * angStep + startAngle;
        const xAx = Math.cos(ang);  // direction of x axis
        const xAy = Math.sin(ang);
        ctx.setTransform(xAx, xAy, -xAy, xAx, centerX, centerY);

        ctx.fillStyle = color(h);
        ctx.fillRect(innerRadius, -barWidthHalf, h * barHeight, barWidth);
    }

    ctx.setTransform(1,0,0,1,0,0);  // reset the transform;
    requestAnimationFrame(drawBars);
};


for(let i = 0; i < steps; i ++) { testData.push(Math.random()) }
var sOffset = 0;
function animateTestData() {
    var i = 0, t, phase = Math.sin(sOffset/ 10) * 100;
    while(i < steps) {
        var t = testData[i];
        t += (Math.random() - 0.5) * 0.01;
        t += Math.sin(i * 0.6 + phase + sOffset) * 0.03
        t += Math.sin(i * 0.1 + sOffset * 2) * 0.07
        testData[i++] = t <= 0 ? 0 : t >= 1 ? 1 : t;
    }
    sOffset += 0.1;
}
<canvas id = "canvas" width = "600" height = "600"></canvas>
...