鸿蒙开发 —— UI动画开发之LibPag

📑往期推文全新看点(文中附带最新·鸿蒙全栈学习笔记)

✒️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

✒️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

✒️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

✒️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

✒️ 记录一场鸿蒙开发岗位面试经历~

✒️ 持续更新中……


简介

PAG(便携式动画图形)文件的官方渲染库,可跨多个平台本地渲染 After Effects 动画。

演示

编译运行

1、通过IDE(DevEco Studio:4.1.500)工具下载依赖SDK,Tools->SDK Manager->OpenHarmony SDK 把native选项勾上下载,API版本>=10

2、开发板选择RK3568,ROM下载地址. 选择开发板类型是rk3568,请使用新的版本

3、使用git clone下载源码,不要直接通过gitee网页的方式下载

下载安装

ohpm install @ohos/libpag

使用说明

把so和a文件放入路径ohos_libpag\libpag\libs\arm64-v8a下
把so和a文件放入路径ohos_libpag\libpag\src\main\cpp\thirdparty\pag\arm64-v8a\lib下

将三方库加入工程中

target_link_libraries(native_libpag PRIVATE N A T I V E R E N D E R R O O T P A T H / t h i r d p a r t y / p a g / {NATIVERENDER_ROOT_PATH}/thirdparty/pag/ NATIVERENDERROOTPATH/thirdparty/pag/{OHOS_ARCH}/lib/libpag.so)
target_link_libraries(native_libpag PRIVATE N A T I V E R E N D E R R O O T P A T H / t h i r d p a r t y / p a g / {NATIVERENDER_ROOT_PATH}/thirdparty/pag/ NATIVERENDERROOTPATH/thirdparty/pag/{OHOS_ARCH}/lib/libtgfx.a)

将三方库的头文件加入工程中

target_include_directories(native_libpag PRIVATE N A T I V E R E N D E R R O O T P A T H / t h i r d p a r t y / p a g / {NATIVERENDER_ROOT_PATH}/thirdparty/pag/ NATIVERENDERROOTPATH/thirdparty/pag/{OHOS_ARCH}/include)

在前端中使用

import { newPAGFile, newPAGView,newPAGComposition  } from '@ohos/libpag';
import { common } from '@kit.AbilityKit';
import XComponentContext from "../interface/XComponentContext";

enum EnumPagPlayState {
  ePagPlayNull,
  ePagPlayPlaying,
  ePagPlayPause,
  ePagPlayComplete,
  ePagPlayStop
};

@Entry
@Component
struct pagViewPage {
  private xcomponentId: string = 'xcomponentId0';
  private PAGFile = new newPAGFile();
  private PAGView = new newPAGView();
  private xComponentContext: XComponentContext | undefined = undefined;
  private pagCompoition: newPAGComposition | undefined = undefined;
  private componentIndex: number = 0;
  @State isPause: boolean = true;
  @State currentStatus: string = "init";

  aboutToAppear(): void {
    this.pagCompoition = new newPAGComposition(this.xcomponentId);
    console.info('aboutToAppear');
  }

  /**
   * 页面销毁时释放动画资源
   */
  aboutToDisappear(): void {
    console.info('aboutToDisappear');
  }

  buildComposition(): void {
    let context = getContext(this) as common.UIAbilityContext;
    let filePath = context.resourceDir ;
    this.PAGFile.loadFromPath(filePath + '/' + 'cat.pag');
    this.PAGView.setComposition();
    this.PAGView.setRepeatCount(0);
    this.PAGView.setSurface();
  }

