HTML5 canvas:角度大于2 PI的逆时针弧

时间:2018-10-16 10:10:24

标签: javascript html5 canvas

我试图弄清楚为什么在顺时针和逆时针绘制圆弧时,角度> 2 PI不能给出相同的结果。

查看此代码段,在第一行上我按顺时针方向绘制3个红色弧,起始角度为0,终止角度为PI,2 * PI和3 * PI。 然后我用相同的参数绘制“逆时针” 3个蓝色弧。

第三个结果让我感到困惑……有人可以向我解释吗?

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

// CLOCKWISE, angle = PI
ctx.beginPath();
ctx.arc(50, 50, 40, 0, Math.PI, false);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "red";
ctx.fill();

// CLOCKWISE, angle = 2 PI
ctx.beginPath();
ctx.arc(150, 50, 40, 0, 2 * Math.PI, false);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "red";
ctx.fill();

// CLOCKWISE, angle = 3 PI
ctx.beginPath();
ctx.arc(250, 50, 40, 0, 3 * Math.PI, false);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "red";
ctx.fill();

// COUNTERCLOCKWISE, angle = PI
ctx.beginPath();
ctx.arc(50, 150, 40, 0, Math.PI, true);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();

// COUNTERCLOCKWISE, angle = 2 PI
ctx.beginPath();
ctx.arc(150, 150, 40, 0, 2 * Math.PI, true);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();

// COUNTERCLOCKWISE, angle = 3 PI
ctx.beginPath();
ctx.arc(250, 150, 40, 0, 3 * Math.PI, true);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();
<canvas id="myCanvas" width="350" height="250" style="border:1px solid #d3d3d3;"/>

2 个答案:

答案 0 :(得分:0)

当您转到COUNTERCLOCKWISE时,在0之后为2PI。您应该尝试以下方法:

// COUNTERCLOCKWISE, angle = 3 PI
ctx.beginPath();
ctx.arc(250, 150, 40, 2 * Math.PI, 0, true);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();
更新:

在OP发表评论后,我添加了一个动画演示:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
let delta = 0;

function Draw(){
 requestAnimationFrame(Draw) 
 delta+= .01; 
ctx.clearRect(0,0,c.width,c.height)

// CLOCKWISE: animating the end point
ctx.beginPath();
ctx.arc(50, 50, 40, 0, delta, false);
ctx.closePath();
ctx.stroke();


// CONTERCLOCKWISE, animating the start point
ctx.beginPath();
ctx.arc(150, 50, 40, 0,-delta, true);
ctx.closePath();
ctx.stroke();

}

Draw()
<canvas id="myCanvas" width="350" height="250" style="border:1px solid #d3d3d3;"/>

答案 1 :(得分:0)

根据to specs

  

如果逆时针为false并且 endAngle-startAngle 等于或大于2π,或者逆时针为true且 startAngle-endAngle 等于或大于2π,则圆弧是此椭圆的整个圆周,并且 startAngle 处沿该圆的圆周的点(从椭圆的弧度开始以弧度为单位)半长轴既充当起点又充当终点。

     

否则,沿着椭圆的半长轴顺时针以弧度为单位,沿着该圆的圆周在 startAngle endAngle 处的点是分别是起点和终点,而圆弧是沿着该椭圆的圆周从起点到终点的路径,如果为逆时针,则为逆时针,否则为顺时针。由于这些点在椭圆上,而不是简单地从零开始的角度,因此弧永远不能覆盖大于2π弧度的角度。

输入更清晰的伪代码:

if(
  (anticlockwise === false && (endAngle - startAngle) >= 2π) ||
  (anticlockwise === true  && (startAngle - endAngle) >= 2π)
  ) {
  arc_circumference = 2π;
}
else {
  startAngle = startAngle % 2π;
  endAngle = endAngle % 2π;
}

在您的情况下, startAngle = 0 endAngle =3π anticlowkwise = true ,如果运行上述算法,则最终在其他情况下,(0-3π<2π) endAngle 现在是(3π%2π=1π)

通过交换 startAngle endAngle ,我们可以在没有逆时针标志的情况下实现相同的输出:

var ctx = canvas.getContext("2d");
// COUNTERCLOCKWISE, angle = -3 PI (from OP)
ctx.beginPath();
ctx.arc(50, 150, 40, 0, 3 * Math.PI, true);
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();

// CLOCKWISE, angle = -3 PI
ctx.beginPath();
ctx.arc(50, 50, 40, 3 * Math.PI, 0);
ctx.stroke();
ctx.fillStyle = "red";
ctx.fill();
<canvas id="canvas"></canvas>