今天学习了贝塞尔曲线的移动轨迹,并用HTML画出来。 贝塞尔曲线的移动轨迹如下: 其中:
起始点为p0(x0,y0),终点为p3(x3,y3),两个控制点分别为p1(x1,y1),p2(x2,y2)
t 为移动因子,并且0< t <1
cx = 3 * (x1 - x0);
bx = 3 * (x2 - x1) - cx;
ax = x3 - x0 - cx - bx;
cy = 3 * (y1 - y0);
by = 3 * (y2 - y1) - cy;
ay = y3 - y0 - cy - by;
代码如下:
<!DOCTYPE html><html> <head> <meta charset="UTF-8"/> <title>Bezier Curve Movement</title> <!-- http://modernizr.com/ --> <script src="modernizr-latest.js"></script> <script> window.addEventListener("load", eventWindowLoaded, false); function eventWindowLoaded() { canvasApp(); } function canvasSupport() { return Modernizr.canvas; } function canvasApp() { if (!canvasSupport()) { return; } var theCanvas = document.getElementById("theCanvas"); var context = theCanvas.getContext("2d"); var pointImage = new Image(); pointImage.src = "point.png"; var p0 = { x:60, y:10 }; // the start point var p1 = { x:70, y:200 }; // control point 1 var p2 = { x:125, y:295 }; // control point 2 var p3 = { x:350, y:350 }; // the end point // t must less than 1, so we will increase t by a speed of .01 var ball = { x:0, y:0, speed:.01, t:0 }; var points = new Array(); gameLoop(); function gameLoop() { window.setTimeout(gameLoop, 20); drawScreen(); } function drawScreen() { // draw background context.fillStyle = "#EEEEEE"; context.fillRect(0, 0, theCanvas.width, theCanvas.height); context.strokeStyle = "#000000"; context.strokeRect(1, 1, theCanvas.width - 2, theCanvas.height - 2); var t = ball.t; // for convenience // calculate coefficients var cx = 3 * (p1.x - p0.x); var bx = 3 * (p2.x - p1.x) - cx; var ax = p3.x - p0.x - cx - bx; var cy = 3 * (p1.y - p0.y); var by = 3 * (p2.y - p1.y) - cy; var ay = p3.y - p0.y - cy - by; var xt = ax*(t*t*t) + bx*(t*t) + cx*t + p0.x; var yt = ay*(t*t*t) + by*(t*t) + cy*t + p0.y; ball.t += ball.speed; if (ball.t > 1) { ball.t = 1; } // draw start point, end point and control points context.font = "10px sans"; context.fillStyle = "#FF0000"; context.beginPath(); context.arc(p0.x, p0.y, 8, 0, 2*Math.PI, false); context.closePath(); context.fill(); context.fillStyle = "#FFFFFF"; context.fillText("0", p0.x - 2, p0.y + 2); context.font = "10px sans"; context.fillStyle = "#FF0000"; context.beginPath(); context.arc(p1.x, p1.y, 8, 0, 2*Math.PI, false); context.closePath(); context.fill(); context.fillStyle = "#FFFFFF"; context.fillText("1", p1.x - 2, p1.y + 2); context.font = "10px sans"; context.fillStyle = "#FF0000"; context.beginPath(); context.arc(p2.x, p2.y, 8, 0, 2*Math.PI, false); context.closePath(); context.fill(); context.fillStyle = "#FFFFFF"; context.fillText("2", p2.x - 2, p2.y + 2); context.font = "10px sans"; context.fillStyle = "#FF0000"; context.beginPath(); context.arc(p3.x, p3.y, 8, 0, 2*Math.PI, false); context.closePath(); context.fill(); context.fillStyle = "#FFFFFF"; context.fillText("3", p3.x - 2, p3.y + 2); // draw points to illustrate path for (var i = 0; i < points.length; ++i) { context.drawImage(pointImage, points[i].x, points[i].y, 1, 1); } points.push({x:xt, y:yt}); // draw circle moving context.fillStyle = "#000000"; context.beginPath(); context.arc(xt, yt, 5, 0, 2*Math.PI, false); context.closePath(); context.fill(); } } </script> </head> <body> <canvas id="theCanvas" width="500" height="500"> Your browser does not support HTML5 Canvas. </canvas> </body></html>
最后的效果请见:贝塞尔测试