动画是在AnimateLayer动画层,播放节点和连线时间线上的不同状态。
一、播放流程

播放动画方式一
预览时自动播放,设置节点/连线的animatePlay属性即可。
播放动画方式二
// 修改动画帧数组,需要先准备动画数据环境
0. pen.initAnimate();
- 播放动画: pen.startAnimate();
- 暂停动画: pen.pauseAnimate();
- 停止动画: pen.stopAnimate(); // 停止动画指下次从0开始播放
每次代码调整过node.animateFrames,可能需要执行node.initAnimate(),恢复到初始状态
不要在for循环中执行上面操作
播放动画方式三
// 标记一组节点为相同tag
topology.animateLayer.readyPlay(tag);
topology.animateLayer.animate();
播放动画方式四
for(…) {
pen.animateStart = Date.now();
}
topology.animateLayer.readyPlay();
topology.animateLayer.animate();
二、节点动画
节点动画用帧表示,帧的数据为Node的animateFrames。
animateFrames
| 名称 | 类型 | 是否必选 | 描述 |
|---|---|---|---|
| duration | number | 是 | 当前帧播放时长 |
| start | number | 否 | 动画层添加节点AnimateLayer.addNode自动计算。相对于整个动画时长,当前帧在什么时候播放。 |
| end | number | 否 | 动画层添加节点AnimateLayer.addNode自动计算。相对于整个动画时长,当前帧在什么时候结束。 |
| state | Node | 是 | 当前帧,节点显示状态 |
| linear | boolean | 否 | 动画属性是否线性变化 |
| initState | Node | 否 | 当前帧播放前,初始状态。 自动计算。 |
如何设置节点动画
// 1. 设置node.animateFrames// 复制当前节点状态const state = Node.cloneState(node);// 修改状态位置state.rect.y -= 10;state.rect.ey -= 10;node.animateFrames.push({duration: 100,linear: true,state});// 回到初始状态const state2 = Node.cloneState(node);node.animateFrames.push({duration: 100,linear: true,state: state2});node.animateDuration = 0;for (const item of node.animateFrames) {node.animateDuration += item.duration;}// 修改动画帧数组,需要先准备动画数据环境node.initAnimate();// A 开始播放node.startAnimate();// B 停止播放node.stopAnimate();
// 参考源码中的函数:onChangeAnimate() {if (this.props.data.animateType === 'custom') {return;}this.props.data.animateFrames = [];const state = Node.cloneState(this.props.data);switch (this.props.data.animateType) {case 'upDown':state.rect.y -= 10;state.rect.ey -= 10;this.props.data.animateFrames.push({duration: 100,linear: true,state});this.props.data.animateFrames.push({duration: 100,linear: true,state: Node.cloneState(this.props.data)});this.props.data.animateFrames.push({duration: 200,linear: true,state: Node.cloneState(state)});break;case 'leftRight':state.rect.x -= 10;state.rect.ex -= 10;this.props.data.animateFrames.push({duration: 100,linear: true,state: Node.cloneState(state)});state.rect.x += 20;state.rect.ex += 20;this.props.data.animateFrames.push({duration: 80,linear: true,state: Node.cloneState(state)});state.rect.x -= 20;state.rect.ex -= 20;this.props.data.animateFrames.push({duration: 50,linear: true,state: Node.cloneState(state)});state.rect.x += 20;state.rect.ex += 20;this.props.data.animateFrames.push({duration: 30,linear: true,state: Node.cloneState(state)});this.props.data.animateFrames.push({duration: 300,linear: true,state: Node.cloneState(this.props.data)});break;case 'heart':state.rect.x -= 5;state.rect.ex += 5;state.rect.y -= 5;state.rect.ey += 5;state.rect.width += 5;state.rect.height += 10;this.props.data.animateFrames.push({duration: 100,linear: true,state});this.props.data.animateFrames.push({duration: 400,linear: true,state: Node.cloneState(this.props.data)});break;case 'success':state.strokeStyle = '#237804';this.props.data.animateFrames.push({duration: 100,linear: true,state});this.props.data.animateFrames.push({duration: 100,linear: true,state: Node.cloneState(this.props.data)});state.strokeStyle = '#237804';this.props.data.animateFrames.push({duration: 100,linear: true,state});this.props.data.animateFrames.push({duration: 100,linear: true,state: Node.cloneState(this.props.data)});state.strokeStyle = '#237804';state.fillStyle = '#389e0d22';this.props.data.animateFrames.push({duration: 3000,linear: true,state});break;case 'warning':state.strokeStyle = '#fa8c16';state.dash = 2;this.props.data.animateFrames.push({duration: 300,linear: true,state});state.strokeStyle = '#fa8c16';state.dash = 0;this.props.data.animateFrames.push({duration: 500,linear: true,state: Node.cloneState(state)});state.strokeStyle = '#fa8c16';state.dash = 2;this.props.data.animateFrames.push({duration: 300,linear: true,state: Node.cloneState(state)});break;case 'error':state.strokeStyle = '#cf1322';state.fillStyle = '#cf132222';this.props.data.animateFrames.push({duration: 100,linear: true,state});break;case 'show':state.strokeStyle = '#fa541c';state.rotate = -10;this.props.data.animateFrames.push({duration: 100,linear: true,state: Node.cloneState(state)});state.rotate = 10;this.props.data.animateFrames.push({duration: 100,linear: true,state: Node.cloneState(state)});state.rotate = 0;this.props.data.animateFrames.push({duration: 100,linear: true,state: Node.cloneState(state)});break;}this.onAnimateDuration();}
三、连线动画
连线动画,目前仅为从起点到终点的动态流量显示。
连线动画属性
| 名称 | 类型 | 是否必选 | 描述 |
|---|---|---|---|
| animateColor | string | 否 | 动画颜色 |
| animateSpan | number | 是 | 连线动画移动大小,像素 |
| animateType | string | 否 | 来自于pen。动画播放类型: 空(默认), beads(水珠流动), dot(圆点), comet(彗星) |
| animatePos | number | 否 | 动画当前位置,自动计算。 |
// 1. 设置动画类型,默认line.animateType = '';// A 开始播放node.startAnimate();// B 停止播放node.stopAnimate();
四、自动播放动画
设置节点/连线的animatePlay属性即可。canvas.open的时候,就好自动播放。
五、自动播放下一个动画
置节点/连线的nextAnimate属性值为下一个节点/连线的tags数组中的一个值。此节点/连线动画播放结束时,自动播放下一个动画。
六、动画时长
节点的动画时长由动画帧数组决定;连线的动画时长与连线长度和播放速度animateSpan有关。
