如何在Canvas中实现图片沿贝塞尔曲线运动并同步路径角度旋转?
实现原理
要实现图片沿二次贝塞尔曲线运动时同步调整朝向,核心是计算路径在当前运动点的切线方向,将图片旋转到和切线方向对齐即可:
- 通过二次贝塞尔曲线的导数公式,计算当前运动点的x/y轴方向变化率,使用
Math.atan2()得到对应的旋转弧度 - 绘制图片前操作Canvas上下文状态:先平移到当前运动点坐标,再按计算出的角度旋转,绘制完成后恢复上下文状态避免影响后续渲染
完整修改后代码
JavaScript 代码
var c = document.getElementById('myCanvas'); var ctx = c.getContext('2d'); var statue = new Image(); statue.src = 'https://i.ibb.co/3TvCH8n/liberty.png'; // 计算二次贝塞尔曲线指定百分比位置的坐标 function getQuadraticBezierXYatPercent(startPt, controlPt, endPt, percent) { var x = Math.pow(1 - percent, 2) * startPt.x + 2 * (1 - percent) * percent * controlPt.x + Math.pow(percent, 2) * endPt.x; var y = Math.pow(1 - percent, 2) * startPt.y + 2 * (1 - percent) * percent * controlPt.y + Math.pow(percent, 2) * endPt.y; return { x: x, y: y }; } // 新增:计算二次贝塞尔曲线指定百分比位置的切线角度(弧度) function getQuadraticBezierTangentAtPercent(startPt, controlPt, endPt, percent) { const dx = 2 * (1 - percent) * (controlPt.x - startPt.x) + 2 * percent * (endPt.x - controlPt.x); const dy = 2 * (1 - percent) * (controlPt.y - startPt.y) + 2 * percent * (endPt.y - controlPt.y); return Math.atan2(dy, dx); } const startPt = { x: 600, y: 200 }; const controlPt = { x: 300, y: 100 }; const endPt = { x: 0, y: 200 }; var percent = 0; statue.addEventListener('load', () => { animate(); }); function animate() { ctx.clearRect(0, 0, c.width, c.height); percent > 1 ? (percent = 0) : (percent += 0.003); var point = getQuadraticBezierXYatPercent(startPt, controlPt, endPt, percent); // 计算当前点的旋转角度 var rotateAngle = getQuadraticBezierTangentAtPercent(startPt, controlPt, endPt, percent); // 如有需要可调整角度偏移,比如rotateAngle += Math.PI / 2适配图片初始朝向 // 操作上下文状态实现旋转绘制 ctx.save(); ctx.translate(point.x, point.y); ctx.rotate(rotateAngle); ctx.drawImage( statue, 0, 0, statue.width, statue.height, -50, // 因为已经平移到运动点,只需按图片大小负偏移一半实现中心对齐 -50, 100, 100 ); ctx.restore(); requestAnimationFrame(animate); }
HTML 代码
<!DOCTYPE html> <html> <body> <canvas id="myCanvas" width="600" height="200" style="border:1px solid #d3d3d3;"> Your browser does not support the HTML5 canvas tag.</canvas> </body> </html>
路径示意图

内容的提问来源于stack exchange,提问作者Toto Briac
相关产品推荐
相关产品推荐

