• Lv9
    粉丝21

积分1228 / 贡献0

提问0答案被采纳67文章11

[经验分享] 【闲谈鸿蒙三方库】动画库@ohos/lottie 原创

马迪 显示全部楼层 发表于 5 天前

三方库背景

在移动设备开发场景,很多大厂都在用lottie来渲染动画。所以在鸿蒙应用中,各厂都有相同的诉求:使用相同的lottie动画资源,实现相同的动画效果。

@ohos/lottie是一个解析Lottie格式的JSON动画,并以鸿蒙原生方式进行渲染的开源库。

其主要特性包括: 越来越多的应用选择Lottie动画,主要有以下原因: 1.Lottie动画支持Android、iOS、React Native、Web和Windows等多个平台,这意味着开发者只需创建一次动画文件,就可以在多个平台上无缝运行,极大地节省了开发资源和时间。这种跨平台特性使得Lottie动画成为构建跨平台应用时的理想选择。 2.Lottie动画通常使用美工擅长的Adobe After Effects工具制作,并通过Bodymovin插件导出为JSON格式,并且能精准还原美工的设计。 3.Lottie动画的JSON文件格式体积小,加载速度快。 4.Lottie提供了简单易用的API接口,前端可以控制动画的播放、暂停、循环、速度调整等操作,甚至播放特定的动画片段。这种易于集成与控制的特点使得Lottie动画在应用中具有更大的灵活性和可扩展性。 5.Lottie是一个开源项目,同时也有商业支持,确保项目的持续发展和改进。 开源代码地址:https://gitcode.com/openharmony-tpc/lottieArkTS showlottie.gif

快速上手方法

1.下载安装

ohpm install @ohos/lottie

当前稳定版本2.0.16 和 3.0.0(多线程并行加载版本)

2.设计动画

lottie动画文件是由设计人员使用Adobe After Effects软件通过bodymovin插件导出json格式的文件。

3.將动画需要的json文件放到pages同级别目录下,然后引用。

注意:json文件路径不能使用 ./ 或者 ../ 等相对路径,相对路径获取不到动画源数据,会导致动画加载不出来, 传递给loadAnimation 方法的路径是相对于pages父文件夹为基准的,而index页面内引入的相对路径的动画是以index.ets文件为基准的,两者基准不一致。 所以如果json文件放置在pages文件夹下,路径应为 'pages/common/data.json' 样式

4.关联Canvas画布

由于Lottie需要使用Canvas渲染,首选需要创建Canvas需要的渲染上下文CanvasRenderingContext2D:

mainRenderingSettings: RenderingContextSettings = new RenderingContextSettings(true)
mainCanvasRenderingContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.mainRenderingSettings)

其次CanvasRenderingContext2D需要跟对应的Canvas关联起来

Canvas(this.mainCanvasRenderingContext)
.width('50%')
.height(360 + 'px')
.backgroundColor(Color.Gray)
.onReady(()=>{
//抗锯齿的设置
    this.mainCanvasRenderingContext.imageSmoothingEnabled = true;
    this.mainCanvasRenderingContext.imageSmoothingQuality = 'medium'
})

5.使用CanvasRenderingContext2D对象加载动画

animationItem = lottie.loadAnimation({
            container: this.mainCanvasRenderingContext,  // 渲染上下文
            renderer: 'canvas',                          // 渲染方式
            loop: true,                                  // 是否循环播放,默认true
            autoplay: true,                              // 是否自动播放,默认true
            name: '2016',                                // 动画名称
            contentMode: 'Contain',                      // 填充的模式
            frameRate: 30,                               //设置animator的刷帧率为30
            imagePath: 'lottie/images/',                 // 加载读取指定路径下的图片资源
            path: this.path,                             // json路径
            initialSegment: [10,50]                      // 播放的动画片段
          })

更多功能展示

示例1 播放动画

lottie.play() //所有动画播放
或
animationItem.play() //当前指定animationItem动画播放

示例2 停止动画

lottie.stop() //所有动画停止
或
animationItem.stop() //当前指定animationItem动画停止

示例3 暂停动画

lottie.pause() //所有动画暂停
或
animationItem.pause() //当前指定animationItem动画暂停

示例4 设置播放速度

注意:speed>0正向播放, speed<0反向播放, speed=0暂停播放, speed=1.0/-1.0正常速度播放

lottie.setSpeed(1) //所有动画设置播放速度
或
animationItem.setSpeed(1) //当前指定animationItem动画设置播放速度

示例5 设置动画播放方向

注意:direction 1为正向,-1为反向

lottie.setDirection(1) //所有动画设置播放方向
或
animationItem.setDirection(1) //当前指定animationItem动画设置播放方向

示例6 控制动画停止在某一帧或某一时刻

注意:根据第二个参数判断按帧还是按毫秒控制,true 按帧控制,false 按时间控制,缺省默认为false

animationItem.goToAndStop(250,true)
或
animationItem.goToAndStop(5000,false)

示例7 添加侦听事件

AnimationEventName = 'drawnFrame' | 'enterFrame' | 'loopComplete' | 'complete' | 'segmentStart' | 'destroy' | 'config_ready' | 'data_ready' | 'DOMLoaded' | 'error' | 'data_failed' | 'loaded_images';

animationItem.addEventListener("enterFrame",function(){
    // TODO something
})

示例8 获取动画时长/帧数

animationItem.getDuration();

示例9 更改动画渲染颜色

注意:第一个参数颜色是RGB/RGBA值,第二个参数是动画的层次 可不填,第三个参数是对应动画层次的元素的下标值 可不填

animationItem.changeColor([255,150,203,0.8])  //修改整个动画的颜色
或
animationItem.changeColor([255,150,203,0.8],2) //修改该动画第二层的颜色
或
animationItem.changeColor([255,150,203,0.8],2,2) //修改该动画第二层第二个元素的颜色

示例10 设置动画的刷帧率

设置动画animator的刷帧率,范围是1~120 帧率越大,功耗越严重

animationItem.setFrameRate(30);

实现原理

1.动画核心加载流程

  • Lottie:全局控制入口
  • AnimationManager:管理所有的动画
  • AnimationItem:每个动画对象
  • DataManager:读取json数据
  • CanvasRendererBase:解析和渲染lottie动画 image5.png

2.核心设计点

  • 基于LottieWeb移植适配,将调用canvas的接口从web canvas移植修改成鸿蒙canvas。
  • 监听canvas对象的可见性回调,当动画处于隐藏状态或完全不可见时,当前动画将自动暂停其向canvas底层发送绘制指令,以此优化性能并减少功耗。

局限性

1.该库基于LottieWeb js版本移植适配,当动画较多或较复杂时,由于都在主线程加载和渲染动画,可能会导致应用卡顿和丢帧,目前正在使用C版本重构实现,且需要实现多个动画在子线程中并行加载,孵化项目在这里。 2.该库没有封装自定义UI组件,导致把canvas的实现暴露给应用开发者,需要应用开发者手工创建和销毁CanvasRenderingContext2D和Canvas,使用方式较不友好,与应用耦合度较高。

结束语

随着越来越多的鸿蒙应用上线,各种开源的闭源的,开发者自发的和大厂贡献的库也正在逐步涌现出来,同时也有一些早期的库已被淘汰。今年我将抽空基于HarmonyOS 5.0+试试水,根据实际效果和下载量筛选在awesome-harmony-library,帮助大家快速找到合适的三方库,也请大家也帮忙Star下这个仓库:)

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2025  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部