围绕 canvas 圈绘制条形音箱
Drawing sound bars around a canvas circle
我有以下将音频剪辑的频率绘制为条形音箱的方法:
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();
};
看起来像这样:
不过我想把它画成一个圆圈,所以就像从圆圈边界发出的光线一样。我没能弄清楚这一点。有人可以帮助我吗?
一个简单的方法是在其侧面绘制一个条形图,偏离圆心。在绘制条形图之前,将当前变换旋转到条形图的正确位置。
该示例使用了一些随机测试数据,因为我懒得设置分析器
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>
我有以下将音频剪辑的频率绘制为条形音箱的方法:
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();
};
看起来像这样:
不过我想把它画成一个圆圈,所以就像从圆圈边界发出的光线一样。我没能弄清楚这一点。有人可以帮助我吗?
一个简单的方法是在其侧面绘制一个条形图,偏离圆心。在绘制条形图之前,将当前变换旋转到条形图的正确位置。
该示例使用了一些随机测试数据,因为我懒得设置分析器
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>