关于 makepad-2.0-animation
面向 Makepad 2.0 界面开发者的动画参考技能,介绍 Animator 轨道、状态转换和着色器属性动画,并说明它与矢量 Tween 的区别。
主要功能
- 01独立动画组
- 02状态转换与循环模式
- 03缓动函数
- 04着色器 instance 属性动画
- 05控件 Animator 支持说明
适用场景
- 01制作按钮悬停动画
- 02创建切换和焦点状态转换
- 03构建基于着色器的加载动画
- 04选择 Animator 或矢量 Tween
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zhanghandong/ makepad-skills --skill makepad-2.0-animation安装后在 Claude Code 中输入/makepad-2.0-animation确认已加载。
附带文件references/animator-reference.md
详细介绍
Makepad 2.0 动画技能
版本: makepad-widgets(dev 分支)| 最后更新: 2026-03-03
概述
Animator 系统可以随时间驱动 instance() 着色器变量,从而实现悬停效果、过渡和循环动画。它使用名为“组”的独立动画轨道,这些轨道会同时运行。
文档
详细文档请参阅本地文件:
./references/animator-reference.md- 完整的 Animator API、播放类型、缓动函数和示例
重要:文档完整性检查
回答问题前,Claude 必须:
- 阅读上方列出的相关参考文件
- 如果文件读取失败或文件为空:
- 告知用户:“参考文档不完整。仍将基于 SKILL.md 中的模式回答。”
- 仍根据 SKILL.md 中的模式和内置知识作答
- 如果参考文件存在,则在回答中结合其内容
关键:控件对 Animator 的支持情况
并非所有控件都支持 animator! 将 animator: Animator{...} 添加到不支持它的控件上会被静默忽略——不会报错,也不会发生动画,什么都不会发生。
支持 Animator 的控件
View、SolidView、RoundedView、ScrollXView、ScrollYView、ScrollXYView、Button、ButtonFlat、ButtonFlatter、CheckBox、Toggle、RadioButton、LinkLabel、TextInput
不支持 Animator 的控件
Label、H1-H4、P、TextBox、Image、Icon、Markdown、Html、Slider、DropDown、Splitter、Hr、Filler
**要为 Label 添加动画:**将它放在带有 animator 的 View 中:
View{
width: Fit height: Fit
animator: Animator{
hover: {
default: @off
off: AnimatorState{ from: {all: Forward {duration: 0.15}} apply: {draw_bg: {hover: 0.0}} }
on: AnimatorState{ from: {all: Forward {duration: 0.15}} apply: {draw_bg: {hover: 1.0}} }
}
}
label := Label{text: "Animated via parent"}
}
Animator 结构
animator: Animator{
<group_name>: {
default: @<state_name>
<state_name>: AnimatorState{
from: { ... }
ease: <EaseFunction>
redraw: true
apply: { ... }
}
<state_name>: AnimatorState{ ... }
}
<group_name>: { ... }
}
组
每个组都是独立的动画轨道。常见的组:
| 组 | 用途 | 典型状态 |
|---|---|---|
hover | 鼠标悬停进入/移出 | off、on |
focus | 键盘焦点 | off、on |
active | 切换/选中状态 | off、on |
disabled | 禁用状态 | off、on |
time | 连续循环 | off、on |
多个组可以同时运行动画,互不干扰。
from 块
控制过渡时序。键表示要从其过渡的状态,或使用 all 作为兜底项。
// From any state, animate over 0.2 seconds
from: {all: Forward {duration: 0.2}}
// Instant from any state
from: {all: Snap}
// Different timing depending on origin
from: {
all: Forward {duration: 0.1}
down: Forward {duration: 0.01}
}
播放类型
| 类型 | 描述 | 示例 |
|---|---|---|
Forward {duration: 0.2} | 单次正向播放 | 悬停过渡 |
Snap | 立即跳转,不播放动画 | 初始化默认状态 |
Loop {duration: 1.0} | 循环动画 | 加载指示器 |
ReverseLoop {duration: 1.0} | 往返循环 | 脉冲效果 |
BounceLoop {duration: 1.0} | 来回弹跳 | 弹跳动画 |
缓动函数
| 函数 | 描述 |
|---|---|
Linear | 匀速 |
InQuad / OutQuad / InOutQuad | 二次缓动 |
InCubic / OutCubic / InOutCubic | 三次缓动 |
InQuart / OutQuart / InOutQuart | 四次缓动 |
InQuint / OutQuint / InOutQuint | 五次缓动 |
InSine / OutSine / InOutSine | 正弦缓动 |
InExp / OutExp / InOutExp | 指数缓动 |
InCirc / OutCirc / InOutCirc | 圆形缓动 |
InElastic / OutElastic / InOutElastic | 弹性弹簧效果 |
InBack / OutBack / InOutBack | 超调 |
InBounce / OutBounce / InOutBounce | 弹跳 |
用法:在 AnimatorState 中设置 ease: OutCubic(可选,默认为 Linear)。
apply 块
要过渡到的目标值。其结构与控件的着色器属性一致。
// Animate single properties
apply: {
draw_bg: {hover: 1.0}
}
// Animate multiple properties
apply: {
draw_bg: {hover: 1.0 color: #f00}
draw_text: {color: #fff}
}
**重要:**只有 instance() 着色器变量可以添加动画。uniform() 变量不能添加动画。
完整的悬停按钮示例
use mod.prelude.widgets.*
let HoverCard = RoundedView{
width: Fill height: Fit
padding: 16
new_batch: true
cursor: Hand
draw_bg +: {
instance hover: 0.0
color: mix(#2a2a3d, #3a3a5d, self.hover)
border_radius: 8.0
}
animator: Animator{
hover: {
default: @off
off: AnimatorState{
from: {all: Forward {duration: 0.15}}
apply: {draw_bg: {hover: 0.0}}
}
on: AnimatorState{
from: {all: Forward {duration: 0.15}}
apply: {draw_bg: {hover: 1.0}}
}
}
}
title := Label{text: "Hover me" draw_text.color: #fff}
}
要点:
- 带背景且支持悬停的项目必须设置
new_batch: true cursor: Hand会在悬停时显示指针光标instance hover: 0.0用于声明可添加动画的变量mix(color1, color2, self.hover)会在颜色之间插值
时间线动画(关键帧)
对于多步动画,请使用 timeline():
animator: Animator{
time: {
default: @off
on: AnimatorState{
from: {all: Loop {duration: 2.0}}
apply: {
draw_bg: {
rotation: timeline(){
snap(0.0)
snap(6.28)
}
}
}
}
}
}
加载旋转动画模式
let Spinner = View{
width: 40 height: 40
draw_bg +: {
instance rotation: 0.0
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
let cx = self.rect_size.x * 0.5
let cy = self.rect_size.y * 0.5
let r = min(cx, cy) * 0.8
sdf.arc(cx, cy, r, self.rotation, self.rotation + 4.5, 3.0)
sdf.stroke(#4488ff, 2.5)
return sdf.result
}
}
animator: Animator{
time: {
default: @on
on: AnimatorState{
from: {all: Loop {duration: 1.0}}
apply: {
draw_bg: {
rotation: timeline(){
snap(0.0)
snap(6.28318)
}
}
}
}
}
}
}
Animator 与 Vector Tween 的区别
Makepad 有两套独立的动画系统:
| 特性 | Animator(本技能) | Tween(参见 makepad-2.0-vector) |
|---|---|---|
| 目标 | Widget 着色器的 instance 变量 | SVG 形状属性(fill、cx、opacity...) |
| 语法 | animator: Animator{...} 块 | 属性值:opacity:Tween{...} |
| 触发方式 | 状态转换(悬停、焦点) | 渲染时自动触发 |
| 循环 | from 中的 Loop {duration: 1.0} | loop_:true(布尔值,不是字符串!) |
| 用途 | UI 交互(悬停、点击) | SVG/Vector 图形动画 |
使用 Animator 的场景: 按钮悬停效果、切换状态、加载旋转动画(基于着色器) 使用 Vector Tween 的场景: SVG 路径动画、脉冲指示器、移动圆点、颜色过渡
Tween 的详细信息请参见 makepad-2.0-vector 技能。
最佳实践
- 始终为带有背景且具有悬停动画的 View 添加
new_batch: true - 需要动画的内容都使用
instance变量 - 组名应与语义用途相匹配(悬停、焦点、活动状态)
- 状态转换使用 Forward,瞬时状态变化使用 Snap
- 对于初始处于非活动状态的状态,设置
default: @off - Label 无法添加动画——如果需要为文本添加动画,请将其包裹在 View 中
- 保持动画时长较短:悬停动画为 0.1-0.3s,基于时间的动画则为 0.5-2.0s