<!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點控制javascript
參考資料: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.htmlhtml