画布:如何围绕指定的紫色点从指定的橙色点到指定的绿色点绘制螺旋

时间:2019-03-18 09:19:55

标签: javascript canvas html5-canvas

我正在尝试绘制一个从“起点”到“终点”的螺旋线。该螺旋线还具有给定的中心点,因此可以围绕该中心点绘制螺旋线。 我无法使其工作,以某种方式数学是完全错误的。 有关如何解决此问题的任何建议?

The jsfiddle of the code I tried is here.

<!DOCTYPE HTML>
<html>
<body>
  <canvas id="myCanvas" width="800" height="600" style="border:1px solid #c3c3c3;"></canvas>

  <script type="text/javascript">
    var c = document.getElementById("myCanvas");
    var cxt = c.getContext("2d");

    //center of the spiral coords:
    var centerX = 400;
    var centerY = 300;

    //draw the center of spiral point:
    drawCirc(centerX, centerY, 10, '#6f0c4f');

    var gap = 8;
    var STEPS_PER_ROTATION = 50;
    var rotations = 4;
    var increment = rotations * Math.PI / STEPS_PER_ROTATION;
    var theta = increment;

    //start point:
    var startX = 500;
    var startY = 380;

    //end point:
    var endX = 600
    var endY = 300;

    //draw the start and end points as small circles:
    drawCirc(startX, startY, 6, '#FF0000');
    drawCirc(endX, endY, 6, '#00FF00');

    //trying to calculate theta start position:
    theta = Math.abs(((centerX - startX) / Math.cos(theta)) / gap);

    var ind = 0;
    while (theta < rotations * Math.PI * 2) {
      var newX = centerX + theta * Math.cos(theta) * gap;
      var newY = centerY + theta * Math.sin(theta) * gap;
      var ukwObj = { x: newX, y: newY };
      if (ind == 0) {
        //draw start point with differnt color to differentiate
        drawCirc(newX, newY, 2, 'orange');
      } else {
        drawCirc(newX, newY);
      }
      ind++;
      theta = theta + increment;
    }

    function drawCirc(x, y, radius = 2, stroke = '#000000') {
      cxt.beginPath();
      cxt.arc(x, y, radius, 0, 2 * Math.PI);
      cxt.strokeStyle = stroke;
      cxt.stroke();
      cxt.fillStyle = stroke;
      cxt.fill();
    }

    cxt.stroke(); // draw the spiral
  </script>
</body>
</html>

1 个答案:

答案 0 :(得分:2)

画圆的原理是:
给定一个中心x,y,半径为r,我们可以通过如下方法计算属于圆的点的坐标:px = x + r * Math.cos(angle)py = y + r * Math.sin(angle),当角度从0到{ {1}}。
如果2* Math.PI在角度变化时增大,我们将得到一个向外的螺旋形(从角度0到角度2 * PI等于0)。

对于眼前的问题,我们需要以极坐标(距离,角度)计算螺旋的开始和结束位置。
因此,我们需要计算起始角度,起始距离,终止角度和终止距离,并通过逐渐增加角度和距离来绘制每个点。

最初的theta计算是错误的,我已经更改了。

然后我需要计算中心到起点之间的起点距离以及中心到终点之间的终点距离。

在旋转过程中,进度从起点到终点。

总角度距离应为r,我将totalTheta = numberOfRotation * 2 * Math.PI + (endAngle - startAngle)替换为rotations * Math.PI * 2

只是为了好玩并演示它可以在任何初始条件下工作,我对开始位置,结束位置和转数进行了随机分配。

我还在每次迭代中减小了角度增量,以使每个点之间的距离看起来更均匀,但是您可以添加注释以保持恒定的角速度。

下面的解决方案将随机选择一个橙色的点,一个绿色的点,若干匝以完成螺旋,并将围绕固定的紫色点绘制螺旋。

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

    //center of the spiral coords:
    var centerX = 200;
    var centerY = 150;

    //draw the center of spiral point:
    drawCirc(centerX, centerY, 10, '#6f0c4f');

    var gap = 8;
    var STEPS_PER_ROTATION = 50;
    var rotations = 1 + parseInt(Math.random() * 5, 10);
    var increment = rotations * Math.PI / STEPS_PER_ROTATION;
    var theta = increment;
    var dist = 0;

    //start point:
    var startX = centerX + (Math.random() * 150 - 75);
    var startY = centerY + (Math.random() * 150 - 75);
    var startAngleOffset = startX > centerX ? (startY > centerY ? 0 : 0) : (startY > centerY ? Math.PI : Math.PI);
    var startAngleSign = startX > centerX ? (startY > centerY ? 1 : -1) : (startY > centerY ? -1 : 1);

    //end point:
    var endX = centerX + (Math.random() * 150 - 75);
    var endY = centerY + (Math.random() * 150 - 75);
    var endAngleOffset = endX > centerX ? (endY > centerY ? 0 : 0) : (endY > centerY ? Math.PI : Math.PI);
    var endAngleSign = endX > centerX ? (endY > centerY ? 1 : -1) : (endY > centerY ? -1 : 1);

    //draw the start and end points as small circles:
    drawCirc(startX, startY, 6, '#FF0000');
    drawCirc(endX, endY, 6, '#00FF00');

    var startTheta = theta = startAngleOffset + startAngleSign * Math.atan(Math.abs(startY - centerY)/Math.abs(startX - centerX));

    var endTheta = endAngleOffset + endAngleSign * Math.atan(Math.abs(endY - centerY)/Math.abs(endX - centerX));

    var totalTheta = rotations * 2 * Math.PI + (endTheta - startTheta)
    dist = Math.sqrt(Math.pow(startY - centerY, 2) + Math.pow(startX - centerX, 2));

    finalDist = Math.sqrt(Math.pow(endY - centerY, 2) + Math.pow(endX - centerX, 2));
    var ind = 0;
    while (theta -startTheta < totalTheta) {
      var currentDist = (dist + ((finalDist - dist)* ((theta - startTheta) / (totalTheta))));
      var newX = centerX + currentDist * Math.cos(theta);
      var newY = centerY + currentDist * Math.sin(theta);
      var ukwObj = { x: newX, y: newY };
      if (ind == 0) {
        //draw start point with differnt color to differentiate
        drawCirc(newX, newY, 2, 'orange');
      } else {
        drawCirc(newX, newY);
      }
      ind++;
      theta = theta + increment;
      // decrement increment to make the space between points look more regular
      increment = Math.max(0.01, increment - 0.00096);
    }

    function drawCirc(x, y, radius = 2, stroke = '#000000') {
      cxt.beginPath();
      cxt.arc(x, y, radius, 0, 2 * Math.PI);
      cxt.strokeStyle = stroke;
      cxt.stroke();
      cxt.fillStyle = stroke;
      cxt.fill();
    }

    cxt.stroke(); // draw the spiral