Canvas 本身不内置补间动画,需通过 JavaScript 手动实现或集成 Tween.js 等库,将插值结果映射到绘图属性并在 requestAnimationFrame 中逐帧重绘。

Canvas 本身不内置补间动画(Tween)功能,但可以通过 JavaScript 手动实现或集成轻量级 Tween 库(如 Tween.js、gsap 或自研简易插值器)来驱动 Canvas 绘图状态的平滑变化。关键在于将补间计算出的中间值,实时映射到 Canvas 的绘图属性(如坐标、尺寸、颜色、透明度、旋转角度等),并在 requestAnimationFrame 循环中持续重绘。
核心思路:时间驱动 + 属性映射 + 逐帧重绘
补间动画的本质是按时间函数(如线性、缓动)在起始值与结束值之间生成连续中间值。在 Canvas 中需完成三步:
- 定义动画目标:例如让一个圆从
(50, 50)移动到(300, 200),同时半径从10变为40,填充色从#ff6b6b渐变为#4ecdc4 - 用 Tween 引擎管理动画生命周期:设置持续时间、缓动类型(如
easeOutQuad)、回调时机 - 在每一帧中读取当前插值结果,清空画布,重新绘制更新后的图形
使用 Tween.js 集成 Canvas 动画(轻量实用示例)
以 tween.js 为例,它体积小、无依赖、API 清晰:
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
<p>// 动画对象(存储可变状态)
const ball = {
x: 50,
y: 50,
r: 10,
color: '#ff6b6b'
};</p><p>// 创建补间:从 ball 当前状态过渡到目标
new TWEEN.Tween(ball)
.to({ x: 300, y: 200, r: 40, color: '#4ecdc4' }, 2000)
.easing(TWEEN.Easing.Quadratic.Out)
.onUpdate(() => {
// 每次更新时直接使用 ball 的当前值绘图
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2);
ctx.fillStyle = ball.color;
ctx.fill();
})
.start();</p><p>// 动画主循环(必需!)
function animate() {
requestAnimationFrame(animate);
TWEEN.update(); // 驱动所有活跃补间
}
animate();
颜色、透明度等非数值属性的插值处理
像 color 这类字符串值不能直接插值,需拆解为 RGB 或 HSL 分量再分别计算。简单做法是借助 tinycolor2 或手动转换:
立即学习“前端免费学习笔记(深入)”;
- 将起始色
#ff6b6b和目标色#4ecdc4转为{r: 255, g: 107, b: 107}和{r: 78, g: 205, b: 196} - 补间对象中改为插值
r、g、b字段,onUpdate中拼接rgb(r,g,b) - 透明度(
globalAlpha)可直接作为数字字段参与补间
性能与实践建议
Canvas 补间动画易因频繁重绘或复杂计算导致掉帧,注意以下几点:
- 避免在
onUpdate中做耗时操作(如 DOM 查询、大数组遍历),只做必要绘图 - 多个动画共存时,统一用单个
requestAnimationFrame驱动所有TWEEN.update(),而非每个动画单独启动循环 - 对静态背景可离屏渲染一次,仅重绘动态元素,减少
clearRect范围 - 复杂图形(如路径、文字)优先缓存为
ImageBitmap或离屏 canvas,用drawImage复用











