博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
由奥迪车灯想到的前端动画
阅读量:6198 次
发布时间:2019-06-21

本文共 3071 字,大约阅读时间需要 10 分钟。

最近对汽车比较感兴趣,平时也多留意看了一些身边的车,发现奥迪部分车型的转向灯很有特色,有一个从左到右的动画效果,视觉效果很赞,这撩起了我的好奇心,怎么用代码在网页上模拟实现呢?

先来看看我们需要实现的效果:

方法一:css

首先,想到的自然是css,因为css动画功能很强大,且这种方式代码简单,效果顺滑,强烈推荐。代码如下:

div.css-light {  width: 0%;  height: 6px;  background: #ff8908;  animation: mymove 1s ease-out infinite;}@keyframes mymove {  from {    width: 0%;  }  to {    width: 100%;  }}

其中,核心属性是animation。那animation怎么用呢?如下:

第一个属性指定要绑定到选择器的关键帧的名称,本例是mymove;
第二个属性指定动画指定需要多少秒或毫秒完成,本例是1s;
第三个属性设置动画将如何完成一个周期,默认是ease,本例是ease-out,表示动画以低速结束;
第四个属性定义动画的播放次数,本例是无限循环;

由此可见,css的animation是真的强大,还支持多种动画效果,比如ease-out这种效果,如果你要用js模拟ease-out等多种效果,那可就不是一行代码的事儿了。

更多参数信息请参考:

方法二:js方法

除开css,js也给与了模拟动画的能力,这种方式通常使用 setInterval()方法来控制动画,代码如下:

let div = document.getElementById('process')function process() {  div.style.width = '0%'  setInterval(() => {    div.style.width = (parseInt(div.style.width, 10) + 1) + '%'    if (div.style.width === '100%') {      div.style.width = '0%'    }  }, 20)}process()

但这种方法有几个弊端。

第一个就是不十分精确,为它传入的第二个参数(如本例中的20),实际上只是指定了把动画代码添加到浏览器 UI 线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行。也就是说,以毫秒表示的延迟时间并不代表到时候一定会执行动画代码,而仅代表到时候会把代码添加到任务队列中。如果 UI 线程繁忙,比如忙于处理用户操作,那么即使把代码加入队列也不会立即执行。

第二个弊端就是编写动画循环需要知道延迟时间多长合适。一方面,循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化。拿本例来说,如果将20改成200,那么你会发现动画效果会显得一卡一卡的。而由20改成1,那么动画会执行的非常快,并且性能的开销也会增加。

第三个弊端是setInterval它的开销也比较大,即便页面后台运行,这个开销也一直存在。

那么,这些个弊端能不能优化呢?是时候让requestAnimationFrame出场了!

与setInterval相比,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机。
具体来说,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。省心!用了它,你就再也不用纠结到底循环间隔设置为多少合适了,它帮你干了这事。

它的用法很简单,用requestAnimationFrame方式改写如下:

function updateProgress () {  let div = document.getElementById('process')  div.style.width = (parseInt(div.style.width, 10) + 1) + '%'  if (div.style.width === '100%') {    div.style.width = '0%'  }  window.requestAnimationFrame(updateProgress);}window.requestAnimationFrame(updateProgress);

关于更多requestAnimationFrame的信息,请参考:

真实情况

本文模拟了一个简单的车灯动画效果,从中引出了一些前端动画方面的知识,并用二种不同的方式进行了实现(css和js)。

最后说下,在汽车上真实的效果应该是由多个led灯来实现的,我这里提供一种方法(借助vue),供大家参考,有兴趣的同学可以用其他的方法自行模拟和拓展。
(需要翻墙),核心代码如下:

new Vue({  el: '#app',  data () {    return {      items: [        {id: 1, active: false},        {id: 2, active: false},        {id: 3, active: false},        {id: 4, active: false},        {id: 5, active: false},        {id: 6, active: false},        {id: 7, active: false},        {id: 8, active: false},        {id: 9, active: false},        {id: 10, active: false}      ]    }  },  created () {    this.init()  },  methods: {    init () {      this.items[0].active = true    }  },  watch: {    items: {      handler (val) {        let index = val.findIndex(v => v.active === false)        if (index === -1) {          setTimeout(() => {            val.forEach(v => v.active = false)          }, 50)        } else {          setTimeout(() => {            val[index].active = true          }, 50)        }      },      deep: true    }  }})

转载地址:http://ddnca.baihongyu.com/

你可能感兴趣的文章
Sonar Runner2.4 安装配置
查看>>
深入理解Ehcache系列(五)
查看>>
java5线程并发库的应用
查看>>
020# Adempiere的会计功能模组(一)
查看>>
舌尖上的程序猿
查看>>
Highcharts参数大全
查看>>
函数式编程
查看>>
datav.js
查看>>
java之不可变对象--java并发编程实践
查看>>
php编译完成后安装mysql扩展
查看>>
LSA
查看>>
java对象的克隆
查看>>
lVS(nat模式)+keepalived搭建
查看>>
用数据冗余换取查询性能
查看>>
JVM快速调优手册03:内存分配策略
查看>>
nginx之ngx_errno.c文件阅读
查看>>
Spring Boot - 2.0.6.RELEASE异步任务获取返回值
查看>>
MySQL编译安装
查看>>
c++错误代码中英文解释
查看>>
我的友情链接
查看>>