鸿蒙(HarmonyOS)开发中 帧动画 的使用解析

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、帧动画核心概念

1. 功能定位
  • 作用:通过连续播放静态图像(帧)实现动态效果,适用于复杂动画场景(如加载动画、游戏角色动作)。
  • 与属性动画区别
    特性帧动画属性动画
    实现方式逐帧图像切换属性值插值计算
    性能依赖资源体积更高效(硬件加速)
    适用场景复杂序列动画(如电影胶卷)简单过渡效果(如缩放、旋转)
2. 实现方式对比
方式API/组件优点缺点
ImageAnimator组件<image-animator>声明式UI,简单易用灵活性较低
Animator逐帧回调@ohos.animator实时控制每一帧需手动计算插值
requestAnimationFrameJavaScript原生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. 性能优化:离屏渲染

步骤

  1. 使用LazyForEach加载大量帧图片。
  2. 预加载图片资源到内存:
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兼容旧版本

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值