Lottie动画在前端的使用

2,373 阅读3分钟

这是我参与8月更文挑战的第2天,活动详情查看: 8月更文挑战

动画.gif

介绍

Lottie是一个适用于Android,iOS,Web和Windows的库,它在AE中使用Bodymovin插件将动画导出为JSON格式的文件,可以在移动端和web端原生支持。详见:官网

而且你可以通过Lottie的全局方法控制动画的帧率,方向,销毁等等。

在这里可以看到Lottie的一些作品集 -- codepen

使用

installation

npm install --save react-lottie

这里使用的是react-lottie,其他框架可以在github上找对应的库。 下面的代码就是项目中的具体实现,效果见上面的图片。其中遇到了两个坑,下面会有介绍

//引入方式和官方文档不同,有坑
import Lottie from 'react-lottie';
// 使用到的JSON数据
import animationData from './loginAnimation/data.json'


//这里只展示了用到的代码
preventMaskClick = (e) => {
    e.preventDefault();
    return false;
}

render() {
    //这里是页面响应式样式的添加
    let clientHeight = document.documentElement.clientHeight
    let clientWidth = document.documentElement.clientWidth

    let scalew = clientWidth / 1920
    let scaleh = clientHeight / 1080
    let marginTop = clientHeight * (1 - scaleh) / -2
    let marginleft = clientWidth * (1 - scalew) / -2
    let lottieStyle = {
      position: 'absolute',
      margin: `${marginTop}px auto auto ${marginleft}px`,
      transform: `scale(${scalew}, ${scaleh})`
    }
    const defaultOptions = {
      loop: true,
      autoplay: true,
      animationData: animationData
    };
    return (
      <div className={styles.login}>
        <Lottie
          options={defaultOptions}
          width={clientWidth}
          height={clientHeight}
          style={{ ...lottieStyle }}
          isStopped={false}
          isPaused={false} />
        <div style={{ position: 'absolute', margin: '0 0', width: '100%', height: '100%' }} onClick={this.preventMaskClick}></div>
    </div>
}

遇到的问题

  1. 首先是引入方式 官网给出的代码是这样的:
import Lottie from 'react-lottie';
import * as animationData from './pinjump.json'

但是这样会报错:# lottie.js:6229 Error: <svg> attribute viewBox: Expected number, “0 0 undefined undefi…

网上找了一圈,发现了解决方法和原因,源码我还没有看,解释如下:

从源代码里发现animData的数据被封装在一个default的大对象中,所以取不到。再回去仔细观察代码,发现引入animationData时用了 “* as”,也就是把json数据导入为一个装在default的大对象中了。将 “* as”去掉,直接导入json数据,问题解决。可能是lottie升级之后数据格式要求变了,而react-lottie使用demo还没改

参照

  1. 其次是在Lottie中动画图片显示不出来 打开控制台查看,发现是路径问题。这里有两种解决方法:

    第一种是使用网络图片,并将JSON文件中"assets": [{"u": "images/",}]删除, 将"assets": [{"p": "",}]的值修改为网络图片路径

    第二种是直接将图片数据装换成base64格式,"assets": [{"p": "",}]的值修改为对应的图片数据。

  2. 第三个问题是由于动画是后加上的,所以存在图片大小和页面适配问题 可以看到代码中有关于适配的代码部分,主要是需要自己计算出缩放比例,使用transform: scale进行缩放。

  3. 之后就是阻止Lottie动画点击事件,这个是有配置的,但是我设置了没有起到效果。所以用了div覆盖上去,然后阻止默认事件。

扩展

关于深入原理方面,可以参考腾讯VTeam技术团队的文章。 主要涉及到JSON文件的各个参数的作用和意义 # 深度剖析Lottie动画原理