我试图弄清楚为什么在顺时针和逆时针绘制圆弧时,角度> 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;"/>
答案 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>