概览
animated image 组件是在屏幕上加入动态效果的最简单方式:旋转的加载器、弹跳的图标、眨眼的眼睛都可以。本文会说明 PicoPixel 中的 LVGL animated image 组件如何工作:怎样添加组件,为什么每一帧都必须尺寸一致,怎样控制速度和循环,以及如何在界面运行时启动和停止它。
animated image 组件是什么?
animated image 会按顺序播放一组静态图片,就像翻页动画。每张图片都是一个 frame,快速翻动这些帧就会产生运动的错觉。你给它一组帧,告诉它播放速度以及是否循环,剩下的交给组件处理。
它非常适合单个、重复播放的动画:加载指示器、跳动的爱心、挥手图标。一个组件,一段序列,循环播放。
底层使用的是 LVGL 的 lv_animimg 组件。导出项目时,PicoPixel 会为你生成 LVGL 代码(lv_animimg_create、lv_animimg_set_src、lv_animimg_set_duration 等),你不需要手写这些代码。当前目标版本是 LVGL 8.x。
Animated image 和 sprite:该用哪一个?
这两个组件看起来相似,但解决的问题不同:
- Animated image,循环播放 一个 动画。当图形永远只做一件事时使用它,比如一直旋转的 spinner。
- Sprite,在一个组件里包含 多个 动画,并且可以在它们之间切换(Idle、Running、Happy 等)。当图形需要多个模式时使用它。
实际上,sprite 是由 animated image 构成的,每个模式在底层都是自己的 animated image。所以如果你想再加一个可切换的动画,那就是该使用 sprite 的信号。
添加 animated image 并上传帧
- 将 Animated Image 组件添加到屏幕。
- 在属性中找到 Image Set 行,然后点击 Add Image Set。
- 在 NEW 标签中,点击上传区域("Click to upload frames")并选择图片。你可以一次选择多张,支持格式为 PNG 和 JPEG(
.png、.jpeg、.jpg)。 - 点击 Continue 将帧绑定到组件。Image Set 行会显示你已有的帧数(例如 "8 frames")。
你也可以从 Assets 标签中选择之前使用过的帧集,不必再次上传。
帧会按文件名的字母顺序排列,因此请用带前导零的序列命名,例如 frame_01.png、frame_02.png、frame_03.png,以确保播放顺序正确。像 frame_2.png 这样的名称会排在 frame_10.png 之后,从而打乱动画。
animated image 至少需要 2 帧,最多可以添加 32 帧。如果需要更多动作,请考虑使用更少但更关键的关键帧,因为每一帧都会存储在设备上。
为什么所有帧必须尺寸一致
这是最重要的一条规则:每一帧都必须拥有完全相同的宽度和高度。 如果你尝试添加不同尺寸的帧,PicoPixel 会阻止并提示 "All frames must have the same dimensions."
原因很简单。组件会在同一个位置、同一个盒子里绘制每一帧。如果第 1 帧是 64×64,而第 2 帧是 80×80,播放时画面就会跳动和偏移,而不是平滑地在原地动起来。保持每一帧尺寸一致,运动效果才会干净。
上传之前先把帧缩放到一致尺寸。最快得到干净序列的方法,是在图像工具中从同一个画布导出所有帧,这样它们天然共享尺寸。
设置速度:duration
Duration 设置控制动画播放速度。它以**毫秒(ms)**为单位,表示穿过所有帧的 一次完整播放 所需时间,而不是单帧时间。默认值是 1000 ms(一秒)。
PicoPixel 会把这个时长平均分配到所有帧。因此 1000 ms 分配给 8 帧,意味着每帧显示 125 ms。想更快?降低 duration。想更慢、更舒展?提高它。
循环:播放一次还是一直播放
Repeat 设置决定动画到达末尾后会发生什么。你有两个选择:
- Infinite,动画永远循环。这是默认值,适合永远不该停止的 spinner。
- Normal(次数),动画播放指定次数后停止。设置为 3,它就播放三次,然后停在最后一帧。
界面运行时控制播放
你不必让动画自动运行:可以用 event editor 根据用户操作启动和停止它。添加一个事件,选择 Animated Image Mode action,指向你的 animated image,然后选择模式:
- Start,开始(或继续)播放。
- Stop,暂停动画。
- Restart,跳回第一帧并重新播放。
例如:让一个 "connecting..." spinner 在按钮按下前保持停止,按钮按下后 Start,任务完成后 Stop。
控制内存占用
动画本质上就是图片,而图片在小设备上会占空间。下面这些习惯能让它更高效:
- 只使用需要的帧。 平滑运动通常不需要太多精心选择之外的帧。
- 保持帧尺寸适中。 64×64 的动画比 240×240 轻得多。
- 让色深匹配显示屏(真实硬件构建的更多内容见 ESP32 tutorial)。
如果导出到固件,animated image 需要在 lv_conf.h 中启用 LV_USE_ANIMIMG。PicoPixel 会在导出的 README.md 中注明这一点,让你的构建流程(或 AI assistant)知道该打开什么。
下一步
- 需要在一个组件里放不止一个动画?升级到 sprite widget。
- 用 event editor 把动画连接到按钮或其他触发器。
- 使用 ESP32 LVGL tutorial 将完成的 UI 放到设备上。