  build() {
    Column() {
      Row() {
        Text('Native XComponent Sample')
          .fontSize('24fp')
          .fontWeight(500)
          .margin({
            left: 24,
            top: 12
          })
      }
      .margin({ top: 24 })
      .width('100%')
      .height(56)

      Column({ space: 10 }) {
        XComponent({
          id: `${this.xcomponentId}`,
          type: XComponentType.SURFACE,
          libraryname: 'native_libpag'
        })
          .onLoad((xComponentContext) => {
            this.PAGView.init(this.xcomponentId);
            this.xComponentContext = xComponentContext as XComponentContext;
            this.currentStatus = "index";
            this.buildComposition();
          })
          .onDestroy(() => {
            console.log('onDestroy');
          })
          .id("xcomponent"+this.componentIndex)

        Text(this.currentStatus)
          .fontSize('24fp')
          .fontWeight(500)
      }
      .onClick(() => {
      })
      .margin({
        top: 27,
        left: 12,
        right: 12
      })
      .height('40%')
      .width('90%')

      Row() {
        Button('播放')
          .onClick(() => {
            this.isPause = true;
            const state = this.PAGView.getState();
            if (state === EnumPagPlayState.ePagPlayPause) {
              this.PAGView.resume();
            } else {
              this.PAGView.play();
            }
          })
        Button(this.isPause ? '暂停' : '继续播放')
          .onClick(() => {
            const state = this.PAGView.getState();
            if (state === EnumPagPlayState.ePagPlayStop || state === EnumPagPlayState.ePagPlayComplete) {
              return
            }
            if (this.isPause) {
              this.PAGView.pause();
            } else {
              this.PAGView.resume();
            }
            this.isPause = !this.isPause;
          })
        Button('停止')
          .onClick(() => {
            this.isPause = true;
            const state = this.PAGView.getState();
            if (state === EnumPagPlayState.ePagPlayComplete) {
              return;
            }
            this.PAGView.stop();
          })
      }.margin({ top: 5 })

    }
    .width('100%')
    .height('100%')
  }
}
XComponentContext
export default interface XComponentContext {
  drawPattern(): void;

  getStatus(): XComponentContextStatus;
};

interface XComponentContextStatus {
  hasDraw: boolean,
  hasChangeColor: boolean,
};

PAGView

播放

PAGView.play();

暂停

PAGView.pause();

继续播放

PAGView.resume();

停止

PAGView.stop();

是否播放

PAGView.isPlaying();

获取动画状态

PAGView.getState();

为PAGView设置一个新的PAG组合以作为内容呈现

PAGView.setComposition();

设置动画的重复次数

PAGView.setRepeatCount(2);

设置缩放模式

PAGView.setScaleMode(PAGScaleMode.None);

返回当前缩放模式

PAGView.scaleMode();

设置矩阵变换

PAGView.setMatrix(1,0.5,0,0,1,0);

获取当前帧

PAGView.currentFrame();

设置播放的起始帧数

PAGView.setProgress(20);

设置cacheEnabled属性的值

PAGView.setCacheEnabled(true);

如果设置为true,PAG渲染器将缓存每个层的静态内容的内部位图表示

PAGView.cacheEnabled();

设置cacheScale属性的值。

PAGView.setCacheScale(0);

该值定义内部图形缓存的比例因子,范围从0.0到1.0。

PAGView.cacheScale();

设置帧率

PAGView.setMaxFrameRate(50);

渲染的帧率

PAGView.maxFrameRate();

设置useDiskCache属性的值

PAGView.setUseDiskCache(true);

如果设置为true,PAG将把相关的渲染数据缓存到磁盘文件中,例如视频合成的解码图像帧

PAGView.useDiskCache();

返回当前PAGView的PAG组合以呈现为内容

PAGView.getComposition();

返回位于指定点下的层数组

PAGView.getLayersUnderPoint(200,200);

设置videoEnabled属性的值

PAGView.setVideoEnabled(true);

如果设置为false,PAGView将跳过视频合成的渲染

PAGView.videoEnabled();

从指定的路径加载一个pag文件,如果该文件不存在或数据不是pag文件,则返回false

PAGView.setPath(filePath + '/' + 'cat.pag');

由setPath()设置的pag文件的路径字符串

PAGView.getPath()

返回播放位置的当前进度,值从0.0到1.0

PAGView.getProgress()

