【HarmonyOS NEXT】控制 WebP 格式动图播放次数的实现方案

发布于:2025-03-01 ⋅ 阅读:(118) ⋅ 点赞:(0)

一、背景

在开发过程中,我们可能会遇到需要控制 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

最后:👏👏😊😊😊👍👍  


网站公告

今日签到

点亮在社区的每一天
去签到