如何在不旋转整个画布的情况下旋转三角形

How to rotate a triangle without rotating the entire canvas?

本文关键字:旋转 情况下 三角形      更新时间:2023-09-26

我是刚开始和<canvas>一起工作的,在数学方面很糟糕。我正在画布上绘制一个简单的等边三角形,其中包含从其他人那里借用的代码(不要讨厌我):

drawTriangle(PosX, PosY, SideLength, Orientation) {
    context.beginPath();
    var sides = 3;
    var a = ((Math.PI * 2) / sides);
    context.moveTo(PosX + SideLength, PosY);
    for (var i = 1; i < sides + 1; i++) {
        context.lineTo(PosX + SideLength * Math.cos(a*i), PosY + SideLength * Math.sin(a*i));
    }
    context.closePath();
    return true;
}

该函数只知道三角形的中心坐标和指向它的方向,没有别的。

它目前成功地绘制了三角形,但"指向"东。

如何使用 Orientation 参数(度)旋转三角形,而无需像其他答案建议的那样旋转整个画布?

下面是一个绘制任何常规多边形和指定角度的函数:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var sideCount=3;
var size=40;
var centerX=50;
var centerY=50;
var strokeWidth=4;
var strokeColor='purple';
var fillColor='skyblue';
var rotationDegrees=0;
var rotationIncrement=1;
var nextTime=0;
var delay=1000/60*1;
requestAnimationFrame(animate);
function animate(time){
    if(time<nextTime){requestAnimationFrame(animate);return;}
    nextTime=time+delay;
    ctx.clearRect(0,0,cw,ch);
    drawPolygon(centerX,centerY,sideCount,size,strokeWidth,strokeColor,fillColor,rotationDegrees);
    rotationDegrees+=rotationIncrement;
    requestAnimationFrame(animate);
}
function drawPolygon(centerX,centerY,sideCount,size,strokeWidth,strokeColor,fillColor,rotationDegrees){
    var radians=rotationDegrees*Math.PI/180;
    ctx.translate(centerX,centerY);
    ctx.rotate(radians);
    ctx.beginPath();
    ctx.moveTo (size * Math.cos(0), size * Math.sin(0));          
    for (var i = 1; i <= sideCount;i += 1) {
        ctx.lineTo (size * Math.cos(i * 2 * Math.PI / sideCount), size * Math.sin(i * 2 * Math.PI / sideCount));
    }
    ctx.closePath();
    ctx.fillStyle=fillColor;
    ctx.strokeStyle = strokeColor;
    ctx.lineWidth = strokeWidth;
    ctx.stroke();
    ctx.fill();
    ctx.rotate(-radians);
    ctx.translate(-centerX,-centerY);    }
<canvas id="canvas" width=512 height=512></canvas>
<canvas id="canvas" width=512 height=512></canvas>

请看这把小提琴。您可以将方向作为可选参数发送。它接受"东"、"西"、"北"、"南"。请验证。

'函数 drawTriangle(PosX, PosY, SideLength, Orientation) {

if (!Orientation) {
   Orientation = 'east';
}
context.beginPath();
var sides = 3;
var a = ((Math.PI * 2) / sides);
// the components have negative contributions
if (Orientation === 'west' || Orientation === 'north') {
    SideLength *= -1;
}
if (Orientation === 'east' || Orientation === 'west') {
    context.moveTo(PosX + SideLength, PosY);
    for (var i = 1; i < sides + 1; i++) {
        context.lineTo(PosX + SideLength * Math.cos(a*i), PosY + SideLength * Math.sin(a*i));
    }
}
else if (Orientation === 'south' || Orientation === 'north') {
    context.moveTo(PosY, PosX + SideLength);
    for (var i = 1; i < sides + 1; i++) {
        context.lineTo(PosY + SideLength * Math.sin(a*i), PosX + SideLength * Math.cos(a*i));
    }
}
context.stroke();
context.closePath();

}'

要仅旋转特定形状而不旋转整个画布 - 您应该手动旋转它所包含的每个点,然后用旋转的点绘制它。

检查我创建的这个例子,它不使用任何canvas API函数进行旋转或平移,也绘制任何规则多边形。

