本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、帧动画核心概念
1. 功能定位
- 作用:通过连续播放静态图像(帧)实现动态效果,适用于复杂动画场景(如加载动画、游戏角色动作)。
- 与属性动画区别:
特性 帧动画 属性动画 实现方式 逐帧图像切换 属性值插值计算 性能 依赖资源体积 更高效(硬件加速) 适用场景 复杂序列动画(如电影胶卷) 简单过渡效果(如缩放、旋转)
2. 实现方式对比
| 方式 | API/组件 | 优点 | 缺点 |
|---|---|---|---|
| ImageAnimator组件 | <image-animator> | 声明式UI,简单易用 | 灵活性较低 |
| Animator逐帧回调 | @ohos.animator | 实时控制每一帧 | 需手动计算插值 |
| requestAnimationFrame | JavaScript原生API | 兼容性强 | 性能较差 |
二、基础使用与API详解
1. ImageAnimator组件
功能:内置帧动画播放器,支持图片序列播放。
示例代码:
// 定义帧图片资源
@State frames: Array<Resource> = [
$r('app.media.frame1'),
$r('app.media.frame2'),
$r('app.media.frame3')
];
build() {
ImageAnimator({
images: this.frames,
duration: 1000, // 总时长(ms)
iteration: 3, // 播放次数(-1表示无限)
reverse: false // 是否反向播放
})
.width(200)
.height(200)
.onStart(() => console.log('动画开始'))
.onPause(() => console.log('动画暂停'))
}
关键API:
images:图片资源数组,支持Resource或网络路径。duration:单次播放总时长(所有帧共享)。iteration:播放次数(-1表示无限循环) 。
2. Animator逐帧控制
适用场景:需要精确控制每一帧属性的动态效果(如抛物线运动)。
示例代码:
import { Animator, AnimatorOptions } from '@ohos.animator';
@State translateX: number = 0;
@State translateY: number = 0;
// 创建Animator实例
private animator: Animator | null = null;
aboutToAppear() {
const options: AnimatorOptions = {
duration: 1500,
begin: 0, // 起始值
end: 300 // 结束值
};
this.animator = this.getUIContext().createAnimator(options);
// 帧回调
this.animator.onFrame = (value: number) => {
this.translateX = value;
this.translateY = Math.pow(value / 10, 2); // 抛物线轨迹
};
}
// 触发动画
Button('播放')
.onClick(() => this.animator?.play())
优势:
- 可实时响应事件(如暂停/继续)。
- 支持复杂物理效果(如弹性、重力模拟)。
三、高级功能实战
1. 复合帧动画(序列+属性)
场景:图片切换的同时叠加缩放效果。
实现:
@State currentFrame: Resource = $r('app.media.frame1');
@State scale: number = 1;
// 使用定时器切换帧
private timer: number = setInterval(() => {
this.currentFrame = this.frames[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.frames.length;
}, 100);
// 叠加属性动画
animateTo({ duration: 500 }, () => {
this.scale = 1.5;
})
效果:图片序列播放时同步放大。
2. 性能优化:离屏渲染
步骤:
- 使用
LazyForEach加载大量帧图片。 - 预加载图片资源到内存:
async preloadImages() {
await Promise.all(this.frames.map(frame => loadImage(frame)));
}
3. 动态帧率控制
API 12+:通过expectedFrameRateRange设置目标帧率:
ImageAnimator({
images: this.frames,
expectedFrameRateRange: {
expected: 60, // 目标帧率
min: 30, // 最低帧率
max: 120 // 最高帧率
}
})
适用场景:适配不同设备性能
四、调试与常见问题
1. 内存泄漏预防
- 释放资源:在
aboutToDisappear中清除定时器/Animator:
aboutToDisappear() {
clearInterval(this.timer);
this.animator = null;
}
2. 性能监控工具
console.time('render');
// 渲染逻辑...
console.timeEnd('render'); // 输出耗时
3. 高频问题解决
| 问题 | 解决方案 |
|---|---|
| 图片闪烁 | 检查帧图片尺寸是否一致 |
| 动画卡顿 | 降低帧率或使用硬件加速(hardwareAccelerated) |
| 资源加载失败 | 使用try/catch包裹loadImage调用 |
五、总结对比
| 方案 | 推荐场景 | 性能 | 灵活性 |
|---|---|---|---|
| ImageAnimator | 简单序列动画(如加载图标) | 高 | 低 |
| Animator回调 | 复杂轨迹动画(如游戏角色) | 中 | 极高 |
| requestAnimationFrame | 兼容旧版本 | 低 | 高 |
1213

被折叠的 条评论
为什么被折叠?



