javascript canvas在面向中心的圆周围绘制多个矩形

时间:2015-04-16 02:58:24

标签: javascript math canvas trigonometry angle

我正在寻找一种方法,以一个面向中心的角度围绕圆形绘制多个矩形。到目前为止我所拥有的,目前只是围绕一个方向的圆形绘制矩形,缺少朝向中心的角度倾斜 -

https://dl.dropboxusercontent.com/u/22052734/player/index.html

我想要的是矩形以一定角度倾斜,使得每个矩形在其指定位置面向圆心。 如何做到这一点?

1 个答案:

答案 0 :(得分:0)

三角学方法

要将线条设置为朝向中心的动画,您可以使用变换或三角函数数学。我个人认为在这种情况下数学更容易,所以这里是一个例子。

有关如何使用变换的示例,请参阅@ markE的答案(通常,变换在眼睛和代码中可以更容易)。

一些先决条件:

  • 我们知道画布的方向是0°角指向右边。如果你想以某种方式标记频率范围,这是必不可少的。
  • 我们需要计算从外半径到中心(内半径)的线的长度
  • 我们需要根据角度计算线的终点。

一个简单的解决方案可以是创建一个函数来计算某个(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分析仪中提供数据。

注意:由于所有线路都指向中心,因此您将拥有一个拥挤的中心区域。在确定线宽和内半径以及要使用的箱数时,需要注意的事项。

演示示例

对于示例,我将使用一些随机数据作为“FFT”并绘制64个区间。

// 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>