【问题标题】:HTML5 canvas : counterclockwise arc with angle > 2 PIHTML5画布:角度> 2 PI的逆时针弧
【发布时间】:2018-10-16 20:22:06
【问题描述】:

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

看看这段代码sn-p,在第一行我画了“顺时针”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;"/>

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    根据to specs

    如果逆时针为假且endAngle-startAngle等于或大于2π,或者,如果逆时针为真且 startAngle-endAngle 等于或大于 2π,那么弧就是这个椭圆的整个圆周,并且 startAngle 处的点沿着这个圆的圆周,从椭圆的顺时针测量弧度半长轴,既是起点又是终点。

    否则,沿着这个圆的圆周在 startAngleendAngle 处的点(以椭圆的半长轴顺时针测量的弧度为单位)是分别是起点和终点,弧是从起点到终点沿着这个椭圆的圆周的路径,如果逆时针为真,则逆时针方向,否则顺时针方向。由于点在椭圆上,而不是简单地从零开始的角度,弧永远不会覆盖大于 2π 弧度的角度。

    输入可能更清晰的伪代码:

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

    在你的例子中,startAngle = 0endAngle = 3πanticlowkwise = true,如果我们运行上面的算法,我们会结束在其他情况下,(0 - 3π 和 endAngle 现在是 (3π % 2π = 1π)

    我们可以通过交换 startAngleendAngle 来实现没有逆时针标志的相同输出:

    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>

    【讨论】:

      【解决方案2】:

      逆时针方向,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;"/>

      【讨论】:

      • 如果我正确理解你的答案,就像在逆时针中所有角度都像模(2*PI)但不是顺时针...所以我应该去 end 以顺时针顺序开始 而不是 以逆时针顺序开始到结束 以避免这种行为。但这种行为是路径的预期行为,还是副作用?
      • 我认为你很聪明。我添加了一个动画演示来展示发生了什么。请看一看。
      • @enxaneta 你似乎对发生的事情并不完全了解......看看我的回答:重要的是开始角度和结束角度或倒角之间的差异。所以如果动画让你更清楚,jsfiddle.net/qL0tdj7a。在那里你会看到值确实是调制的
      猜你喜欢
      • 2011-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-24
      • 1970-01-01
      • 2023-03-22
      • 2018-04-04
      • 1970-01-01
      相关资源
      最近更新 更多