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

时间:2015-01-08 17:06:50

标签: javascript jquery canvas geometry trigonometry

我正在尝试在画布上创建一个带有弧线的向日葵效果,并且我的几何技能已经生锈。

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

现在,如果我从原点 Mp 创建一条虚线,那么 Mp 应该是用新的更小的点将弧分成两半的点原点位于原点的方向,它将定义具有静态半径的弧(比如20)。所有三个点原点 Mp 和较小的半径应形成一条直线。

我希望它以静态半径(比如20)切穿弧的中心,无论鼠标离Origin有多近。

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

  • 如果鼠标位于3点位置,则Arc看起来像“)”
  • 如果鼠标位于9点位置,则Arc看起来像“(”
  • 如果鼠标位于12点钟位置,则Arc看起来像“(”如果旋转90°
  • 如果鼠标位于6点钟位置,则Arc看起来像“(”如果旋转270°
  • 等...

鼠标位于Arc的顶部。

对于我的问题,具体而言,并不是如何获得点数或鼠标事件或任何东西,而是假设我有{X1,Y1}和{Xm,Ym},如上所述制作弧所需的数学是什么以上?

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

编辑:一个非常差的Photoshop渲染 Curves

右下角添加了一个鼠标,通常显示鼠标指针在绘制圆弧/曲线时的位置。

2 个答案:

答案 0 :(得分:2)

最简单的方法是调整起始和放大弧命令的结束角度。

你可以绘制一系列圆弧来形成你的花朵。

提示:如果你想要你的花瓣不那么圆,更弯曲,你可以使用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>
&#13;
&#13;
&#13;

[根据更多信息添加]

是的,我认为你已经得到了它!

从鼠标位置mcx,mcy开始。

定义较小的圆心点与鼠标位置radianAngle的角度。

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

计算小圆的中心点:

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

定义较小圆圈smallRadius的半径。

在较小的弧sweepAngle上定义所需的总扫描角度。

定义起点&amp;在小圆圈上结束弧的角度。这实际上很简单,因为你希望小弧度指向&#34;指向&#34;在鼠标点。提示:小弧的中心必须始终位于radianAngle的中点。因此,startingAngle = ( radianAngle - sweepAngle/2

所以最后你的小角度&#34;指向&#34;鼠标变为:

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

干杯!

答案 1 :(得分:0)

添加仅仅因为:

&#13;
&#13;
$(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;
      });
    });
&#13;
<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>
&#13;
&#13;
&#13;