用于创建动态、程序化和基于表达式的动画的高级动画系统,超越简单的关键帧。
动画系统支持多种类型,超越传统的关键帧:
这些高级动画在元素的 animations 数组属性中定义。
节点动画 (animations 数组):
关键帧 (keyframes 数组):
当多个动画方法针对同一属性时:
| 属性 | 类型 | 必需 | 示例 | 值范围 | 描述 |
|---|---|---|---|---|---|
| type | string | true | - | expression | procedural | sequence | path | 动画的类型。 |
| enabled | boolean | false | - | - | 动画是否处于活动状态。 |
| target | string | true | - | - | 要动画的属性路径(例如,`"x"`、`"rotation"`、`"scaleX"`)。 |
| startTime | number | false | - | - | 相对于元素开始的动画开始时间,以秒为单位。 |
| duration | number | false | - | - | 动画的持续时间(以秒为单位)。对于循环动画,这是循环周期。 |
| loop | boolean | false | - | - | 动画是否循环。 |
| blendMode | string | false | - | replace | add | multiply | 此动画与其他动画的组合方式:替换(覆盖)、添加(求和)、乘法(缩放)。 |
| blendWeight | number | false | - | - | 此动画的强度/影响力(0-1)。用于混合多个动画。 |
表达式是每帧评估的 JavaScript 代码,可以访问动画上下文变量。
{
time: number; // 当前绝对时间(秒)
localTime: number; // 相对于元素开始的时间
duration: number; // 元素持续时间
progress: number; // 标准化进度(0-1)
index: number; // 组内元素索引
total: number; // 组内总元素数
fps: number; // 每秒帧数
width: number; // 画布宽度
height: number; // 画布高度
value: any; // 当前属性值
}使用数学函数的弹跳动画:
{
"id": "element-1",
"type": "Image",
"start": 0,
"duration": 5,
"animations": [
{
"type": "expression",
"target": "y",
"enabled": true,
"expression": "100 + Math.abs(Math.sin(localTime * 3)) * 200",
"startTime": 0,
"duration": 5,
"loop": true
}
]
}
组合多个效果:
{
"animations": [
{
"type": "expression",
"target": "rotation",
"expression": "(localTime * 2 * Math.PI / duration) + Math.sin(localTime * 4) * 0.1",
"loop": true
},
{
"type": "expression",
"target": "scaleX",
"expression": "1 + Math.sin(localTime * 5) * 0.2",
"loop": true
}
]
}
具有可配置参数的内置动画模式。
{
"animations": [
{
"type": "procedural",
"proceduralType": "wiggle",
"target": "rotation",
"enabled": true,
"frequency": 2,
"amplitude": 0.1,
"loop": true
}
]
}
在特定间隔内更改值的基于步骤的动画。
| 属性 | 类型 | 必需 | 示例 | 值范围 | 描述 |
|---|---|---|---|---|---|
| values | array | true | - | - | 要逐步遍历的值数组。 |
| stepDuration | number | true | - | - | 每个步骤的持续时间,以秒为单位。 |
| loop | boolean | false | - | - | 是否循环序列。 |
文本循环不同大小:
{
"animations": [
{
"type": "sequence",
"target": "fontSize",
"enabled": true,
"values": [24, 32, 40, 32, 24],
"stepDuration": 0.5,
"loop": true
}
]
}
沿贝塞尔曲线路径为元素添加动画。
| 属性 | 类型 | 必需 | 示例 | 值范围 | 描述 |
|---|---|---|---|---|---|
| path | string | array | true | - | - | SVG 路径数据(d 属性)或路径点数组。 |
| autoRotate | boolean | false | - | - | 是否自动旋转元素以跟随路径切线。 |
| duration | number | true | - | - | 完成完整路径的时间。 |
圆形运动:
{
"animations": [
{
"type": "path",
"target": "position",
"enabled": true,
"path": "M 100,100 a 200,200 0 1,1 0,1 Z",
"autoRotate": true,
"duration": 4,
"loop": true
}
]
}
target 属性使用点表示法来指定嵌套属性:
"x"、"y"、"rotation""scale.x"、"position.y""colors[0]"、"points[2].x"{
"target": "x" // 元素的 x 位置
"target": "scaleX" // 水平缩放
"target": "alpha" // 不透明度
"target": "fill.color" // 填充颜色(如果填充是对象)
"target": "points[0].x" // 第一个点的 x 坐标
}控制当多个动画目标相同属性时,它们是如何组合的:
{
"blendMode": "replace",
"blendWeight": 1.0
}完全替换属性值。
{
"blendMode": "add",
"blendWeight": 0.5
}添加到现有值(加权)。适用于累积偏移量。
{
"blendMode": "multiply",
"blendWeight": 1.0
}乘以现有值。适用于缩放效果。
结合不同的动画类型:
{
"id": "animated-element",
"type": "Shape",
"animations": [
{
"type": "expression",
"target": "x",
"expression": "width / 2 + Math.sin(localTime * 2) * 300",
"blendMode": "replace",
"loop": true
},
{
"type": "procedural",
"proceduralType": "wiggle",
"target": "rotation",
"frequency": 3,
"amplitude": 0.2,
"blendMode": "add",
"blendWeight": 0.5
},
{
"type": "sequence",
"target": "alpha",
"values": [1, 0.8, 1],
"stepDuration": 0.3,
"loop": true,
"blendMode": "multiply"
}
],
"keyframes": [
{
"id": "kf-1",
"time": 0,
"stateObj": { "scaleX": 1 }
},
{
"id": "kf-2",
"time": 2,
"stateObj": { "scaleX": 1.5 }
}
]
}
在此示例中:
startTime 和 duration 相对于元素的 start 时间localTime 在元素开始时为 0duration 边界enabled: truetarget 属性startTime 在元素的持续时间内{
"type": "expression",
"target": "x",
"expression": "value + (targetX - value) * 0.1"
}{
"type": "expression",
"target": "scaleY",
"expression": "1 + Math.exp(-localTime * 3) * Math.cos(localTime * 8) * 0.5"
}{
"type": "procedural",
"proceduralType": "wiggle",
"target": "x",
"frequency": 10,
"amplitude": 5
}{
"type": "expression",
"target": "alpha",
"expression": "Math.max(0, Math.min(1, (localTime - index * 0.1) * 2))"
}