二阶:http://qingshanboke.com/demo/quadratic.htm
三阶:http://qingshanboke.com/demo/bezier.htm
一、实现思路:
1.用两个canvas实现,一个绘制曲线,一个绘制运动圆点。
2.绘制曲线:可以通过canvas提供的API方法绘制。
二阶:quadraticCurveTo(controlX, controlY, endingPointX, endingPointY) 1个控制点。
三阶:bezierCurveTo(controlX1, controlY1, controlX2, controlY2, endPointX, endPointY),2个控制点。
3.绘制圆点:根据贝塞尔曲线公式,计算出不同时刻圆点坐标,然后绘制到canvas上。
二、实现过程:
1.二阶曲线:
核心公式:
<html> <title>二阶贝塞尔曲线</title> <style type="text/css"> body { background: black; } #canvas { position: absolute; top: 0; left: 0; width: 600px; height: 600px; } #line { position: absolute; top: 0; left: 0; width: 600px; height: 600px; } </style> <body> <canvas id="canvas" width="600" height="600"></canvas> <canvas id="line" width="600" height="600"></canvas> <script type="text/javascript"> var point = { begin: { x: 20, y: 20 }, control: { x: 40, y: 400 }, end: { x: 600, y: 600 }, }; function drawline() { let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(point.begin.x, point.begin.y); ctx.quadraticCurveTo(point.control.x, point.control.y, point.end.x, point.end.y); ctx.strokeStyle = "#2578b0"; ctx.lineWidth = 2; ctx.stroke(); } drawline(); let t = 0; function drawPoint() { //根据二次贝塞尔曲线的公式,获取某时刻t[0-1]的贝塞尔曲线上的点 let x = Math.pow((1 - t), 2) * point.begin.x + 2 * t * (1 - t) * point.control.x + Math.pow(t, 2) * point.end.x; let y = Math.pow((1 - t), 2) * point.begin.y + 2 * t * (1 - t) * point.control.y + Math.pow(t, 2) * point.end.y; //移出画布后,重新开始 if (x > 600) { t = 0; x = point.begin.x; y = point.begin.y; } let canvas = document.getElementById("line"); let ctx = canvas.getContext("2d"); //清除上一次的点 ctx.clearRect(0, 0, 600, 600); ctx.beginPath(); //画小圆点 ctx.moveTo(point.begin.x, point.begin.y); ctx.arc(x, y, 4, 0, 2 * Math.PI, false); ctx.fillStyle = "white"; ctx.fill(); //显示坐标 ctx.font = 'bold 12px Arial'; ctx.textAlign = 'left'; ctx.textBaseline = 'bottom'; ctx.fillStyle = 'white'; ctx.fillText("x:" + parseInt(x), x, y - 24); ctx.fillText("y:" + parseInt(y), x, y - 12); ctx.closePath(); t += 0.006; } setInterval(drawPoint, 60); </script> </body> </html>
2.三阶曲线:
核心公式:
<html> <title>三阶贝塞尔曲线</title> <style type="text/css"> body { background: black; } #canvas { position: absolute; top: 0; left: 0; width: 600px; height: 600px; } #line { position: absolute; top: 0; left: 0; width: 600px; height: 600px; } </style> <body> <canvas id="canvas" width="600" height="600"></canvas> <canvas id="line" width="600" height="600"></canvas> <script type="text/javascript"> var point = { begin: { x: 0, y: 600 }, control1: { x: 500, y: 500 }, control2: { x: 400, y: 40 }, end: { x: 600, y: 0 }, }; function drawline() { let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(point.begin.x, point.begin.y); ctx.bezierCurveTo(point.control1.x, point.control1.y, point.control2.x, point.control2.y, point.end.x, point.end.y); ctx.strokeStyle = "#2578b0"; ctx.lineWidth = 2; ctx.stroke(); } drawline(); let t = 0; function drawPoint() { //根据三次贝塞尔曲线的公式,获取某时刻t[0-1]的贝塞尔曲线上的点 let x = point.begin.x * Math.pow((1 - t), 3) + 3 * t * point.control1.x * Math.pow((1 - t), 2) + 3 * point.control2.x * Math.pow(t, 2) * (1 - t) + point.end.x * Math.pow(t, 3); let y = point.begin.y * Math.pow((1 - t), 3) + 3 * t * point.control1.y * Math.pow((1 - t), 2) + 3 * point.control2.y * Math.pow(t, 2) * (1 - t) + point.end.y * Math.pow(t, 3); //移出画布后,重新开始 if (x > 600) { t = 0; x = point.begin.x; y = point.begin.y; } let canvas = document.getElementById("line"); let ctx = canvas.getContext("2d"); //清除上一次的点 ctx.clearRect(0, 0, 600, 600); ctx.beginPath(); //画小圆点 ctx.moveTo(point.begin.x, point.begin.y); ctx.arc(x, y, 4, 0, 2 * Math.PI, false); ctx.fillStyle = "white"; ctx.fill(); //显示坐标 ctx.font = 'bold 12px Arial'; ctx.textAlign = 'left'; ctx.textBaseline = 'bottom'; ctx.fillStyle = 'white'; ctx.fillText("x:" + parseInt(x), x, y - 24); ctx.fillText("y:" + parseInt(y), x, y - 12); ctx.closePath(); t += 0.006; } setInterval(drawPoint, 60); </script> </body> </html>
在线预览:http://qingshanboke.com/demo/bezier.htm
参考资料:
https://www.w3school.com.cn/tags/canvas_quadraticcurveto.asp
https://www.w3school.com.cn/tags/canvas_beziercurveto.asp
https://baike.baidu.com/item/%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF/1091769?fr=aladdin
https://blog.csdn.net/ixygj197875/article/details/80043658