Skip to main content
 首页 » 编程设计

javascript之Arc SVG 参数

2025年05月04日25java哥

我一直在尝试理解 arc svg,因为我似乎需要它们进行绘图——我的目标是绘制圆的交点。

我最初的想法是这样的:

对于每个路口,找到起点和终点坐标以及高度 - 但我不太确定从这里到哪里去。看来我缺少旋转和大弧形标志/扫描参数,而且我不确定我将如何检索它们。如果有人能在这里指出我正确的方向,那就太好了!

请您参考如下方法:

圆圈和拦截点

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用于求解三 Angular 形。

在这种情况下,三 Angular 形是由 3 个长度创建的。一个是圆半径,一个是圆心之间的距离。图片提供了更多细节

用 Angular c 可以求出 GE、DE 和 EF 的长度。如果你想要另一边在 f 点的 Angular ,只需交换 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);
canvas { 
  position: absolute; 
  top: 0px; 
  left: 0px; 
}
<canvas id="canvas"></canvas>