var ctx = document.getElementById("cnv").getContext('2d');
var id = 0;
var Point2d = function(x, y) {
  this.x = x || 0;
  this.y = y || 0;
}
Point2d.prototype.set = function(x, y) { 
  this.x = x;
  this.y = y;
};
Point2d.prototype.translate = function(p) { 
  this.x += p.x;
  this.y += p.y;
  return this;
};
//rotation around origin
Point2d.prototype.rotate = function(phi) {
  this.set(
    this.x*Math.cos(phi) - this.y*Math.sin(phi),
    this.x*Math.sin(phi) + this.y*Math.cos(phi)
  );
  return this;
};
function getRegularPolygonPoints(center, numSides, sideLength) {
  var points = [];
  var alpha = 2*Math.PI / numSides;  
  for (var i = 0; i < numSides; i++) {
    points.push(new Point2d( 
      center.x + sideLength*Math.cos(alpha*i),
      center.y + sideLength*Math.sin(alpha*i))
    )
  }  
  return points;
}
function drawPolygon(points) {
  ctx.beginPath();
  ctx.moveTo(points[0].x, points[0].y); 
  for (var i = 1; i < points.length; i++) {
    ctx.lineTo(points[i].x, points[i].y);
  }
  ctx.lineTo(points[0].x, points[0].y);//  close the shape
  ctx.lineWidth = 1;
  ctx.fillStyle = "#899";
  ctx.fill();
  ctx.stroke();
  ctx.closePath();
}
function rotatePolygon(polygonPoints, phi, pointAround) {
  var pointAroundInv= new Point2d(-pointAround.x, -pointAround.y);
  
  for (var i = 0; i < polygonPoints.length; i++) {
    polygonPoints[i].translate(pointAroundInv);//  translate to origin
    polygonPoints[i].rotate(phi);//  rotate
    polygonPoints[i].translate(pointAround);// translate back to it's original position
  }
}
var center = new Point2d(250, 120);
var regPolPoints = getRegularPolygonPoints(center, 3, 50);
var currentFrame = (new Date).getTime();
var lastFrame = currentFrame;
var dt = 0;
var render = function() {
  ctx.clearRect(0, 0, 400, 400);
  currentFrame = (new Date).getTime();
  dt = currentFrame - lastFrame;
  lastFrame = currentFrame; 
  
  rotatePolygon(regPolPoints, -dt/600, center);
  drawPolygon(regPolPoints);
  id = requestAnimationFrame(render);
}
id = requestAnimationFrame(render);
<canvas id="cnv" width="400" height="400"></canvas>

这里的数学非常简单。我们正在从半径半径的圆中提取的等角点之间绘制直线(见下面的参数)。另外,我们应该记住,边长不是多边形的实际边长。我简化了初始代码并添加了图形旋转功能。结果函数和示例如下所示:

        /* here, radius means the radius of circle, inside of which polygon is drawn */
        function drawTriangle(context, PosX, PosY, radius, rotate) {
            context.beginPath();
            /* number of vertices for polygon */
            var sides = 3;
            /* angle between vertices of polygon */
            var a = ((Math.PI * 2) / sides);
            for (var i = 0; i < sides; i++) {
                context.lineTo(PosX + radius * Math.cos(a*i+rotate), PosY + radius * Math.sin(a*i+rotate));
            }
            context.closePath();
            context.stroke();
            return true;
        }
        var canvas = document.getElementById("demo")
        if (canvas.getContext) {
            var ctx = canvas.getContext('2d');
            var PosX = 50;
            var PosY = 50;
            var radius = 40;
            drawTriangle(ctx, PosX, PosY, radius, Math.PI / 4);
        }
canvas#demo
{
  border: thin solid green;
}
<canvas id="demo" width="200" height="200">
    This browser or document mode doesn't support canvas
</canvas>

旋转三角形

drawTriangle(PosX, PosY, SideLength, Orientation) {
    context.setTransform(1,0,0,1,PosX,PosY); // Set position
    context.rotate(Orientation);  // set rotation in radians
    context.beginPath();
    var sides = 3;
    var a = ((Math.PI * 2) / sides);
    context.moveTo(SideLength,0);
    for (var i = 1; i < sides + 1; i++) {
        context.lineTo(SideLength * Math.cos(a*i), SideLength * Math.sin(a*i));
    }
    context.closePath();
    context.fill()
    context.setTransform(1,0,0,1,0,0);// reset the transform
    return true;
}