【发布时间】:2020-04-25 07:00:12
【问题描述】:
我正在寻找一种方法以面向中心的角度围绕圆绘制多个矩形。到目前为止我所拥有的,目前只是围绕一个面向一个方向的圆绘制矩形,而没有向中心倾斜的角度 -
https://thysultan.com/projects/thyplayer/
我想要的是让矩形倾斜一个角度,使每个矩形在其指定位置面向圆心。 如何做到这一点?
【问题讨论】:
标签: javascript math canvas trigonometry angle
我正在寻找一种方法以面向中心的角度围绕圆绘制多个矩形。到目前为止我所拥有的,目前只是围绕一个面向一个方向的圆绘制矩形,而没有向中心倾斜的角度 -
https://thysultan.com/projects/thyplayer/
我想要的是让矩形倾斜一个角度,使每个矩形在其指定位置面向圆心。 如何做到这一点?
【问题讨论】:
标签: javascript math canvas trigonometry angle
要使线条向中心移动,您可以使用变换或三角数学。就个人而言,我发现在这种情况下使用数学更容易,所以这里有一个例子。
有关如何使用转换的示例,请参阅 @markE 的回答(转换在视觉上和在代码中通常更容易)。
一些先决条件:
一个简单的解决方案是创建一个函数,计算中心(cx, cy) 在某个angle(以弧度为单位)处的一条线,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>
【讨论】: