我一直在努力理解arc svg,因为我似乎需要它们 - 我的目标是绘制圆形交叉点。
我最初的想法是这样的:
对于每个交叉路口,找到起点和终点坐标以及高度 - 但我不太清楚从哪里开始。看来我缺少旋转和大弧标记/扫描参数,我不知道如何检索它们。如果有人能指出我在这里正确的方向,那将是伟大的!
答案 0 :(得分:4)
不太了解SVG arcTo。 MDN提供"A rx,ry xAxisRotate LargeArcFlag,SweepFlag x,y"
。作为路径元素中的弧。什么rx和ry是???我猜半径为x,y。
我猜你会用它作为
// x,y start position
// rx,ry radius x and y
// x1,y1 end position
<path d="M x,y A rx, ry, 0 1 1 x1, y1"/>
以下是javascript解决的问题。我已经评论了SVG所需的部分。两个终点(拦截)
有很多冗余,但不清楚你想要什么,所以代码提供了如何找到两个相交圆的其他部分。
解决问题的数学运算称为law of cosines,用于求解三角形。
在这种情况下,三角形由3个长度组成。圆半径各一个,圆中心之间的距离为1。图像提供了更多细节
使用角度c,您可以找到长度GE,DE和EF。如果你想在f点另一边的角度只是交换B和C.
移动鼠标以检查拦截。
const ctx = canvas.getContext("2d");
const m = {
x: 0,
y: 0
};
document.addEventListener("mousemove", e => {
var b = canvas.getBoundingClientRect();
m.x = e.pageX - b.left - scrollX;
m.y = e.pageY - b.top - scrollY;
});
const PI = Math.PI;
const PI2 = Math.PI * 2;
const circles = [];
function circle(x, y, r, col, f = 0, t = PI2, w = 2) {
var c;
circles.push(c = { x, y,r, col, f, t, w});
return c;
};
function drawCircle(A) {
ctx.strokeStyle = A.col;
ctx.lineWidth = A.w;
ctx.beginPath();
ctx.arc(A.x, A.y, A.r, A.f, A.t);
ctx.stroke();
}
function mark(x, y, r, c) {
ctx.strokeStyle = c;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(x, y, r, 0, PI2);
ctx.stroke();
}
function line(A, B, c) {
ctx.strokeStyle = c;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.lineTo(A.x, A.y);
ctx.lineTo(B.x, B.y);
ctx.stroke();
}
// note I am sharing calc results between function
function circleIntercept(A, B) {
var vx, vy, dist, c, d, x, y, x1, y1, x2, y2, dir, a1, a2;
// Vec from A to B
vx = B.x - A.x;
vy = B.y - A.y;
// Distance between
dist = Math.sqrt(vx * vx + vy * vy);
// Are the intercepting
if (dist < A.r + B.r && dist > B.r - A.r) {
c = (B.r * B.r - (dist * dist + A.r * A.r)) / (-2 * dist);
// Find mid point on cord
x = A.x + vx * (c / dist);
y = A.y + vy * (c / dist);
mark(x, y, 5, "blue");
// Find circumference intercepts
//#################################################################
//=================================================================
// SVG path
// Use x1,y1 and x2,y2 as the start and end angles of the ArcTo SVG
d = Math.sqrt(A.r * A.r - c * c);
x1 = x - vy * (d / dist);
y1 = y + vx * (d / dist);
x2 = x + vy * (d / dist);
y2 = y - vx * (d / dist);
// SVG path from above coords
// d = `M ${x1}, ${y1} A ${A.r}, ${A,r1} 0, 1, 1, ${x2}, ${y2}`;
//=================================================================
// draw the chord
line({x: x1,y: y1}, {x: x2,y: y2}, "red");
// mark the intercepts
mark(x1, y1, 5, "Green");
mark(x2, y2, 5, "Orange");
// Get direction from A to B
dir = Math.atan2(vy, vx);
// Get half inside sweep
a1 = Math.acos(c / A.r);
// Draw arc for A
A.col = "black";
A.w = 4;
A.f = dir - a1;
A.t = dir + a1;
drawCircle(A);
A.col = "#aaa";
A.w = 2;
A.f = 0;
A.t = PI2;
// inside sweep for B
a2 = Math.asin(d / B.r);
// Draw arc for B
B.col = "black";
B.w = 4;
if (dist < c) {
B.t = dir - a2;
B.f = dir + a2;
} else {
B.f = dir + PI - a2;
B.t = dir + PI + a2;
}
drawCircle(B);
B.col = "#aaa";
B.w = 2;
B.f = 0;
B.t = PI2;
}
}
var w = canvas.width;
var h = canvas.height;
var cw = w / 2; // center
var ch = h / 2;
var C1 = circle(cw, ch, ch * 0.5, "#aaa");
var C2 = circle(cw, ch, ch * 0.8, "#aaa");
function update(timer) {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.globalAlpha = 1;
if (w !== innerWidth || h !== innerHeight) {
cw = (w = canvas.width = innerWidth) / 2;
ch = (h = canvas.height = innerHeight) / 2;
C1.x = cw;
C1.y = ch;
C1.r = ch * 0.5;
ctx.lineCap = "round";
}
C2.x = m.x;
C2.y = m.y;
ctx.clearRect(0, 0, w, h);
drawCircle(C1);
drawCircle(C2);
circleIntercept(C1, C2);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
&#13;
canvas {
position: absolute;
top: 0px;
left: 0px;
}
&#13;
<canvas id="canvas"></canvas>
&#13;
答案 1 :(得分:1)
让我们从一些术语开始,以清除顺时针方向(记住SVG的y轴向下):第一个圆有半径r1
,第二个{{1 }}
r2
),则将交叉点命名为较小的x坐标cy1 > cy2
,另一个(x1, y1)
。 (x2, y2)
),则将交叉点命名为较大的x坐标cy1 < cy2
,另一个(x1, y1)
。 (x2, y2)
和另一个(x1, y1)
命名交叉点。现在我们将从第一个到第二个交叉点绘制一个圆弧,该圆弧的半径为第一个圆。前两个弧参数是水平和垂直半径。由于我们画一个圆圈,两者都是相同的。出于同样的原因,旋转半径没有意义,第三个参数是0。
两个圆的交点总是使用小弧(大弧将用于并集),因此大弧标志为0.我们正在顺时针绘制弧,因此扫描标志为1.
还不清楚? spec使用此图片来解释标志:
第二个弧从第二个圆到第一个交叉点,第二个圆的半径。标志保持不变。
结果如下:
(x2, y2)