当前合成的持续时间(以微秒为单位)

PAGView.duration()

调用此方法可立即渲染当前位置

PAGView.flush()

添加播放状态的监听

PAGView.addPlayStateListener(playFuc)
PAGView.addPlayStateListener(pauseFuc)
PAGView.addPlayStateListener(stopFuc)

添加重复次数的监听

PAGView.addRepeatCountListener(RepeatCountFuc)

添加当前帧的监听

PAGView.addCurrentFrameListener(CurrentFrame)

移除播放状态的监听

PAGView.removePlayStateListener()
PAGView.addPlayStateListener(pauseFuc)
PAGView.addPlayStateListener(stopFuc)

移除重复次数的监听

PAGView.removeRepeatCountListener()

移除当前帧的监听

PAGView.removeCurrentFrameListener()

立即释放pag视图创建的缓存

PAGView.freeCache()

返回当前矩阵的副本

PAGView.matrix()

返回动画播放的总次数

PAGView.repeatCount();

PAGFile

设置此PAGFile的持续时间。

PAGFile.setDuration(50);

加载pag文件,仅支持沙箱路径

PAGFile.loadFromPath(filePath + '/' + 'cat.pag');

设置图层的开始时间

PAGFile.setStartTime(0);

该层的持续时间

PAGFile.duration();

可替换图像的数量

pagFile.numImages();

可编辑文本的数量

pagFile.numTexts();

视频作品的数量

pagFile.numVideos();

此文件的路径字符串

pagFile.path();

标记级别

pagFile.maxSupportedTagLevel()

返回此PAGFile中可编辑层的索引

pagFile.getEditableIndices(3);

指示当文件的持续时间更改时,如何拉伸原始持续时间以适应目标持续时间

pagFile.timeStretchMode();

此pag文件所需的标记级别

pagFile.tagLevel();

设置此文件的timeStretchMode。

PAGFile.setTimeStretchMode(0);

PAGComposition

创建一个具有指定大小的空 PAGComposition

PAGComposition.init(0,0);

将 PAGLayer 添加到当前 PAGComposition 的指定索引处

PAGComposition.addLayerAt(0);

返回指定索引处存在的子图层

PAGComposition.getLayerAt(0);

将 PAGLayer 添加到当前 PAGComposition 的顶部

PAGComposition.addLayer();

从当前PAG组合中删除指定索引处的PAG层。

pagCompoition.removeLayerAt(0);

从当前PAG组合中删除指定的PAG层。

PAGComposition.removeLayer();

从当前PAG组合中删除所有PAG层。

PAGComposition.removeAllLayers();

返回PAGComposition的子层数。

PAGComposition.numChildren();

接口说明

PAGView

