一、背景
在开发过程中,我们可能会遇到需要控制 WebP 格式动态图播放次数的需求。例如,某些场景下只需要动图播放一次,而不是循环播放。然而,使用原生组件(如 Image
或 ImageAnimator
)时,WebP 动图会被当作普通图片处理,无法直接控制播放次数。本文将介绍两种解决方案:使用官方原生 API ImageAnimator
组件和使用第三方插件 ImageKnife
。
二、实现方式
2.1 使用官方原生 API - ImageAnimator
组件
2.2 使用第三方插件 - ImageKnife
三、使用 ImageAnimator
组件实现
官方文档指引👉:文档中心
3.1 解决思路
ImageAnimator
组件默认将 WebP 动图作为普通图片处理,无法直接控制播放次数。为了实现播放次数的控制,我们需要将 WebP 动图解析为多帧图片,然后将这些帧作为 ImageAnimator
的输入,从而实现对播放次数的精确控制。
3.2 示例代码
以下是使用 ImageAnimator
组件实现 WebP 动图播放一次的核心代码:
import { image } from '@kit.ImageKit';
@Entry
@Component
struct ImageAnimatorExample {
@State state: AnimationStatus = AnimationStatus.Initial; // 控制动画状态
imageFrames: Array<ImageFrameInfo> = []; // 存储解析后的帧信息
isSelected: boolean = false; // 控制点击状态
async aboutToAppear() {
// 解析 WebP 动图,获取帧信息
this.imageFrames = await this.getImageFrameInfoFromMedia($r('app.media.duck'));
}
build() {
Column({ space: 10 }) {
// ImageAnimator 组件
ImageAnimator()
.images(this.imageFrames) // 设置帧信息
.state(this.state) // 设置动画状态
.iterations(1) // 设置播放次数为 1
.width(400)
.height(400)
.margin({ top: 100 })
.onClick(() => {
// 点击图片,开始播放动画
this.isSelected = true;
this.state = AnimationStatus.Running;
});
// 重置按钮
Button('Reset')
.onClick(() => {
// 点击按钮,停止动画并重置状态
this.isSelected = false;
this.state = AnimationStatus.Stopped;
});
}
.width('100%')
.height('100%');
}
// 解析 WebP 动图,获取帧信息
private async getImageFrameInfoFromMedia(resource: Resource) {
// 获取 WebP 文件的二进制数据
let unit8Array = await getContext(this)?.resourceManager?.getMediaContent({
bundleName: resource.bundleName,
moduleName: resource.moduleName,
id: resource.id,
});
// 创建 ImageSource 对象
let imageSource = image.createImageSource(unit8Array.buffer.slice(0, unit8Array.buffer.byteLength));
// 获取所有帧的 PixelMap
let createPixelMap: Array<image.PixelMap> = await imageSource.createPixelMapList({
desiredPixelFormat: image.PixelMapFormat.RGBA_8888,
});
// 获取每帧的延迟时间
let delayList = await imageSource.getDelayTimeList();
await imageSource.release();
// 构建帧信息数组
let imageFrameInfoArray: Array<ImageFrameInfo> = [];
for (let i = 0; i < createPixelMap.length; i++) {
imageFrameInfoArray.push({
src: createPixelMap[i],
duration: delayList[i],
});
}
return imageFrameInfoArray;
}
}
3.3 实现效果
点击“Reset”按钮后,动画停止并重置状态展示图片。
点击图片后,动图开始播放,且只播放一次。
图2
四、使用第三方插件 ImageKnife
4.1 解决思路
ImageKnife
是一个功能强大的第三方插件,支持对动图的精细控制,包括播放次数、播放状态等。通过 ImageKnife
,我们可以更简单地实现 WebP 动图的播放控制。
4.2 三方库介绍及安装
4.2.1 简介:
这是专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单
entry/src/main/ets/pages/ImageAnimatorPage.ets · OpenHarmony-TPC/ImageKnife - Gitee.com
4.2.2 安装:
ohpm i @ohos/imageknife
4.3 示例代码
以下是使用 ImageKnife
实现 WebP 动图播放的核心代码:
import { AnimatorOption, ImageKnifeAnimatorComponent } from '@ohos/imageknife';
@Entry
@Component
struct ImageAnimatorExample {
@State animatorOption: AnimatorOption = {
state: AnimationStatus.Running, // 动画状态
iterations: 3, // 播放次数
};
build() {
Column() {
// ImageKnifeAnimatorComponent 组件
ImageKnifeAnimatorComponent({
imageKnifeOption: {
loadSrc: $r('app.media.duck'), // 加载 WebP 动图
},
animatorOption: this.animatorOption, // 设置动画选项
})
.width(300)
.height(300)
.backgroundColor(Color.Orange)
.margin({ top: 30 });
}
.width('100%')
.height('100%');
}
}
4.4 实现效果
动图自动开始播放,控制播放3次。
通过
animatorOption
可以灵活控制播放次数和状态。
图1
🚀🚀🚀 踩坑不易,还希望各位大佬支持一下
📃 鸿蒙土拨鼠充电开源项目:
✍GitHub开源项目地址👉:https://github.com/cheinlu/groundhog-charging-system
📃 鸿蒙土拨鼠大理石开源项目
✍GitHub开源项目地址👉https://github.com/lusson-luo/HarmonyOS-groundhog-marble-system
最后:👏👏😊😊😊👍👍