canvas中已知两圆的圆心坐标,在两圆之间绘制弧线

上述问题的起因是有一需求,需要在两圆之间绘制弧线。
canvas中绘制弧线的方法有两个 arcTo()arc()
arcTo是在两条切线间弧线,不适用。
arc绘制的是圆或者弧线,较为符合,但需要设置起始弧度、结束弧度、半径、圆心坐标。
已知的是两圆的圆心坐标、半径,需要计算起始弧度、结束弧度、弧线半径、弧线圆心坐标。

  1. 计算弧线半径、圆心。
  // 起始点 终点 半径
  const { x: startX, y: startY } = start
  const { x: endX, y: endY } = end
  const radius = 20

  // 两圆圆心坐标连线的长度
  const distance = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2))

  // 弧线所对应的弧度
  // 为确保弧线的弧度不会过大,默认弧线对应的角度为60°
  // 即圆心与两圆圆心连线后为等边三角形,半径就等于两圆圆心坐标的间距
  const arcAngle = Math.PI / 3

  // 两圆圆心坐标连线与x轴夹角所对应的弧度
  const posLineAngle = Math.atan2(endY - startY, endX - startX)

  // 弧线的圆心与起始点坐标连线与X轴夹角所对应的弧度
  const arcLineAngle = arcAngle - posLineAngle

  // 弧线的圆心坐标
  const circle = {
    x: startX + distance * Math.cos(arcLineAngle),
    y: startY - distance * Math.sin(arcLineAngle)
  }
  1. 计算起始弧度、结束弧度
  const { x, y } = circle

  // 弧线在起始节点和结束节点中多余的弧度
  const startOffset = Math.asin(radius / (2 * distance)) * 2
  const endOffset = Math.asin(radius / (2 * distance)) * 2

  // 弧线的起始弧度 结束弧度
  const startAngle = arcLineAngle + Math.PI + startOffset
  const endAngle = arcLineAngle + Math.PI * 4 / 3 - endOffset
  1. 绘制弧线
  // 上述弧度是逆时针计算,js的圆绘制是以顺时针绘制
  canvas.arc(x, y, distance, -endAngle, -startAngle)
  1. 绘制弧线末的箭头
    为美观着想,对弧线的末尾处添加指示箭头
  const ax = x + distance * Math.cos(endAngle)
  const ay = y - distance * Math.sin(endAngle)
  const angle = Math.PI / 2 - endAngle
  const arrowSize = 12 // 箭头的边长,控制箭头大小
  const bx = ax + Math.sin(angle + Math.PI / 3) * arrowSize
  const by = ay - Math.cos(angle + Math.PI / 3) * arrowSize
  const cx = ax + Math.sin(angle + Math.PI - Math.PI / 3) * arrowSize
  const cy = ay - Math.cos(angle + Math.PI - Math.PI / 3) * arrowSize
  canvas.stroke()
  canvas.beginPath()
  canvas.moveTo(ax, ay)
  canvas.lineTo(bx, by)
  canvas.lineTo(cx, cy)
  canvas.closePath()
  canvas.fill()

至此,需求基本满足

你可能感兴趣的:(canvas中已知两圆的圆心坐标,在两圆之间绘制弧线)