# LottieC **Repository Path**: openharmony-tpc-incubate/lottie-c ## Basic Information - **Project Name**: LottieC - **Description**: lottie是一个适用于OpenHarmony的动画库,它可以解析Adobe After Effects软件通过Bodymovin插件导出的json格式的动画,并在移动设备上进行本地渲染。该库基于rlottie及c++实现 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 17 - **Created**: 2024-11-19 - **Last Updated**: 2025-06-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # lottie-turbo ## 简介 lottie-turbo是一个适用于OpenHarmony的动画库,它可以解析Adobe After Effects软件通过Bodymovin插件导出的json格式的动画,并在移动设备上进行本地渲染,使用声明式语法创建和使用,具备并行化能力,适用于应用加载lottie动画的场景。 ![lottie Gif](image/lottie.gif) ## 快速上手 ### 简易示例 ```js import { LottieController, LottieView } from '@ohos/lottie-turbo'; @Entry @Component struct Load { private controller: LottieController = new LottieController(); build() { Column() { LottieView({ lottieId: "lottie1", //动画id,需要保证唯一性 loop: true, //是否循环播放 autoplay: true, //是否自动播放 path: $rawfile('common/lottie/grunt.json'), //通过rawfie文件播放 // path: "https://cdn.lottielab.com/l/7Zgk9iuQxmZ3tD.json", //通过uri播放 controller: this.controller, }) .width('50%') .height(160) .backgroundColor(Color.Gray) .onClick(() => { this.controller.togglePause(); //控制动画播放暂停 }) } .height('100%') .width('100%') } } ``` ### 补充示例 ```js import { LottieView, LottieController, LottieListener, lottie } from '@ohos/lottie-turbo'; @Entry @Component struct Index { private controller: LottieController = new LottieController(); //动画控制器 // 事件监听器 private listener: LottieListener = new LottieListener({ onEnterFrame: () => { //开始渲染帧回调 this.updateAllStates() }, onLoopComplete: () => { //动画循环播放一轮完成时 console.info("lottie complete"); this.playCount = this.controller?.playCount; this.totalPlayedCount += 1; }, onComplete: () => { //动画播放结束时调用 this.log += "lottie1 event complete\r\n" }, onDestroy: () => { //动画删除后回调 console.info("lottie destroy"); }, onDOMLoaded: () => { //动画加载完成,播放之前触发回调 console.info("lottie DOMLoaded"); }, onDataReady: () => { //动画数据初始化完成时调用 this.log += "lottie1 event data_ready\r\n" }, }) build() { ... LottieView({ loop: true, //是否循环 autoplay: true, //自动播放 autoSkip: true, //不可见时是否自动跳过渲染 lottieId: "lottie1" + this.getUniqueId(), //设置唯一id contentMode: 'Contain', //填充模式 path: $rawfile('common/lottie/animation.json'), //动画路径 frameRate: 30, //播放帧率,1-120Hz controller: this.controller, //动画控制器 initialSegment: [30, 150], //初始化动画资源播放时的整体帧范围 listener: this.listener, //监听事件容器 useCache: true, //是否使用缓存 setImageAssetDelegate: [["refid", "uri" ]]//替换图片资源文件,支持Base64和uri }) Button("全局控制") .onClick(() => { lottie.play(); //全局播放 lottie.pause(); //全局暂停 lottie.stop(); //全局停止 lottie.destroy(); //全局暂停 lottie.togglePause();//全局切换暂停/播放 lottie.setSpeed(1); //设置全局播放速度 lottie.setDirection(1); //设置全局播放方向 1代表正向 -1代表方向 lottie.setFrameRate(30);//全局设置播放帧率 lottie.clearFileCache("");//清除单个文件缓存 不传参数为清除所有文件缓存 lottie.clearCache();//清除内存缓存 lottie.resizeCache(10, 10 * 1024 * 1024);//重置内存缓存大小 lottie.resizeFileCache(10, 1024*1024);//重置文件缓存大小 lottie.removeCache("path")//通过key删除内存缓存 }) Button("单个控制") .onClick(() => { this.controller.play(); //播放 this.controller.stop(); //停止 this.controller.pause(); //暂停 this.controller.destroy(); //销毁 this.controller.setSpeed(1); //设置播放速度 this.controller.goToAndPlay(250,true); //跳转到250帧并播放,false单位为ms this.controller.goToAndStop(250,true); //跳转到250帧并停止,false单位为ms this.controller.setDirection(1); //设置播放方向 1代表正向 -1代表方向 this.controller.setSegment(350, 0); //限定动画资源播放时的整体帧范围 this.controller.setSubframe(true); //设置是否插帧播放,默认为true this.controller.playSegments([[5,15],[20,30]],false);//下次播放按照片段设置播放,tru立即生效 this.controller.changeColor("**", [255, 0, 0, 1]); //按照图层名称,修改RGBA动画颜色 this.controller.togglePause() //切换暂停/播放 this.controller.setFrameRate(30) //设置播放帧率 this.controller1.setContentMode("Contain"); //设置填充模式,支持Fill,Cover,Top,Bottom,Contain //切换为其他动画,可通过path配置 this.controller.reload({ path: "https://kjstorage.360buyimg.com/cms-file/1_eec97231.zip" }) //添加监听事件 this.controller.addEventListener('drawFrame', (): void => { this.log += "add lottie event " + eventName + "\r\n" }); this.controller.removeEventListener(‘drawFrame’); //移除监听事件 this.controller.triggerEvent("drawFrame"); //强制触发回调 // }) ... } // 默认在LottieView组件销毁时自动触发销毁 aboutToDisappear(): void { } } ``` ### 注意事项 - 1.当前默认在页面aboutToDisappear时自动触发destroy进行销毁。 - 2.需要注意lottieId的唯一性,不配置时将自动随机生成。 ## 使用说明 前提:数据准备 lottie动画文件是由设计人员使用Adobe After Effects软件通过bodymovin插件导出json格式的文件。 AE软件创建动画时需要设置动画的宽(w)、高(h)、bodymovin插件的版本号(v)、帧率(fr)、开始帧(ip)、结束帧(op)、静态资源信息(assets) 、图层信息(layers)等重要信息。 如果仅是用于demo测试,可以使用[工程示例中的json文件] 。 ### 1.引入组件: ```js import lottie from '@ohos/lottie-turbo' ``` ### 2.动画资源导入 (1)通过本地文件加载动画 ```js LottieView({ path: $rawfile('common/lottie/animation.json'), //动画路径 }) ``` > 路径资源在工程entry/src/main/resources/rawfile下 (2)通过网络资源加载动画 ```js LottieView({ path: "https://cdn.lottielab.com/l/7Zgk9iuQxmZ3tD.json", //动画路径 }) ``` (3)通过json字符串加载动画 ```js LottieView({ animationData: this.netPath, // animationData优先级 > path 优先级 }) ``` ### 3.LottieView组件设置 LottieView支持常规ArkUI通用设置 ```js LottieView({ path: $rawfile('common/lottie/grunt.json'), //通过rawfie文件播放 }) .width('50%') //设置宽度 .height(160) //设置高度 .backgroundColor(Color.Gray) // 设置背景颜色 // 设置点击事件 .onClick(() => { }) ``` ### 4.LottieView组件使用 > 可参考快速上手中简易示例 ## LottieView配置项 | 参数名称 | 参数类型 | 参数说明 | |------------------------------------|----------|----------------------------------------| | lottieId | 字符串 | 应用内的唯一id | | path | 字符串/资源文件 | 应用内的动画数据文件路径, 仅限json格式 | | animationData | 字符串 | json格式的动画数据, 仅限json字符串格式,优先级高于path | | loop?: boolean|number | 布尔值/正整数 | 是否循环播放/循环次数 | | autoplay?: boolean; | 布尔值 | 是否自动播放 | | initialSegment?: AnimationSegment; | 数组 | 初始化动画资源播放时的整体帧范围:[1-60] | | contentMode?: string; | 字符串 | 动画填充模式,取值Fill,Cover,Top,Bottom,Contain | | frameRate?: number; | 数值 | 设置animator的刷帧率,范围1~120 | | useCache?: boolean | 布尔值 | 是否使用缓存,默认true,使用缓存 | | autoSkip?: boolean; | 布尔值 | 当动画不可见时,是否跳过绘制:设为true则跳过绘制,默认为 true | | controller?: LottieController; | 控制器 | 控制动画操作,通过new LottieController()创建 | | listener?: LottieListener; | 监听 | 监听事件,通过new LottieListener()创建 | | setImageAssetDelegate(interface[]) | object | 设置Assets资源替换功能,[图片资源id,base64/uri] | ## 单个动画控制 LottieController参数说明 | 参数名称 | 相关描述 | |-----------------------------|---------------------------------------| | lottieId: string | 唯一id | | isLoaded: boolean; | 是否加载 | | currentFrame: number; | 当前帧号,默认为浮点数,调用setSubframe(false) 后为整数 | | currentRawFrame: number; | 当前帧数,浮点数 | | firstFrame: number; | 当前播放片段的第一帧帧号 | | totalFrames: number; | 当前播放片段的总帧数 | | frameRate: number; | 帧率 frame/s | | frameMult: number; | 帧率 frame/ms | | playSpeed: number; | 播放速度 | | playDirection: number; | 播放方向 | | playCount: number; | 动画完成播放的次数 | | isPaused: boolean; | 是否已暂停 | | autoplay: boolean; | 是否自动播放 | | loop: boolean | 是否自动循环 | | timeCompleted: number = 0; | 当前动画片段完成单次播放的帧数 | | segmentPos: number = 0; | 当前动画片段序号 | | isSubframeEnabled: boolean; | 是否尽可能更新动画帧率 | | segments: AnimationSegment | 当前动画播放片段 | ## 单个动画控制 LottieController接口说明 | 使用方法 | 输入参数 | 相关描述 | |-----------------------|----------------------------------------------------------------------|------------------------------------| | play() | null | 播放 | | stop() | null | 停止 | | pause() | null | 暂停 | | togglePause() | null | 切换暂停 | | destroy() | null | 销毁动画 | | goToAndStop() | value: number, isFrame?: boolean | 跳到某一时刻并停止 | | goToAndPlay() | value: number, isFrame?: boolean | 跳到某一时刻并播放 | | setSegment() | init: number, end: number | 设置动画片段 | | playSegments() | segments: AnimationSegment | AnimationSegment[], forceFlag?: boolean | 播放指定片段 | | resetSegments() | forceFlag | 重置动画 | | setSpeed() | speed: number | 设置播放速度 | | setDirection() | direction: number | 设置播放方向 | | setSubframe() | useSubFrames: boolean | 设置尽可能更新动画帧率 | | getDuration() | inFrames?: boolean | 默认获取播放时间,入参为true 时获取帧数,false 为时间ms | | triggerEvent() | name: string | 强制触发指定事件 | | addEventListener() | name: string, callback: Function | 添加监听状态 | | removeEventListener() | name: string, callback?: Function | 移除监听状态,移除后触发回调 | | changeColor() | layer: string, startColor: number[], endColor?: number[] | 更改动画颜色 | | setContentMode() | contentMode: string | 设置填充模式 | | setFrameRate() | frameRate: number | 设置动画刷帧率 | | reload() | config: ConfigType | 重载动画 | ## 全局动画控制 lottie全局api说明 | 使用方法 | 参数类型 | 相关描述 | |--------------------------|-------------------------------------------------|-------------------------------------------------------------------------------------------------------| | lottie.play() | lotteId ?: string (动画名) | 播放动画,可通过设置lotteId 指定动画操作 | | lottie.stop() | lotteId ?: string (动画名) | 停止动画,可通过设置lotteId 指定动画操作 | | lottie.pause() | lotteId ?: string (动画名) | 暂停动画,可通过设置lotteId 指定动画操作 | | lottie.togglePause() | lotteId ?: string (动画名) | 切换暂停动画,可通过设置lotteId 指定动画操作 | | lottie.destroy() | lotteId ?: string (动画名) | 销毁动画,可通过设置lotteId 指定动画操作 | | lottie.setSpeed() | speed: number (播放方向) , lotteId ?: string (动画名) | 全局动画播放方向控制,speed>0正向播放, speed<0反向播放, speed=0暂停播放, speed=1.0/-1.0正常速度播放 | | lottie.setDirection() | direction: 1 或 -1, lotteId ?: string (动画名) | 全局设置播放方向,可通过设置lotteId 指定动画操作; 1为正向, -1为反向; 当设置为反向时, 从当前播放进度开始回播直到首帧, loop值为true时可无限倒放, speed<0叠加时也是倒放 | | lottie.setFrameRate() | frameRate: number | 全局设置播放帧率 | | lottie.clearFileCache() | url?: string (路径path或者网络uri) | 全局文件缓存清除 ,可通过设置url指定清除文件. | | lottie.resizeCache() | size: number, capacity: number (缓存总量大小) | 设置内存缓存容器大小 | | lottie.resizeFileCache() | size: number, capacity: number (缓存总量大小) | 设置文件缓存容器大小 | | lottie.clearCache() | 无 | 清空缓存容器 | | lottie.removeCache() | key: string (缓存键) | 通过缓存键移除缓存 | ## 场景使用指南 ### 1.动画播放暂停 ```js lottie.play() //所有动画播放 lottie.play('animation1') //animation1动画播放 this.controller.play() //this.controller绑定的动画播放 lottie.stop() //所有动画停止 lottie.stop('animation1') //animation1动画停止 this.controller.stop() //this.controller绑定的动画停止 lottie.pause() //所有动画暂停 lottie.pause('animation1') //animation1动画暂停 this.controller.pause() //this.controller绑定的动画暂停 lottie.togglePause() //所有动画切换暂停/播放 lottie.togglePause('animation1') //animation1动画切换暂停/播放 this.controller.togglePause() //this.controller绑定的动画切换暂停/播放 ``` ### 2.设置播放速度 > 注意:speed>0正向播放, speed<0反向播放, speed=0暂停播放, speed=1.0/-1.0正常速度播放 ```js lottie.setSpeed(1) //所有动画设置播放速度 lottie.setSpeed(1,'animation1') //animation1动画设置播放速度 this.controller.setSpeed(1) //this.controller绑定的动画设置播放速度 ``` ### 3.设置播放速度 > 注意:direction 1为正向,-1为反向 ```js lottie.setDirection(1) //所有动画设置播放方向 lottie.setDirection(1,'animation1') //animation1动画设置播放方向 this.controller.setDirection(1) ///this.controller绑定的动画设置播放方向 ``` ### 4.设置播放速度 > 注意:页面不显示或退出页面时,需要销毁动画; > 默认已在LottieView的aboutToDisappear()中调用了this.controller.destroy ```js lottie.destroy() //销毁所有动画 lottie.destroy('animation1') //销毁animation1动画 this.controller.destroy('animation1') //销毁指定name动画 ``` ### 5.动画跳转 > 注意:根据第二个参数判断按帧还是按毫秒控制,true 按帧控制,false 按时间控制,缺省默认为false ```js this.controller.goToAndPlay(250,true) //跳转到250帧并播放 this.controller.goToAndPlay(12000,false) //跳转到5000ms并播放 this.controller.goToAndStop(250,true) //跳转到250帧并停止 this.controller.goToAndStop(5000,false) //跳转到5000ms并停止 ``` ### 6.动画片段播放 ```js // 限定动画资源播放时的整体帧范围,即设置动画片段 this.controller.setSegment(5,15); // 播放动画片段,第二参数值为true立刻生效, 值为false循环下次播放的时候生效 this.controller.playSegments([[5,15],[20,30]],true) // 重置动画播放片段,使动画从起始帧开始播放完整动画 // 参数值为true立刻生效, 值为false循环下次播放的时候生效 this.controller.resetSegments(true); ``` ### 7.动画事件监听 > 可监听事件说明 | 序号 | 事件名称 | 说明 | |----|---------------|-----------------| | 1 | enterFrame | 渲染一帧开始 | | 2 | drawFrame | 渲染一帧完成 | | 3 | loopComplete | 循环一次 | | 4 | complete | 播放完成 | | 5 | segmentStart | 片段开始播放 | | 6 | destroy | 销毁 | | 7 | config_ready | 数据准备 | | 8 | data_ready | 数据解析 | | 9 | DOMLoaded | 组件添加完成回调 | | 10 | data_failed | 数据加载失败,json文件异常 | | 11 | loaded_images | 图片数据获取失败 | #### (1)创建 LottieView时设置 ```js // 设置监听器 private listener: LottieListener = new LottieListener({ onDrawFrame: () => { onsole.info("onDrawFrame"); } }) //绑定监听器 LottieView({ listener: this.listener }) ``` #### (2)动态添加 ```js // 添加监听 this.controller.addEventListener('loopComplete', (): void => { console.info("loopComplete"); }) ``` #### (3)动态移除 ```js // 移除事件监听,可选择设置执行完成后的回调函数 this.controller.removeEventListener('loopComplete', (): void => { //执行移除后,调用此处函数 console.info("loopComplete"); }) ``` ### 8.更改动画渲染颜色 > 当前只支持填充图层与形状图层 #### (1)非关键帧 ```js // 注意:第一个参数代码图层名称,第二个参数是颜色的RGB或者RGBA值。 // 颜色取值0-255,透明度取值0-1.0 this.controller.changeColor("**.Layer 1 Outlines.**",[255,150,203]) //修改某一个元素的颜色,不带透明度 this.controller.changeColor("**.Layer 1 Outlines.**",[255,150,203,1.0]) //修改某一个元素的颜色,带透明度 ``` #### (2)关键帧,渐变色修改 ```js // 注意:第一个参数代码图层名称,第二和第三个参数是关键帧的起始和结束RGB或者RGBA值。 // 颜色取值0-255,透明度取值0-1.0 this.controller.changeColor("**.Layer 1.**",[255,0,0],[0,0,255]) //修改某一个关键帧的颜色,不带透明度 this.controller.changeColor("**.Layer 1.**",[255,0,0,0],[0,0,255,1]) //修改某一个关键帧的颜色,带透明度 ``` ### 9.设置资源文件替换 > 针对需要在加载前修改json动画中图片资源的场景,提供接口进行修改。 ```js "assets": [ { "id": "blep", "h": 114, "w": 114, "u": "", "p": "data:image/png;", "e": 1 } ] // 在 lottieView中setImageAssetDelegate参数使用,可替换带有image资源的动画,支持base64和uri替换 // refId为json动画中"assets"字段下的"id"属性,如上例 LottieView({ path: $rawfile('common/lottie/data_url.json'), setImageAssetDelegate: [ ["refid", "base64" ], ["refid", "uri" ], ] }) ``` ### 9.加载跨module动画 > 针对多个module,资源调用需要跨包的场景,提供跨module读取资源的能力 (1)加载module 在oh-package.json下dependencies中添加对指定module (2)LottieView加载 在path属性中设置$rawfile,中括号内为moduleName,该资源文件可被系统索引 ```js LottieView({ loop: true, autoplay: true, path: $rawfile('[lalhan].robotYoga.json') // 此处entry换成对应的moduleName }) ``` ### 10.更改动画 > 针对相同组件需要播放不同动画的场景,提供更改显示动画的接口 * path?: string | Resource * animationData?: string; * loop?: boolean | number * autoplay?: boolean * initialSegment?: AnimationSegment * contentMode?: string * frameRate?: number * setImageAssetDelegate?: ImageAssetDelegate[]; * resManager?: resmgr.ResourceManager; 其他参数可参考LottieView介绍,新增参数resManager resManager:资源管理器,可选参数,当与初始动画不在同一个module时使用,使用方式如下: (1)更改的动画与原本动画在同一个module ```js this.controller.reload({ loop: true, autoplay: true, path: $rawfile('common/lottie/animation.json') }) ``` (2)更改的动画与原本动画在不同的module ```js this.controller.reload({ loop: true, autoplay: true, path: $rawfile('[lalhan].robotYoga.json'), resManager: (await application.createModuleContext(getContext(this),'lalhan')).resourceManager // 此处entry换成对应的moduleName }) ``` ## 与LottieArkts特性对比 ### 更换说明 > LottieArkts的使用流程是先创建canvas,再手动调用播放,Lottie-turbo使用LottieView组件可直接实现加载播放 ![](image/image.png) > 最小替换部分可参考上图 ### 配置对比 ### 方法对比 | 接口 | 描述 | **lottieArkTS** | lottieC | |-----------------------------------|-----------------------------------------------------------|-----------------|----------------------------------------------------------| | play() | 播放 | 是 | 是 | | stop() | 停止 | 是 | 是 | | pause() | 暂停 | 是 | 是 | | togglePause() | 切换暂停 | 是 | 是 | | destroy() | 销毁动画 | 是 | 是 | | goToAndStop() | 跳到某一时刻并停止 | 是 | 是 | | goToAndPlay() | 跳到某一时刻并播放 | 是 | 是 | | setSegment() | 设置动画片段 | 是 | 是 | | playSegments() | 播放指定片段 | 是 | 是 | | resetSegments() | 重置动画 | 是 | 是 | | setSpeed() | 设置播放速度 | 是 | 是 | | setDirection() | 设置播放方向 | 是 | 是 | | getDuration() | 获取动画时长 | 是 | 是 | | addEventListener() | 添加监听状态 | 是 | 是 | | removeEventListener() | 移除监听状态 | 是 | 是 | | changeColor() | 更改动画颜色 | 是 | 否 (layer?: string, Color: number[]) layer表示图层,Color 代表颜色 | | setContentMode() | 设置填充模式 | 是 | 是 | | setFrameRate() | 设置动画刷帧率 | 是 | 是 | | cacheFileClear() | 清除文件缓存 | 是 | 是 | | bindContext2dToCoordinator() | 跟踪 lottie动画, CanvasRenderingContext2D, Canvas 三者之间的动态关联关系 | 是 | 废弃 | | unbindContext2dFromCoordinator() | 解除追踪关系 | 是 | 废弃 | | setAttachedCanvasHasVisibleArea() | 支持强制修正context2d所关联的canvas节点状态 | 是 | 废弃 | ### 属性对比 | 属性 | 描述 | lottieArkts | lottieC | |-------------------|---------------------------|-------------|-------------| | animationID | 动画名称 | 是 | 否 lottieId | | isLoaded | 动画是否已加载 | 是 | 是 | | currentFrame | 当前帧 | 是 | 是 | | currentRawFrame | 当前帧数(浮点) | 是 | 是 | | firstFrame | 第一帧索引 | 是 | 是 | | totalFrames | 总帧数 | 是 | 是 | | frameRate | 帧率 frame/s | 是 | 是 | | frameMult | 帧率 frame/ms | 是 | 是 | | playSpeed | 播放速度 | 是 | 是 | | playDirection | 播放方向 | 是 | 是 | | playCount | 完成播放的次数 | 是 | 是 | | isPaused | 是否暂停 | 是 | 是 | | isNetLoad | 是否网络加载 | 是 | 废弃 | | autoplay | 自动播放 | 是 | 是 | | loop | 是否循环 | 是 | 是 | | timeCompleted | 当前动画片段完成单次播放的帧数 | 是 | 是 | | segmentPos | 当前动画片段序号 | 是 | 是 | | isSubframeEnabled | 是否尽可能更新动画帧率 | 是 | 是 | | segments | 当前动画播放片段 | 是 | 是 | | packageName | 包名 | 废弃 | 废弃 | | autoSkip | 当动画不可见时,是否跳过绘制:设为true则跳过绘 | 是 | 是 | | uri | 网络资源加载路径 | 是 | 否 (合并到path) | | initialSegment | 初始化动画资源播放时的整体帧范围 | 是 | 是 | | animationData | json格式的动画数据 | 是 | 是 | | contentMode | 动画填充模式 | 是 | 是 | ## 约束与限制 在下述版本可验证使用: DevEco Studio: 5.0.4 Release(5.0.11.100), SDK: API16(5.0.0.150) ## 目录结构 待更新 ## 贡献代码 使用过程中发现任何问题都可以提交 [Issue](https://gitee.com/openharmony-tpc-incubate/lottie-c/issues),当然,也非常欢迎提交 [PR](https://gitee.com/openharmony-tpc-incubate/lottie-c/pulls) 。 ## 开源协议 本项目遵循 [Apache-2.0 License](https://gitee.com/openharmony-tpc-incubate/lottie-c/blob/master/LICENSE)。