从两个 x, y 点和一个中心 x, y 点在画布上绘制圆弧

DaC*_*aCh 4 javascript trigonometry html5-canvas

我正在尝试从两点(X,Y 线)绘制弧线。

但我不知道如何做到这一点,以便我可以指定起始角度和结束角度

我得到了中心点(p2),半径= r。起点(p1)和终点(p3)。如下图所示 我拥有的

我想做的是使用弧线画一条圆线,如下所示

我想要拥有什么

我在这个主题上发现的只是弧线从 0 绘制到 2*Math.PI 之类的示例。

ctx.arc(100,75,50,0,2*Math.PI);
Run Code Online (Sandbox Code Playgroud)

像这样。A 无法找出可以使用 p1 和 p3 代替这些数字的方法。任何人都可以解释这是如何工作的,并且也许可以尝试一下我如何解决这个问题?

小智 7

arc()方法仅适用于角度,因此必须根据点的位置和到中心的距离进行转换(在这种情况下,代表半径的距离必须相同)。

arc() 的签名是:

void arc(无限制双 x、
              无限制双 y、
              无限制双半径、
              无限制双 startAngle、
              无限制双 endAngle、
              可选布尔值逆时针 = false);

您可以通过简单的三角函数找到从中心 P2 到 P1/P3 的两个角度:

var startAngle = Math.atan2(p1.y - p2.y, p1.x - p2.x),
    endAngle   = Math.atan2(p3.y - p2.y, p3.x - p2.x);
Run Code Online (Sandbox Code Playgroud)

假设半径已知,现在可以将这些输入到 arc 方法中:

ctx.arc(p2.x, p2.y, radius, startAngle, endAngle);
Run Code Online (Sandbox Code Playgroud)

如果半径未知但已知相同,您可以执行以下操作:

var diffX = p1.x - p2.x,
    diffY = p1.y - p2.y,
    radius = Math.abs(Math.sqrt(diffX*diffX + diffY*diffY));
Run Code Online (Sandbox Code Playgroud)

例子

var startAngle = Math.atan2(p1.y - p2.y, p1.x - p2.x),
    endAngle   = Math.atan2(p3.y - p2.y, p3.x - p2.x);
Run Code Online (Sandbox Code Playgroud)
ctx.arc(p2.x, p2.y, radius, startAngle, endAngle);
Run Code Online (Sandbox Code Playgroud)

辅助线的结果

var diffX = p1.x - p2.x,
    diffY = p1.y - p2.y,
    radius = Math.abs(Math.sqrt(diffX*diffX + diffY*diffY));
Run Code Online (Sandbox Code Playgroud)
var p2 = {x: 100   , y: 100   },
    p1 = {x: 111, y:  30.9},
    p3 = {x: 149.5 , y:  149.5},
    diffX = p1.x - p2.x,
    diffY = p1.y - p2.y,
    radius = Math.abs(Math.sqrt(diffX*diffX + diffY*diffY)),
    startAngle = Math.atan2(diffY, diffX),
    endAngle   = Math.atan2(p3.y - p2.y, p3.x - p2.x),
    ctx = document.querySelector("canvas").getContext("2d");

// arc
ctx.arc(p2.x, p2.y, radius, startAngle, endAngle, false);
ctx.stroke();

// points / lines helpers:
ctx.fillRect(p1.x - 2, p1.y - 2, 4, 4);
ctx.fillRect(p2.x - 2, p2.y - 2, 4, 4);
ctx.fillRect(p3.x - 2, p3.y - 2, 4, 4);
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.x);
ctx.lineTo(p3.x, p3.x);
ctx.strokeStyle = "#999";
ctx.stroke();
Run Code Online (Sandbox Code Playgroud)