动画
animate 块将动画附加到某个属性。
每当该属性的值发生变化时,值会随时间移动到其目标值,而不是立即跳变过去:
export component Example inherits Window { background: area.pressed ? blue : red; animate background { duration: 250ms; } area := TouchArea {}}animate 块是元素体内的语句。
它可以出现在任何元素上——根元素、子元素或子组件的根元素。
全局对象不得包含 animate 块;这样做会构成编译错误。
animate 关键字后跟一个或多个属性名,以及一个由花括号界定、包含若干绑定的主体:
animate <property> { // field: value;}- 每个名字都指向
animate块所在元素的一个属性。 此处不允许使用诸如other.property这样的限定名;引用另一个元素的属性会构成编译错误。 - 主体中只能包含
field: value;形式的绑定。 任何其他语句都会构成编译错误。 - 仅有的字段为
delay、duration、easing、iteration-count、direction和enabled。 绑定任何其他名字都会构成编译错误。 每个字段都是可选的。
将两个 animate 块附加到同一个属性会构成编译错误。
可动画的属性
Section titled “可动画的属性”只有当属性的类型为以下之一时,才可以对其应用动画:
int、float、length、physical-length、color、brush 或 angle。
对任何其他类型的属性应用动画——例如 string、bool、image 或结构体属性——都会构成编译错误。
该属性还必须是可在该元素上设置的。 对无法赋值的属性应用动画(例如另一个组件的私有属性)会构成编译错误。
对多个属性应用动画
Section titled “对多个属性应用动画”列出以逗号分隔的多个名字,会对每个名字应用相同的动画:
animate x, y { duration: 100ms; easing: ease-out-bounce; }等价于:
animate x { duration: 100ms; easing: ease-out-bounce; }animate y { duration: 100ms; easing: ease-out-bounce; }每个被命名的属性都必须满足上述规则,即可动画且可设置。
durationdefault: 0ms
动画开始前等待的时间。
duration
Section titled “duration”durationdefault: 0ms
动画完成所需的时间。
iteration-count
Section titled “iteration-count”floatdefault: 1
动画运行的次数。负值会使其永远运行。 允许使用小数值。若要获得与属性变化无关、连续运行的值, 请参见 `animation-tick()`。
easing
Section titled “easing”easingdefault: linear
在动画时长内应用的 缓动曲线。 可视化参考请见
easings.net。
direction
Section titled “direction”enum AnimationDirectiondefault: the first enum value
每个迭代播放的方向。
enabled
Section titled “enabled”booldefault: true
动画是否运行。当为 false 时,变化会立即将属性设置为
目标值,没有延迟、缓动或迭代。
在过渡内部,animate 块则描述状态改变时属性如何移动。
在那里名字可以是限定名,例如 animate root.background { ... },因此过渡可以为嵌套元素的属性应用动画。
字段与上文相同。
关于过渡的书写位置以及它们如何选择应用哪个动画,请参见状态与过渡。
spring 缓动曲线接受一个可选的 bounce 参数,例如 spring(0.4)。
bounce 必须是介于 -1 和 1 之间的数字字面量;任何其他参数都会构成编译错误。
只写 spring 与 spring(0) 相同。
由于 duration 有助于定义弹簧的固有频率,动画并不保证在 duration 流逝后完成。
如果 bounce 接近 0,动画将接近完成;然而 bounce 离 0 越远,动画所需的时间就越长。
具有有限 iteration-count 的弹簧无法永远振荡。它的总时长最多被限制为(iteration-count + 9)x duration。
当 iteration-count 设为 -1 时,该限制永远不适用。
直到 iteration-count 的每一次迭代都以 bounce 运行。
如果弹簧在最后一次迭代的 duration 结束时仍未稳定,它会被重新阻尼,使其在额外的 9x duration 内稳定(从最后一次迭代开始算起总计 10x duration)。
iteration-count 为 -1 会使动画无限进行,bounce 为 1 会使循环无缝衔接。
原因请见下方的 迭代与方向。
与其他缓动曲线不同,弹簧在重新定向时会保持速度,因此它会平滑地继续移动,而不是跳变到一条新曲线上。
Bounce 取值
Section titled “Bounce 取值”bounce= 0:值尽可能快地接近目标而不越过它(临界阻尼)。bounce> 0:值快速接近目标但会越过它(欠阻尼)——越接近 1,稳定所需的时间越长。bounce< 0:值缓慢接近目标而不越过它(过阻尼)。
export component Example inherits Window { width: 200px; height: 100px;
ball := Rectangle { x: area.pressed ? 150px : 0px; width: 50px; height: 50px; border-radius: 25px; background: blue; animate x { duration: 500ms; easing: spring(0.5); } } area := TouchArea {}}弹簧动画依赖固有频率(ω₀ = 2π/duration)和 阻尼比(ζ = 1 - bounce)来驱动质量-弹簧-阻尼器模型。
由于弹簧不保证在 duration 内稳定,重复的弹簧动画
(iteration-count 大于 1)会在恰好 duration 时进入下一次迭代,而不是
等待弹簧完全稳定。
弹簧的速度总会延续到下一次迭代。其位置会怎样 取决于该次迭代是否也翻转了方向:
- 同方向重复会将位置重置到动画的起点,就像 重复的缓动曲线动画从头重新开始一样。
- 方向翻转(
alternate或alternate-reverse)则会从弹簧 实际所在的位置继续,因此值会平滑地继续移动,而不是突然跳到另一端。
无限连续弹簧
Section titled “无限连续弹簧”如果 bounce 设为 1,弹簧的周期恰好为 duration。如果将一个对象从 x = 0px 动画到 x = 100px,
那么在恰好 duration 时会有 x == 0px。由于下一次迭代恰好从 duration 开始,只要 direction
不是 alternate 或 alternate-reverse,iteration-count 为 -1 就会形成无限连续弹簧。如果 bounce 设为
除 1 以外的值,位置就不会恰好位于动画的两端,并且会出现明显的跳变。
© 2026 SixtyFPS GmbH