javascript canvas 围绕一个面向中心的圆绘制多个矩形
javascript canvas draw multiple rectangles around a circle facing the centre
我正在寻找一种方法,以面向中心的角度围绕一个圆绘制多个矩形。到目前为止我所拥有的,目前只是围绕一个面向一个方向的圆圈绘制矩形,缺少朝向中心的倾斜角 -
https://thysultan.com/projects/thyplayer/
我想要的是让矩形倾斜一个角度,使每个矩形在指定位置面向圆心。
怎么做到的?
三角法
要使线条向中心移动,您可以使用变换或三角数学。就个人而言,我发现在这种情况下使用数学更容易,所以这里有这样一个例子。
有关如何使用转换的示例,请参见@markE 的回答(转换通常在视觉上和代码中更容易)。
一些先决条件:
- 我们知道 canvas 的方向是 0° 角指向右边。如果您想以某种方式标记频率范围,这是必不可少的。
- 我们需要计算从外半径到中心(内半径)的线的长度
- 我们需要根据角度计算直线的端点。
一个简单的解决方案可以是创建一个函数,该函数在某个 angle
(以弧度为单位)的中心 (cx, cy)
处计算一条单线,长度为 t
,t在 [0, 1] 范围内(作为 FFT 浮点缓冲区)。我们还提供了一个外半径和内半径来限制线:
function getLine(cx, cy, angle, t, oRadius, iRadius) {
var radiusDiff = oRadius - iRadius, // calc radius diff to get max length
length = radiusDiff * t; // now we have the line length
return {
x1: oRadius * Math.cos(angle), // x1 point (outer)
y1: oRadius * Math.sin(angle), // y1 point (outer)
x2: (oRadius - length) * Math.cos(angle), // x2 point (inner)
y2: (oRadius - length) * Math.sin(angle) // y2 point (inner)
}
}
我们现在需要做的就是从 FFT 分析器向它提供数据。
注意:由于所有线都指向中心,因此中心区域会很拥挤。确定线宽和内半径以及要使用的 bin 数量时需要注意的事项。
示例演示
例如,我将为 "FFT" 使用一些随机数据并绘制 64 个 bin。
// angle - in radians
function getLine(cx, cy, angle, t, oRadius, iRadius) {
var radiusDiff = oRadius - iRadius, // calc radius diff to get max length
length = radiusDiff * t; // now we have the line length
return {
x1: cx + oRadius * Math.cos(angle), // x1 point (outer)
y1: cy + oRadius * Math.sin(angle), // y1 point (outer)
x2: cx + (oRadius - length) * Math.cos(angle), // x2 point (inner)
y2: cy + (oRadius - length) * Math.sin(angle) // y2 point (inner)
}
}
// calculate number of steps based on bins
var ctx = document.querySelector("canvas").getContext("2d"),
fftLength = 64,
angleStep = Math.PI * 2 / fftLength,
angle = 0,
line;
ctx.beginPath(); // not needed in demo, but when animated
while(angle < Math.PI*2) {
// our line function in action:
line = getLine(250, 250, angle, getFFT(), 240, 50);
ctx.moveTo(line.x1, line.y1); // add line to path
ctx.lineTo(line.x2, line.y2);
angle += angleStep // get next angle
}
ctx.lineWidth = 5; // beware of center area
ctx.stroke(); // stroke all lines at once
// to smooth the "FFT" random data
function getFFT() {return Math.random() * 0.16 + 0.4}
<canvas width=500 height=500></canvas>
我正在寻找一种方法,以面向中心的角度围绕一个圆绘制多个矩形。到目前为止我所拥有的,目前只是围绕一个面向一个方向的圆圈绘制矩形,缺少朝向中心的倾斜角 -
https://thysultan.com/projects/thyplayer/
我想要的是让矩形倾斜一个角度,使每个矩形在指定位置面向圆心。 怎么做到的?
三角法
要使线条向中心移动,您可以使用变换或三角数学。就个人而言,我发现在这种情况下使用数学更容易,所以这里有这样一个例子。
有关如何使用转换的示例,请参见@markE 的回答(转换通常在视觉上和代码中更容易)。
一些先决条件:
- 我们知道 canvas 的方向是 0° 角指向右边。如果您想以某种方式标记频率范围,这是必不可少的。
- 我们需要计算从外半径到中心(内半径)的线的长度
- 我们需要根据角度计算直线的端点。
一个简单的解决方案可以是创建一个函数,该函数在某个 angle
(以弧度为单位)的中心 (cx, cy)
处计算一条单线,长度为 t
,t在 [0, 1] 范围内(作为 FFT 浮点缓冲区)。我们还提供了一个外半径和内半径来限制线:
function getLine(cx, cy, angle, t, oRadius, iRadius) {
var radiusDiff = oRadius - iRadius, // calc radius diff to get max length
length = radiusDiff * t; // now we have the line length
return {
x1: oRadius * Math.cos(angle), // x1 point (outer)
y1: oRadius * Math.sin(angle), // y1 point (outer)
x2: (oRadius - length) * Math.cos(angle), // x2 point (inner)
y2: (oRadius - length) * Math.sin(angle) // y2 point (inner)
}
}
我们现在需要做的就是从 FFT 分析器向它提供数据。
注意:由于所有线都指向中心,因此中心区域会很拥挤。确定线宽和内半径以及要使用的 bin 数量时需要注意的事项。
示例演示
例如,我将为 "FFT" 使用一些随机数据并绘制 64 个 bin。
// angle - in radians
function getLine(cx, cy, angle, t, oRadius, iRadius) {
var radiusDiff = oRadius - iRadius, // calc radius diff to get max length
length = radiusDiff * t; // now we have the line length
return {
x1: cx + oRadius * Math.cos(angle), // x1 point (outer)
y1: cy + oRadius * Math.sin(angle), // y1 point (outer)
x2: cx + (oRadius - length) * Math.cos(angle), // x2 point (inner)
y2: cy + (oRadius - length) * Math.sin(angle) // y2 point (inner)
}
}
// calculate number of steps based on bins
var ctx = document.querySelector("canvas").getContext("2d"),
fftLength = 64,
angleStep = Math.PI * 2 / fftLength,
angle = 0,
line;
ctx.beginPath(); // not needed in demo, but when animated
while(angle < Math.PI*2) {
// our line function in action:
line = getLine(250, 250, angle, getFFT(), 240, 50);
ctx.moveTo(line.x1, line.y1); // add line to path
ctx.lineTo(line.x2, line.y2);
angle += angleStep // get next angle
}
ctx.lineWidth = 5; // beware of center area
ctx.stroke(); // stroke all lines at once
// to smooth the "FFT" random data
function getFFT() {return Math.random() * 0.16 + 0.4}
<canvas width=500 height=500></canvas>