要用canvas实现贝塞尔平滑路径动画,需先拟合控制点使路径c¹连续,再用beziercurveto分段绘制,并通过弧长参数化实现匀速运动。

要用 Canvas 实现基于贝塞尔曲线的平滑路径插值动画,核心是:用 quadraticCurveTo(二阶)或 bezierCurveTo(三阶)连续绘制分段贝塞尔曲线,再结合时间驱动的参数插值(如匀速重采样或弧长参数化),让动画沿路径匀速、自然地运动。
1. 构建控制点序列与路径拟合
原始路径点(如鼠标轨迹、GPS坐标)通常不光滑。需先生成贝塞尔控制点,使整条路径C¹连续(切线连续):
- 对 n+1 个锚点
P₀…Pₙ,计算每段的两个控制点C₁ᵢ、C₂ᵢ,常用方法是“Catmull-Rom 转贝塞尔”或“自然三次样条转控制点”; - 更实用的做法:对每个内部点
Pᵢ (1≤i≤n−1),设C₁ᵢ = Pᵢ + (Pᵢ₊₁ − Pᵢ₋₁)/3,C₂ᵢ = Pᵢ₊₁ − (Pᵢ₊₂ − Pᵢ)/3(类Hermite逼近); - 首尾段可用延长线法补控制点,确保起点/终点精确落在锚点上。
2. 在Canvas中绘制贝塞尔路径
用 beginPath() → moveTo(P₀) → 多次 bezierCurveTo(C₁₀, C₂₀, P₁) 绘制整条平滑曲线:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (let i = 0; i <h3>3. 实现匀速插值动画(关键难点)</h3><p>直接按参数 t ∈ [0,1] 线性插值贝塞尔点会导致“忽快忽慢”(因贝塞尔是非匀速参数化)。需做弧长重映射:</p>
- 预计算:将整条贝塞尔路径离散为 100–200 段,用 De Casteljau 算法采样点,累加欧氏距离得到近似弧长数组
arcLengths[]; - 构建查找表:对目标归一化进度
s ∈ [0,1](即动画完成度),查arcLengths找到对应 t 值(可用二分查找); - 动画循环中,用该 t 调用
getBezierPoint(t, P₀,C₁₀,C₂₀,P₁)得到当前位置,再绘制小球或图标。
4. 性能与交互优化建议
避免每帧重复计算弧长或控制点:
- 控制点和弧长表只在路径更新时预计算一次,存为实例属性;
- 动画用
requestAnimationFrame驱动,t 按时间线性递增(如t = Math.min(1, (now - start) / duration)),再查表得位置; - 若路径动态变化(如实时绘图),可局部重算受影响的 2–3 段,而非全路径;
- 需要高精度匀速?可用数值积分(如自适应 Simpson)代替固定步长采样,但开销略高。
不复杂但容易忽略的是:贝塞尔动画的“平滑感”不仅来自曲线形状,更取决于速度连续性——弧长参数化是让运动真正自然的关键一步。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










