首页 文章

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

提问于
浏览
2

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

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

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

我希望它以静态半径(比如20)切入弧的中心,无论鼠标与Origin有多远 .

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

  • 如果鼠标位于3点钟位置,则Arc看起来像")"

  • 如果鼠标位于9点钟位置,则Arc看起来像"("

  • 如果鼠标位于12点钟位置,如果旋转90°,则Arc看起来像"("

  • 如果鼠标位于6点位置,如果旋转270°,则Arc看起来像"("

  • 等......

鼠标位于Arc的顶部 .

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

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

Edit :一个非常差的Photoshop渲染
Curves

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

2 回答

  • 0

    The simplest way is to adjust the starting & ending angles of the arc command.

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

    提示:如果您希望您的花瓣不那么圆,更弯曲,您可以使用 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>
    

    [ Addition based on more information ]

    是的,我想你已经拥有了!

    从鼠标位置 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 .

    所以最后你的“指向”鼠标的小角度变为:

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

    干杯!

  • 2

    Adding 因为:

    $(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>
    

相关问题