HTML画布上的旋转多边形

时间:2013-02-05 16:54:40

标签: javascript math canvas

我正在尝试在画布上旋转N边多边形,我遇到了坐标问题。形状似乎围绕着一个自身外部的原点旋转(我希望原点是形状的中心)。 任何提示都将非常感激。

var x = 50;
var y = 50;
var tranx;
var trany;

x -= tranx = x + shape.radius;
y -= trany = y + shape.radius;

elem.translate(tranx,trany);
elem.rotate(90 * radian);

var k = 0,
angle = 360/shape.sides;

elem.moveTo(x,y);

for (; k <shape.sides; k++) {
    elem.lineTo(x+=Math.cos( ( angle * k )* radian) * shape.radius, y+=Math.sin( ( angle * k )* radian) * shape.radius);
}

2 个答案:

答案 0 :(得分:1)

嗯,第一个解决方案,有点像黑客,将是以下内容:向形状对象添加参数rotation_angle。然后你的循环应该按以下方式改变:

k=0;
elem.moveTo(
     x+=Math.cos( ( angle * k +shape.rotation_angle)* radian) * shape.radius,
     y+=Math.sin( ( angle * k +shape.rotation_angle)* radian) * shape.radius);
for(k=1;k<shape.sides;k++){
     elem.lineTo(
          x+=Math.cos( ( angle * k +shape.rotation_angle)* radian) * shape.radius,
          y+=Math.sin( ( angle * k +shape.rotation_angle)* radian) * shape.radius);
}

第二种解决方案依赖于假设elem是画布上下文,多边形的中心应该在坐标(x,y)处。

然后我想,正确的顺序如下:

elem.translate(x,y); //Translate the origin to the center of polygon.
elem.rotate(rotation_angle); // Rotate the context around the origin
var k=0;
elem.moveTo(shape.radius,0);
for(k=1;k<shape.sides;k++){
   elem.lineTo(Math.cos(k*angle*radian)*shape.radius,
               Math.sin(k*angle*radian)*shape.radius);
}

答案 1 :(得分:0)

我整理了几个函数来旋转正多边形。第一步是生成一个完全与<canvas>分开的(x,y)坐标列表。重要的是要注意,要获得相移(最终会导致多边形旋转),您必须将旋转添加到余弦和正弦函数中的语句中:

Math.cos(rotation + (i * 2 * Math.PI / numberOfSides))
Math.sin(rotation + (i * 2 * Math.PI / numberOfSides))

这是一个生成具有正多边形的画布,并围绕其原点旋转多边形的工作示例:

&#13;
&#13;
var canvas = document.querySelector('canvas');
var polygon = {
  sides: 3,
  radius: 50,
  phase: 0
};

document.addEventListener('click', function(e) {
  switch (e.target.id) {
    case "-side":
      polygon.sides--;
      break;
    case "+side":
      polygon.sides++;
      break;
    case "-phase":
      polygon.phase -= Math.PI / 12;
      break;
    case "+phase":
      polygon.phase += Math.PI / 12;
      break;
  }

  drawPolygon(canvas, polygon.sides, polygon.radius, polygon.phase);
});

function generateCoordinates(centerX, centerY, numberOfSides, radius, rotation) {
  var coordinates = [];
  for (var i = 0; i < numberOfSides; i++) {
    coordinates.push({
      x: parseFloat((centerX + radius * Math.cos(rotation + (i * 2 * Math.PI / numberOfSides))).toFixed(4)),
      y: parseFloat((centerY + radius * Math.sin(rotation + (i * 2 * Math.PI / numberOfSides))).toFixed(4))
    })
  }
  return coordinates;
};

function drawPolygon(canvas, numberOfSides, radius, rotation) {
  var context = canvas.getContext('2d');
  canvas.height = radius * 2;
  canvas.width = radius * 2;

  var coordinates = generateCoordinates(radius, radius, numberOfSides, radius, rotation);

  context.strokeStyle = "black";
  context.beginPath();

  coordinates.forEach(function(coordinate, index) {
    if (index === 0) {
      context.moveTo(coordinate.x, coordinate.y);
    } else {
      context.lineTo(coordinate.x, coordinate.y);
    }
  });
  context.closePath();
  context.stroke();
}

drawPolygon(canvas, polygon.sides, polygon.radius, polygon.phase);
&#13;
<canvas></canvas>

<div>
  <button id="-side">fewer sides</button>
  <button id="+side">more sides</button>
</div>

<div>
  <button id="-phase">minus phase shift</button>
  <button id="+phase">plus phase shift</button>
</div>
&#13;
&#13;
&#13;