【vue自定义组件】实现UI给的动画,lottie登场

3,301 阅读4分钟

小知识,大挑战!本文正在参与“  程序员必备小知识  ”创作活动

本文同时参与 「掘力星计划」  ,赢取创作大礼包,挑战创作激励金

前言

佛祖保佑, 永无bug。Hello 大家好!我是海的对岸!

这个组件也是做项目的时候,碰到的。当时UI给的原型图,强调,这是一个会动动画,不是静态图片。

image.png

UI给的图 ↑

当时第一反应就是,这个直接用css的动画animation, 好像不太好搞的样子。当时也是脸皮厚,对UI说,要不你做一个动态的效果出来,我看看,再实现

but,后来UI真的做出来了,我当时第一反应,就是卧槽, UI 🐂 🍺 !

animation.gif

第二反应就是,我要怎么搞?

实现过程思考

既然UI 弄出来了,那么说明 这个东西,恩,理论上是可以用前端代码实现的,那么就开始着手做吧

剥茧抽丝

  1. 刚开始,看到这个动画,确实不知道要怎么弄,当时 UI 是给了一个文件夹过来,说,让我用nginx本地部署一下,就能看到效果了。

文件夹的内容如下:

image.png

  1. 第一眼看上去,这个东西,怎么看都不是她自己手写出来的,应该是UI用她的软件画出一个动画出来,然后导出成代码的形式,给我们前端工程师看的

接着看逐次打开每个文件夹,images里面放的都是图片素材,jc.html一看就是个入口文件scripts里面放的是js文件,data.json是一长串的json对象,也不太好下手。

image.png

image.png

等下!!script中的bodymovin.js怎么看都应该是生成出来的固定文件名,这个文件名,网上一定能搜的到

顺藤摸瓜

  1. 在网上搜 bodymovin.js,没有得到想要的结果,但是让我知道了这个js作用大概就是实现动画的,而data.json就是支撑动画的数据images里放的就是动画要用到的素材

  2. 我是用vue开发的,那么,在网上接着搜vue bodymovin.js,果然,很快就找到我想要的了

image.png

vue-lottie登场

关于vue-lottie的安装,可以去看我的【vue起步】快速搭建vue项目引入第三方插件

为什么使用Lottie

一直以来我们的设计同学都是使用设计软件,设计动画效果,开发同学再通过代码来实现动效。对于复杂的动画,开发同学要用很长的时间来实现,并且还有可能无法达到设计同学的最初的效果。
还有一种实现动画的方式就是gif图。然而Android并不支持gif图,而且gif图对于移动端还有占用过多空间的问题。

那么,Lottie为我们做了什么呢。
首先,设计同学在Adobe After Effects上设计了动画效果,通过bodymovin插件,可以将动画导出成一个json文件。
然后,开发同学就可以通过Lottie将前面生成的json文件渲染成动画效果。
这样就可以高效的实现很多复杂动画效果啦。

直接上代码

image.png

image.png

comLottie.vue

<template>
  <div>
    <lottie
      :options="defaultOptions"
      :height="170"
      :width="170"
      v-on:animCreated="handleAnimation"
    />
  </div>
</template>

<script>
// 引入data.json
import * as animationData from "@/assets/lottie/effect/data.json";
animationData.assets.forEach((item) => {
  item.u = "";
  if (item.w && item.h) {
    item.p = require(`@/assets/lottie/effect/images/${item.p}`);
  }
}); // 获取静态资源
export default {
  name: "robotLottie",
  props: [],
  data() {
    return {
      defaultOptions: {
        // 动画数据:注意是 .default
        animationData: animationData.default,
      },
    };
  },
  computed: {},
  methods: {
    handleAnimation(anim) {
      this.anim = anim;
    },
  },
  mounted() {},
};
</script>

<style lang="scss" scoped></style>

这样就完了?没错,这就好了,然后我们引用一下

<template>
  <div class="hello">
    <module style="display: inline-block" />
  </div>
</template>

<script>
import module from "./comLottie.vue";

export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  components: {
    module,
  },
  data() {
    return {
      echartObj: {},
    };
  },
  methods: {},
  mounted() {},
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.hello {
  background-color: #182634;
}
</style>

animation2.gif

因为这种动画的素材引用的并不多,项目中就只有2个,所以我就给另一个动画素材,直接也新建一个组件来展示了。 把comLottie.vue 复制一下,改名comLottie2.vue

把代码中的动画资源地址改下

image.png

再引入一遍

<template>
  <div class="hello">
    <module style="display: inline-block" />
    <module2 style="display: inline-block" />
  </div>
</template>

<script>
import module from "./comLottie.vue";
import module2 from "./comLottie2.vue";

export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  components: {
    module,
    module2,
  },
  data() {
    return {
      echartObj: {},
    };
  },
  methods: {},
  mounted() {},
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.hello {
  background-color: #182634;
}
</style>

这样,效果就来了!

animation.gif

参考文档

参考1:segmentfault.com/a/119000001…

参考2:www.cnblogs.com/cynthia-wuq…

评论抽奖

欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边

  • 抽奖礼物:100份,掘金官方提供,包括掘金徽章、拖鞋、马克杯、帆布袋等,随机发放
  • 抽奖时间:「掘力星计划」活动结束后,预计3个工作日内,官方将在所有符合规则的活动文章评论区抽出
  • 抽奖方式:掘金官方随机抽奖+人工核实
  • 评论内容:与文章内容相关的评论、建议、讨论等,「踩踩」「学习了」等泛泛类的评论无法获奖

都看到这里了,求各位观众大佬们点个赞再走吧,你的赞对我非常重要