<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Demo smooth connection</title>
</head>
<body>
<canvas id="canvas"></canvas>
<style>
html {
position: relative;
height: 100%;
width: 100%;
}
body {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: 0;
}
canvas {outline: 1px solid red;}
</style>
<script>
const getDistance = (p1, p2) => {
return Math.sqrt(Math.pow(p1.x + p2.x, 2)
+
Math.pow(p1.y + p1.y, 2)
)
}
const getControlpoint = (points) => {// 三个点出两个控制点
const p01 = getDistance(points[0], points[1])
const p12 = getDistance(points[1], points[2])
const p02 = p01 + p12
let vector = [points[2].x - points[0].x, points[2].y - points[0].y]
return [
{x: points[1].x - vector[0] * 0.5 * p01 / p02,
y: points[1].y - vector[1] * 0.5 * p01 / p02
},
{x: points[1].x + vector[0] * 0.5 * p01 / p02,
y: points[1].y + vector[1] * 0.5 * p01 / p02
}
]
}
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
window.onload = window.onresize = () => {
canvas.width = document.body.clientWidth
canvas.height = document.body.clientHeight
drawBezierCurve()
drawPoint()}
let points = [{ x: 131, y: 193},
{x: 187, y: 128},
{x: 231, y: 240},
{x: 280, y: 124},
{x: 340, y: 236},
{x: 368, y: 131},
{x: 416, y: 239},
]
const drawPoint = () => {
points.forEach(point => {ctx.beginPath()
ctx.arc(point.x, point.y, 5, 0, 2 * Math.PI)
ctx.fill()})
}
const drawBezierCurve = () => {
let len = points.length
if (len < 2) {return}
ctx.beginPath()
ctx.moveTo(points[0].x, points[0].y)
if (len === 2) {ctx.lineTo(points[1].x, points[1].y)
} else {let controlPoint = []
for (let i = 1; i < len - 1; i++) {controlPoint = controlPoint.concat(getControlpoint([points[i - 1], points[i], points[i + 1]]))
}
let i = 2
ctx.quadraticCurveTo(controlPoint[0].x, controlPoint[0].y, points[1].x, points[1].y)
for (; i < len - 1; i++) {
ctx.bezierCurveTo(controlPoint[(i - 2) * 2 + 1].x,
controlPoint[(i - 2) * 2 + 1].y,
controlPoint[(i - 1) * 2].x,
controlPoint[(i - 1) * 2].y,
points[i].x,
points[i].y
)
}
console.log(controlPoint, i)
ctx.quadraticCurveTo(controlPoint[(i - 2) * 2 + 1].x,
controlPoint[(i - 2) * 2 + 1].y,
points[i].x,
points[i].y
)
}
ctx.strokeStyle = 'blue'
ctx.stroke()}
</script>
</body>
</html>
留神点:1. 第二个点和最初一个点要应用 quadraticCurveTo, 2. 线 1 受 2 点和 3 点管制
参考资料:https://stackoverflow.com/questions/7054272/how-to-draw-smooth-curve-through-n-points-using-javascript-html5-canvas/10060462#10060462
原理:http://scaledinnovation.com/analytics/splines/aboutSplines.html