简介
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 NATIVERENDERROOTPATH/thirdparty/pag/𝑁𝐴𝑇𝐼𝑉𝐸𝑅𝐸𝑁𝐷𝐸𝑅𝑅𝑂𝑂𝑇𝑃𝐴𝑇𝐻/𝑡ℎ𝑖𝑟𝑑𝑝𝑎𝑟𝑡𝑦/𝑝𝑎𝑔/{OHOS_ARCH}/lib/libpag.so) target_link_libraries(native_libpag PRIVATE NATIVERENDERROOTPATH/thirdparty/pag/𝑁𝐴𝑇𝐼𝑉𝐸𝑅𝐸𝑁𝐷𝐸𝑅𝑅𝑂𝑂𝑇𝑃𝐴𝑇𝐻/𝑡ℎ𝑖𝑟𝑑𝑝𝑎𝑟𝑡𝑦/𝑝𝑎𝑔/{OHOS_ARCH}/lib/libtgfx.a)
将三方库的头文件加入工程中
target_include_directories(native_libpag PRIVATE 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;
};
type 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
接口名 | 参数 | 返回值 | 说明 |
---|---|---|---|
Init | id: string | void | 初始化配置 |
setComposition | 无 | void | 设置一个新的PAGComposition,让PAGPlayer作为内容呈现 |
play | 无 | void | 开始播放接口 |
pause | 无 | void | 在当前位置暂停动画 |
resume | 无 | void | 在当前位置继续播放动画 |
stop | 无 | void | 停止播放 |
isPlaying | 无 | number | 判断动画是否播放 |
getState | 无 | number | 获取动画状态 |
setRepeatCount | count:number | void | 设置动画播放次数 |
repeatCount | 无 | number | 返回动画播放的总次数 |
setScaleMode | mode: number | void | 设置缩放模式 |
scaleMode | 无 | number | 返回当前缩放模式 |
setMatrix | a: number,b: number,c:number,d:number,tx: number,ty:number | void | 设置矩阵变换 |
setProgress | value: number | void | 设置播放的起始帧数 |
setCacheEnabled | value: boolean | void | 设置cacheEnabled属性的值 |
cacheEnabled | 无 | boolean | 如果设置为true,PAG渲染器将缓存每个层的静态内容的内部位图表示 |
setCacheScale | value: number | void | 设置cacheScale属性的值 |
cacheScale | 无 | boolean | 该值定义内部图形缓存的比例因子,范围从0.0到1.0 |
setMaxFrameRate | value: number | void | 设置帧率 |
maxFrameRate | 无 | number | 渲染的帧率 |
setUseDiskCache | value: boolean | void | 设置useDiskCache属性的值 |
useDiskCache | 无 | boolean | 如果设置为true,PAG将把相关的渲染数据缓存到磁盘文件中,例如视频合成的解码图像帧 |
getComposition | 无 | PAGComposition | 返回当前PAGView的PAG组合以呈现为内容 |
getLayersUnderPoint | localX: number,localY: number | PAGLayer[] | 返回位于指定点下的层数组 |
setVideoEnabled | value: boolean | void | 设置videoEnabled属性的值 |
videoEnabled | 无 | boolean | 如果设置为false,PAGView将跳过视频合成的渲染 |
setPath | path: string | boolean | 从指定的路径加载一个pag文件,如果该文件不存在或数据不是pag文件,则返回false |
getPath | 无 | String | 由setPath()设置的pag文件的路径字符串 |
getProgress | 无 | number | 返回播放位置的当前进度,值从0.0到1.0 |
duration | 无 | number | 当前合成的持续时间(以微秒为单位) |
flush | 无 | boolean | 调用此方法可立即渲染当前位置 |
addPlayStateListener | cb: (state: number) => void | number | 添加播放状态的监听 |
addRepeatCountListener | cb: (state: number) => void | number | 添加播放次数的监听 |
addCurrentFrameListener | cb: (state: number) => void | number | 添加对当前帧的监听 |
removePlayStateListener | 无 | void | 移除播放状态的监听 |
removeRepeatCountListener | 无 | void | 移除播放次数的监听 |
removeCurrentFrameListener | 无 | void | 移除对当前帧的监听 |
freeCache | 无 | void | 立即释放pag视图创建的缓存 |
matrix | 无 | Matrix | 返回当前矩阵的副本 |
PAGFile
接口名 | 参数 | 返回值 | 说明 |
---|---|---|---|
setDuration | number | void | 设置此PAGFile的持续时间 |
loadFromPath | string | PAGFile | 从指定路径加载pag文件 |
setStartTime | number | void | 设置图层的开始时间 |
duration | 无 | number | 该层的持续时间 |
numImages | 无 | number | 可替换图像的数量 |
numTexts | 无 | number | 可编辑文本的数量 |
numVideos | 无 | number | 视频作品的数量 |
path | 无 | String | 此文件的路径字符串 |
maxSupportedTagLevel | 无 | number | 标记级别 |
getEditableIndices | layerType: number | number[] | 返回此PAGFile中可编辑层的索引 |
timeStretchMode | 无 | number | 指示当文件的持续时间更改时,如何拉伸原始持续时间以适应目标持续时间 |
tagLevel | 无 | number | 此pag文件所需的标记级别 |
setTimeStretchMode | value: number | void | 设置此文件的timeStretchMode。 |
PAGComposition
接口名 | 参数 | 返回值 | 说明 |
---|---|---|---|
init | width: number, height: number | void | 创建一个具有指定大小的空 PAGComposition |
addLayerAt | index: number | void | 将 PAGLayer 添加到当前 PAGComposition 的指定索引处 |
addLayer | 无 | void | 将 PAGLayer 添加到当前 PAGComposition 的顶部 |
getLayerAt | index: number | void | 返回存在于指定索引处的子层 |
removeLayer | 无 | void | 从当前 PAGComposition 中删除指定的 PAGLayer |
removeAllLayers | 无 | void | 从当前 PAGComposition 中删除所有 PAGLayers |
removeLayerAt | index: number | void | 从当前 PAGComposition 中删除指定索引处的 PAGLayer |
numChildren | 无 | void | 该合成的子层数 |
源库编译
参考 libpag_compile.md文档
目录结构
|---- libpag
| |---- entry # 示例代码文件夹
| |---- library # library 库文件夹
| |---- cpp # native模块
| |----- common # libpag内部公共模块
| |----- manager # 封装NAPI接口
| |----- napi # 封装NAPI接口
| |----- render # 动画渲染模块
| |----- third_party # 三方库依赖
| |----- types # d.ts文件导出模块
| |---- ets # ets接口模块
| |----- utils # 工具
| |---- README.MD # 安装使用方法
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)最新学习路线
-
HarmonOS基础技能
- HarmonOS就业必备技能
- HarmonOS多媒体技术
- 鸿蒙NaPi组件进阶
- HarmonOS高级技能
- 初识HarmonOS内核
- 实战就业级设备开发
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。