上述问题的起因是有一需要,须要在两圆之间绘制弧线。
canvas 中绘制弧线的办法有两个 arcTo()、arc()。
arcTo 是在两条切线间弧线,不实用。
arc 绘制的是圆或者弧线,较为合乎,但须要设置起始弧度、完结弧度、半径、圆心坐标。
已知的是两圆的圆心坐标、半径,须要计算起始弧度、完结弧度、弧线半径、弧线圆心坐标。
- 计算弧线半径、圆心。
// 起始点 起点 半径
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)
}
- 计算起始弧度、完结弧度
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
- 绘制弧线
// 上述弧度是逆时针计算,js 的圆绘制是以顺时针绘制
canvas.arc(x, y, distance, -endAngle, -startAngle)
- 绘制弧线末的箭头
为好看着想,对弧线的开端处增加批示箭头
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()
至此,需要根本满足