在HTML5画布上围绕其中一个点旋转星形

时间:2014-10-22 21:17:52

标签: javascript html5 canvas

我正在将flash动画转换为javascript / html5。我的动画看起来非常相似,但是,我正在努力完成我在html5画布上绘制的星星上的旋转。我使用的是该网站代码的变体:http://programmingthomas.wordpress.com/2012/05/16/drawing-stars-with-html5-canvas/作为参考,我已粘贴下面的相关代码。

function star(ctx, x, y, r, p, m)
{
    ctx.save();
    ctx.beginPath();
    ctx.translate(x, y);
    ctx.moveTo(0,0-r);
    for (var i = 0; i < p; i++)
    {
        ctx.rotate(Math.PI / p);
        ctx.lineTo(0, 0 - (r*m));
        ctx.rotate(Math.PI / p);
        ctx.lineTo(0, 0 - r);
    }
    ctx.fill();
    ctx.restore();
}

我已经想出如何通过插入ctx.rotate()来调整围绕其中心的星星,如下所示:

    ...beginPath();
    ctx.translate(x, y);
    ctx.rotate(radianOffset);
    ctx.moveTo(0,0-r);
    for (var i = 0...

是否有人有任何线索如何围绕其中一个点旋转恒星?我一直在阅读有关旋转功能的内容,但无法弄清楚如何使其与星形函数一起使用。

1 个答案:

答案 0 :(得分:1)

只需转换到您想要旋转的点,旋转然后平移回来继续绘制星星。

然而,使用你正在使用的功能可能会变得比仅仅更复杂,因为你需要星点“尖峰”的点的绝对位置。

这是我写的一个替代实现来处理这个问题。在这里,我们调用一个函数来获取带有点的数组,以便构建一个星。

然后我们可以使用该点阵列来选择旋转的枢轴点以及渲染星本身。该函数如下所示:

// cx = center x
// cy = center y
// r1 = outer radius
// r2 = inner radius
// spikes = number of star "spikes"
function getStarPoints(cx, cy, r1, r2, spikes) {

  var i = 0,
      deltaAngle = (2 * Math.PI) / spikes,
      x, y,
      points = [];

  // calc rest of points
  for (; i < spikes; i++) {
    points.push(
      {
        x: cx + r2 * Math.cos(deltaAngle * i),               // calc inner point
        y: cy + r2 * Math.sin(deltaAngle * i)
      }, {
        x: cx + r1 * Math.cos(deltaAngle * i + deltaAngle * 0.5), // outer point
        y: cy + r1 * Math.sin(deltaAngle * i + deltaAngle * 0.5)
      }
    );
  }

  return points;
}

现在我们需要做的就是从数组中选取一个点作为点对象,并将其用于旋转中心,这里点索引1:

ctx.translate(points[1].x, points[1].y);   // translate to origin for rotation
ctx.rotate(angle);                         // rotate angle (radians)
ctx.translate(-points[1].x, -points[1].y); // translate back

然后渲染星星

ctx.beginPath();                           // start a new path
ctx.moveTo(points[0].x, points[0].y);      // starting point
for(var i = 1, p; p = points[i++];)
    ctx.lineTo(p.x, p.y);                  // add points to path
ctx.fill();                                // close and fill

注意:如果你想抚摸星星,你需要在抚摸之前使用closePath()

就是这样。请参阅下面的代码段,了解此动画版本以及完整来源。

性能方面,这将更快,我们只计算一次星,并且在这种情况下,我们不使用动画的保存/恢复(这是一些成本高昂的操作)。

希望这有帮助!

var ctx = document.getElementById('canvas').getContext('2d'),
    points = [],
    angleStep = 0.025;

ctx.fillStyle = 'orange';

// draw first star at angle 0 and get point array
points = getStarPoints(150, 90, 80, 40, 5);

// now that we know the point for each part, lets animate
loop();

function loop() {

  // clear canvas
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

  // rotate around one of the points (or anywhere if wanted..)
  ctx.translate(points[1].x, points[1].y);
  ctx.rotate(angleStep);
  ctx.translate(-points[1].x, -points[1].y);

  // draw start
  ctx.beginPath();
  ctx.moveTo(points[0].x, points[0].y);
  for(var i = 1, p; p = points[i++];) ctx.lineTo(p.x, p.y);
  ctx.fill();

  requestAnimationFrame(loop);
}

// Star by Ken Fyrstenberg/CC3.0-Attr
// cx = center x
// cy = center y
// r1 = outer radius
// r2 = inner radius
// spikes = number of star "spikes"
function getStarPoints(cx, cy, r1, r2, spikes) {

  var i = 0,
      deltaAngle = (2 * Math.PI) / spikes,
      x, y,
      points = [];

  // calc rest of points
  for (; i < spikes; i++) {
    points.push(
      {
        x: cx + r2 * Math.cos(deltaAngle * i),
        y: cy + r2 * Math.sin(deltaAngle * i)
      }, {
        x: cx + r1 * Math.cos(deltaAngle * i + deltaAngle * 0.5),
        y: cy + r1 * Math.sin(deltaAngle * i + deltaAngle * 0.5)
      }
    );
  }

  return points;
}
<canvas id="canvas" width=350 height=180></canvas>