如何创建始终打开到固定点的圆弧

How to Create an Arc that always opens to a fixed point

我正在尝试在 canvas 上创建 向日葵效果,带有弧线,但我的几何技能生疏了。

首先,我在 canvas、Origin (X1, Y1) 中间某处创建了一个原点 然后我创建获取鼠标位置 Mp (Xm, Ym)

现在如果我从 OriginMp 做一条假想线,那么 Mp 应该是用一个新的较小原点平分圆弧的点,该原点位于 Origin 的方向,这将定义具有静态半径(比如 20)的圆弧。所有三个点 OriginMp 和较小的 Radius 应该形成一条直线。

我希望它以静态半径(比如 20)穿过圆弧的中心,而不管鼠标离原点有多远。

所以,如果你想象一个时钟。如果手连接的中间部分是Origin

并且鼠标位于该弧形的顶部。

对于我的问题,具体来说,与其说是如何获得积分、鼠标事件或其他任何问题,不如说是假设我有 {X1,Y1} 和 {Xm,Ym},那么制作弧线所需的数学是什么如上所述?

或者对于 JS/jQuery 专家,arc() 参数?

编辑:一个非常糟糕的 photoshop 渲染

右下角添加了一个鼠标,一般显示绘制 arc/curve 时鼠标指针所在的位置。

最简单的方法就是调整圆弧指令的起止角度

你可以画一系列弧线来形成你的花。

提示:如果你想让你的花瓣不那么圆,更弯曲,你可以使用 quadraticCurveTo 而不是弧线来绘制花瓣的外侧。

祝你项目顺利!

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var cx=150;
var cy=150;
var radius=50;
var PI=Math.PI;
var startAngle=0-PI/8;
var sweepAngle=PI/4;
var nextTime=0;
var delay=250;

requestAnimationFrame(animate);

function draw(){

  ctx.clearRect(0,0,cw,ch);

  ctx.beginPath();
  ctx.arc(cx,cy,5,0,PI*2);
  ctx.closePath();
  ctx.fill();

  ctx.beginPath();
  ctx.arc(cx,cy,radius,startAngle,startAngle+sweepAngle);
  ctx.stroke();

}

function animate(time){
  requestAnimationFrame(animate);
  if(time>nextTime){
    draw();
    startAngle+=PI*2/30;
    nextTime+=delay;
  }
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>

[根据更多信息添加]

是的,我想你明白了!

从鼠标位置开始mcx,mcy

定义小圆心与鼠标位置的夹角radianAngle

定义小中心点与鼠标中心点的距离radius

计算小圆的圆心:

var scx = mcx + radius*Math.cos(radianAngle);
var scy = mcy + radius*Math.sin(radianAngle);

定义小圆的半径smallRadius

在较小的圆弧上定义您想要的总扫描角度 sweepAngle

定义小圆弧的起点和终点角度。这实际上很容易,因为您希望鼠标点处的小圆弧为 "point"。提示:小圆弧的中心必须始终位于 radianAngle 的中点。因此,startingAngle = ( radianAngle - sweepAngle/2.

所以最后你的 "points" 与鼠标的小角度变成了:

ctx.arc( scx,scy, smallRadius, startingAngle, startingAngle+sweepAngle );

干杯!

添加只是因为:

$(document).ready(function() {
      var canvas = $('#canvas');

      function getPosition(mouseEvent) {
        var x, y;
        x = mouseEvent.clientX;
        y = mouseEvent.clientY;
        return {
          X: x - canvas.offset().left,
          Y: y - canvas.offset().top
        };
      }

      $('#canvas').mousemove(function(e) {
        var origin = {
          x: 325,
          y: 100
        };
        var posit = getPosition(e)
        var degrees = Math.PI /
          180;
        var plotR = {
          X: 0,
          Y: 0
        };
        var radius = 15;
        var curveDeg = 65;
        var context = $('#canvas').get(0).getContext('2d');

        if (posit.X >= origin.x && posit.Y <= origin.y) {
          quadrant = 1;
        } else if (posit.X >= origin.x && posit.Y >= origin.y) {
          quadrant = 2;
        } else if (posit.X < origin.x && posit.Y >= origin.y) {
          quadrant = 3;
        } else {
          quadrant = 4;
        }

        deltaY = posit.Y - origin.y;
        deltaX = posit.X - origin.x;

        if (deltaX == 0) {
          distance = deltaY;
          plotR.X = origin.x;
          switch (quadrant) {
            case 2:
            case 3:
              plotR.Y = posit.Y - radius;
              break;
            case 1:
            case 4:
            default:
              plotR.Y = posit.Y + radius;
              break;
          }
        } else {
          distance = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
          slope = deltaY / deltaX;
          delta = radius / (Math.sqrt(1 + Math.pow(slope, 2)));

          switch (quadrant) {
            case 1:
              plotR.Y = posit.Y - slope * delta;
              plotR.X = posit.X - delta;
              break;
            case 2:
              plotR.Y = posit.Y - slope * delta;
              plotR.X = posit.X - delta;
              break;
            case 3:
              plotR.Y = posit.Y + slope * delta;
              plotR.X = posit.X + delta;

              break;
            case 4:
            default:
              plotR.Y = posit.Y + slope * delta;
              plotR.X = posit.X + delta;
              break;
          }
        }
        startAngle = Math.acos(deltaX / distance);
        if (quadrant == 1 || quadrant == 4) startAngle = -startAngle;


        context.clearRect(0, 0, 900, 400);

        // Draw Origin Point for reference, but not for production
        context.beginPath();
        context.lineWidth = 1;
        context.fillStyle = "#0000FF";
        context.strokeStyle = "#0000FF";
        context.arc(origin.x, origin.y, 3, 0, 2 * Math.PI, true);
        context.fill();

        // Drawn Calculated Origin point offset from Mouse in the direction of Origin Point
        context.beginPath();
        context.lineWidth = 1;
        context.fillStyle = "#00FF00";
        context.strokeStyle = "#00FF00";
        context.arc(plotR.X, plotR.Y, 3, 0, 2 * Math.PI, true);
        context.fill();

        // Draw 'Sunflower' Curve
        context.beginPath();
        context.lineCap = 'round';
        context.lineWidth = 3;
        context.strokeStyle = "#FF0000";
        context.arc(plotR.X, plotR.Y, radius, startAngle - (curveDeg * degrees / 2), startAngle + (curveDeg * degrees / 2), false);

        context.stroke();
        return;
      });
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="650" height="200" style=" border: 1px #000 solid"></canvas>