OpenHarmony开发者论坛

标题: 【闲谈鸿蒙三方库】动画库@ohos/lottie [打印本页]

作者: 马迪    时间: 6 天前
标题: 【闲谈鸿蒙三方库】动画库@ohos/lottie
[md]## 三方库背景

在移动设备开发场景,很多大厂都在用lottie来渲染[动画](https://airbnb.design/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](https://dl-harmonyos.51cto.com/i ... 05c1c6b2b8ec976.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](https://dl-harmonyos.51cto.com/i ... rocess=image/resize,w_820,h_557)

#### 2.核心设计点

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

## 局限性

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

## 结束语

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




欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/) Powered by Discuz! X3.5