接口名参数返回值说明
Initid: stringvoid初始化配置
setCompositionvoid设置一个新的PAGComposition,让PAGPlayer作为内容呈现
playvoid开始播放接口
pausevoid在当前位置暂停动画
resumevoid在当前位置继续播放动画
stopvoid停止播放
isPlayingnumber判断动画是否播放
getStatenumber获取动画状态
setRepeatCountcount:numbervoid设置动画播放次数
repeatCountnumber返回动画播放的总次数
setScaleModemode: numbervoid设置缩放模式
scaleModenumber返回当前缩放模式
setMatrixa: number,b: number,c:number,d:number,tx: number,ty:numbervoid设置矩阵变换
setProgressvalue: numbervoid设置播放的起始帧数
setCacheEnabledvalue: booleanvoid设置cacheEnabled属性的值
cacheEnabledboolean如果设置为true,PAG渲染器将缓存每个层的静态内容的内部位图表示
setCacheScalevalue: numbervoid设置cacheScale属性的值
cacheScaleboolean该值定义内部图形缓存的比例因子,范围从0.0到1.0
setMaxFrameRatevalue: numbervoid设置帧率
maxFrameRatenumber渲染的帧率
setUseDiskCachevalue: booleanvoid设置useDiskCache属性的值
useDiskCacheboolean如果设置为true,PAG将把相关的渲染数据缓存到磁盘文件中,例如视频合成的解码图像帧
getCompositionPAGComposition返回当前PAGView的PAG组合以呈现为内容
getLayersUnderPointlocalX: number,localY: numberPAGLayer[]返回位于指定点下的层数组
setVideoEnabledvalue: booleanvoid设置videoEnabled属性的值
videoEnabledboolean如果设置为false,PAGView将跳过视频合成的渲染
setPathpath: stringboolean从指定的路径加载一个pag文件,如果该文件不存在或数据不是pag文件,则返回false
getPathString由setPath()设置的pag文件的路径字符串
getProgressnumber返回播放位置的当前进度,值从0.0到1.0
durationnumber当前合成的持续时间(以微秒为单位)
flushboolean调用此方法可立即渲染当前位置
addPlayStateListenercb: (state: number) => voidnumber添加播放状态的监听
addRepeatCountListenercb: (state: number) => voidnumber添加播放次数的监听
addCurrentFrameListenercb: (state: number) => voidnumber添加对当前帧的监听
removePlayStateListenervoid移除播放状态的监听
removeRepeatCountListenervoid移除播放次数的监听
removeCurrentFrameListenervoid移除对当前帧的监听
freeCachevoid立即释放pag视图创建的缓存
matrixMatrix返回当前矩阵的副本

PAGFile

接口名参数返回值说明
setDurationnumbervoid设置此PAGFile的持续时间
loadFromPathstringPAGFile从指定路径加载pag文件(使用沙箱路径时,请将文件放在项目resources目录下的resfile文件夹内)
setStartTimenumbervoid设置图层的开始时间
durationnumber该层的持续时间
numImagesnumber可替换图像的数量
numTextsnumber可编辑文本的数量
numVideosnumber视频作品的数量
pathString此文件的路径字符串
maxSupportedTagLevelnumber标记级别
getEditableIndiceslayerType: numbernumber[]返回此PAGFile中可编辑层的索引
timeStretchModenumber指示当文件的持续时间更改时,如何拉伸原始持续时间以适应目标持续时间
tagLevelnumber此pag文件所需的标记级别
setTimeStretchModevalue: numbervoid设置此文件的timeStretchMode。

PAGComposition

接口名参数返回值说明
initwidth: number, height: numbervoid创建一个具有指定大小的空 PAGComposition
addLayerAtindex: numbervoid将 PAGLayer 添加到当前 PAGComposition 的指定索引处
addLayervoid将 PAGLayer 添加到当前 PAGComposition 的顶部
getLayerAtindex: numbervoid返回存在于指定索引处的子层
removeLayervoid从当前 PAGComposition 中删除指定的 PAGLayer
removeAllLayersvoid从当前 PAGComposition 中删除所有 PAGLayers
removeLayerAtindex: numbervoid从当前 PAGComposition 中删除指定索引处的 PAGLayer
numChildrenvoid该合成的子层数

源库编译

参考 libpag_compile_zh.md文档

目录结构

|---- libpag  
|     |---- entry  # 示例代码文件夹
|     |---- library  # library 库文件夹
|            |---- cpp  # native模块
|                  |----- common # libpag内部公共模块
|                  |----- manager      # 封装NAPI接口
|                  |----- napi     # 封装NAPI接口
|                  |----- render    # 动画渲染模块
|                  |----- third_party # 三方库依赖 
|                  |----- types     # d.ts文件导出模块
|            |---- ets  # ets接口模块
|                  |----- utils     # 工具  
|     |---- README.MD  # 安装使用方法
|     |---- README_zh.MD  # 安装使用方法

约束与限制

在下述版本验证通过:

  • DevEco Studio: NEXT Release(5.0.3.900), SDK: API12 (5.0.0.71)
  • DevEco Studio: NEXT Developer Beta3(5.0.3.524), SDK: API12 (5.0.0.25)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值