通过圆形缠结点以已知半径2D绘制圆弧以适合html画布中的角度

时间:2015-05-13 22:35:57

标签: javascript html5 canvas html5-canvas trigonometry

很难解释这个问题。但我会尽我所能。 首先我制作2行,一行包含一个起点和一个终点,如下所示

newData('senderName').val(); //not working
newData('$message_id/senderName').val(); //also not working("$message_id": {})

然后我在画布上绘制两条线,形成像这样的三角形的角落。

First drawn triangle corner

我现在将线条彼此远离,长度为Radius * 2,如下所示 Line move with radius * 2

那么我现在如何使用两个端点作为切线点来绘制弧,如下所示 Finale proudct

我需要使用arc还是使用arcto?如果是它的话;然后,我如何给它开始绘制和结束点,以便绘制它,如上图中的图像所示。感谢您的时间,任何输入都有帮助。对于问题的错误描述再次抱歉

  • 更新 - 似乎我没有完全解释我的问题。所以这里有一点点更新。使用这里给出的例子。我最终得到一个椭圆形圆圈。我试图获得的是一条线之间的圆圈。

2 个答案:

答案 0 :(得分:0)

给定2个在公共点相交的线段,可以使用立方贝塞尔曲线对它们应用圆角交点:

enter image description here

以下是......

  • 给定点p1和线段从p1延伸到p0(P10)和从p1延伸到p2(P12):

    var p0={x:50,y:50};
    var p1={x:100,y:150};
    var p2={x:250,y:100};
    
  • 计算P10&的点数。 P12是从公共点(p1)回到各自起点(p0& p2)的指定百分比:

    var lerp=function(a,b,x){ return(a+x*(b-a)); };
    var dx,dy,length;
    var offsetPct=0.15;
    
    // calc a point on P10 that is 15% of the way from p1 to p0
    dx=p1.x-p0.x;
    dy=p1.y-p0.y;
    p00={ x:lerp(p1.x,p0.x,offsetPct), y:lerp(p1.y,p0.y,offsetPct) }
    
    // calc a point on P12 that is 15% of the way from p1 to p2
    dx=p1.x-p2.x;
    dy=p1.y-p2.y;
    p22={ x:lerp(p1.x,p2.x,offsetPct), y:lerp(p1.y,p2.y,offsetPct) }
    
  • 然后,您可以使用缩短的线段和三次贝塞尔曲线绘制圆角交点:

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");

var p0={x:50,y:50};
var p1={x:100,y:150};
var p2={x:150,y:50};


roundedIntersection(p0,p1,p2,0.15);


function roundedIntersection(p0,p1,p2,offsetPct){

  var lerp=function(a,b,x){ return(a+x*(b-a)); };
  var dx,dy,length;
  dx=p1.x-p0.x;
  dy=p1.y-p0.y;
  p00={ x:lerp(p1.x,p0.x,offsetPct), y:lerp(p1.y,p0.y,offsetPct) }
  dx=p1.x-p2.x;
  dy=p1.y-p2.y;
  p22={ x:lerp(p1.x,p2.x,offsetPct), y:lerp(p1.y,p2.y,offsetPct) }

  ctx.beginPath();
  ctx.moveTo(p0.x,p0.y);
  ctx.lineTo(p00.x,p00.y);
  ctx.bezierCurveTo( p1.x,p1.y,  p1.x,p1.y  ,p22.x,p22.y);
  ctx.lineTo(p2.x,p2.y);
  ctx.stroke();

  dot(p0.x,p0.y);
  dot(p1.x,p1.y);
  dot(p2.x,p2.y);
  dot(p00.x,p00.y);
  dot(p22.x,p22.y);

  function dot(x,y){
    ctx.beginPath();
    ctx.arc(x,y,2,0,Math.PI*2);
    ctx.closePath();
    ctx.fill();
  }

}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>

答案 1 :(得分:0)

是的,您可以使用arcTo()

  • 使用moveTo()
  • 设置第一行开始点
  • 然后两行之间的交叉点点作为第一对
  • 然后是第二行的结束点(你称之为&#34;起点第2行和第34行;)最后一对。
  • 提供半径
  • 要实际绘制最后一行(它仅用于arcTo()的计算),请为弧中的最后一个点添加lineTo(),描边/填充。

如果你想分开但不知道交叉点,你必须manually calculate(见那个答案中的getIntersection()),首先插入超出原始长度的线。

&#13;
&#13;
var ctx = document.querySelector("canvas").getContext("2d");

ctx.moveTo(0, 0);                 // start point
ctx.arcTo(50, 150, 100, 0, 20);   // intersection, outpoint, radius
ctx.lineTo(100, 0);               // line from arc-end to outpoint

ctx.translate(130, 0);
ctx.moveTo(0, 0);                 // start point
ctx.arcTo(50, 150, 80, 50, 8);   // intersection, outpoint, radius
ctx.lineTo(80, 50);               // line from arc-end to outpoint

ctx.stroke();
&#13;
<canvas></canvas>
&#13;
&#13;
&#13;

如果在不知道交叉点的情况下将它们移开,可以使用以下方法扩展线条以找到交点:

function extendLine(line, scale) {
  var sx = line.startPoint.x,
      sy = line.startPoint.y,
      ex = line.endPoint.x,
      ey = line.endPoint.y;

   return {
     startPoint: {x: sx, y: sy},
     endPoint: {
       x: sx + (ex - sx) * scale,
       y: sy + (ey - sy) * scale
     }
   }
}

比例可能是一个荒谬的值,因为我们需要确保在非常陡峭的角度线条会在某处交叉。它不会影响计算速度。

然后使用两条线(确保第二条线从第一条线的终点继续,这意味着您可能必须反转坐标 - 如果您想要动态执行此操作,则可以测量第二行中每个点到第一行终点的距离,最短距离首先作为startPoint):

执行步骤将是:

var line1 = ...,
    line2 = ...,
    line1tmp = extendLine(line1, 10000),
    line2tmp = extendLine(line2, 10000),
    ipoint = getIntersection(line1, line2); // see link above

// define the line + arcTo
ctx.moveTo(line1.startPoint.x, line1.startPoint.y);
ctx.arcTo(ipoint.x, ipoint.y, 
          line2.endPoint.x, line2.endPoint.y,
          Math.abs(line2.startPoint.x - line1.endPoint.x) / 2);
ctx.lineTo(line2.endPoint.x, line2.endPoint.y);
ctx.stroke();