模块6: 动画系统
基于 W3C Web Animations API 的图形动画
1. 概述
@antv/g 的动画系统实现了 W3C Web Animations API 标准。如果你熟悉浏览器的 element.animate(),就能直接上手。
源码位于 packages/g/src/plugins/web-animations-api/,核心类:Animation、KeyframeEffect、AnimationTimeline。
2. 基本用法
// 最简动画 - 与 DOM element.animate() 完全一致 const animation = circle.animate( [ { r: 50, fill: '#1890ff' }, // 起始关键帧 { r: 100, fill: '#f5222d' }, // 结束关键帧 ], { duration: 1000, // 持续时间 ms easing: 'ease-in-out', iterations: Infinity, // 循环次数 direction: 'alternate', // 交替播放 } );
3. Animation 类
每次调用 .animate() 返回一个 Animation 实例:
// 播放控制 animation.play(); // 播放 animation.pause(); // 暂停 animation.reverse(); // 反向播放 animation.finish(); // 跳到结束 animation.cancel(); // 取消 // 属性 animation.currentTime // 当前时间 (ms) animation.playbackRate // 播放速率 (1=正常, 2=2倍速) animation.playState // idle | running | paused | finished animation.pending // 是否等待中 // 事件回调 animation.onfinish = () => { /* 完成时 */ }; animation.oncancel = () => { /* 取消时 */ }; // Promise 方式 await animation.finished; // 等待动画完成
4. KeyframeEffect 关键帧
// 多关键帧 circle.animate( [ { cx: 100, opacity: 0 }, // 0% { cx: 300, opacity: 1 }, // 50% { cx: 500, opacity: 0.5 }, // 100% ], { duration: 2000, easing: 'linear' } ); // 指定 offset(时间位置) circle.animate( [ { offset: 0, r: 10 }, { offset: 0.3, r: 80 }, // 30% 时 { offset: 1, r: 50 }, ], { duration: 1500 } );
5. 缓动函数 (Easing)
| 缓动 | 说明 |
|---|---|
linear | 线性 |
ease | 默认缓动 |
ease-in | 慢入 |
ease-out | 慢出 |
ease-in-out | 慢入慢出 |
cubic-bezier(x1,y1,x2,y2) | 自定义贝塞尔 |
steps(n, start|end) | 阶梯函数 |
// 弹性缓动 circle.animate([...], { duration: 800, easing: 'cubic-bezier(0.68, -0.55, 0.265, 1.55)', }); // 阶梯动画 circle.animate([...], { duration: 1000, easing: 'steps(5, end)', });
6. 可动画属性
以下样式属性支持动画插值:
| 类别 | 属性 |
|---|---|
| 位置 | cx, cy, x, y, x1, y1, x2, y2 |
| 尺寸 | r, rx, ry, width, height |
| 颜色 | fill, stroke, shadowColor |
| 透明度 | opacity, fillOpacity, strokeOpacity |
| 描边 | lineWidth, lineDashOffset |
| 变换 | transform (translate/rotate/scale) |
| 路径 | d (Path morph) |
7. AnimationTimeline 时间轴
// 获取画布时间轴 const timeline = canvas.document.timeline; timeline.currentTime; // 当前时间 // 所有正在运行的动画 canvas.document.getAnimations();
8. 组合动画
// 串行:等第一个完成后启动第二个 const anim1 = circle.animate( [{ cx: 100 }, { cx: 400 }], { duration: 1000, fill: 'forwards' } ); anim1.onfinish = () => { circle.animate( [{ cy: 100 }, { cy: 300 }], { duration: 1000, fill: 'forwards' } ); }; // 并行:同时启动多个动画 circle.animate([{ r: 50 }, { r: 100 }], { duration: 1000 }); circle.animate([{ fill: 'red' }, { fill: 'blue' }], { duration: 1000 });
9. fill 模式
| 值 | 说明 |
|---|---|
none | 动画结束后恢复初始值(默认) |
forwards | 动画结束后保持最终值 |
backwards | 动画开始前应用初始关键帧 |
both | forwards + backwards |