Vue中使用requestAnimationFrame制作动画

概述

requestAnimationFrame是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。

设置这个API的目的是为了让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,它采用系统时间间隔, 保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销。也不会因为间隔时间太长,使用动画卡顿不流畅,从而节省系统资源,提高系统性能,改善视觉效果。代码中使用这个API,就是告诉浏览器希望执行一个动画,让浏览器在下一个动画帧安排一次网页重绘。

特点

requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量

requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销

在Vue中使用

举个例子, 例如我想实现如下的动画效果:

trigger.gif

实现上图的效果, 需要如下一张原始背景图片:

themetrigger.png

通过不断切换背景图片的定位, 从而达到一张纸被掀开的效果

所以requestAnimationFrame就派上用场了

template:

<div @mouseenter="enter" @mouseleave="leave" title="更换皮肤" class="theme-trigger" :style="`background-position: -${position}px 0`"> </div>

css

.theme-trigger { background-image: url(trigger.png); background-position: 0 0; border-radius: 0 4px 0 0; cursor: pointer; width: 58px; height: 49px; position: absolute; top: 0; right: 0; }

第一种实现方式:

export default { data() { return { position: 0, is_enter: false, } }, methods: { async enter() { this.is_enter = true; while (this.position !== 522 && this.is_enter) { await new Promise(resolve => window.requestAnimationFrame(() => resolve(this.position += 58))); } }, async leave() { this.is_enter = false; while (this.position !== 0 && !this.is_enter) { await new Promise(resolve => window.requestAnimationFrame(() => resolve(this.position -= 58))); } }, }

利用ES7的async/await特性, 在while中不断调用requestAnimationFrame, 设置定位即可

第二种实现方式:

export default { data() { return { position: 0, timer: 0, } }, methods: { enlarge() { if (this.position === 522) { window.cancelAnimationFrame(this.timer); } else { this.position += 58; this.timer = window.requestAnimationFrame(this.enlarge); } }, narrow() { if (this.position === 0) { window.cancelAnimationFrame(this.timer); } else { this.position -= 58; this.timer = window.requestAnimationFrame(this.narrow); } }, enter() { window.cancelAnimationFrame(this.timer); this.timer = window.requestAnimationFrame(this.enlarge); }, leave() { window.cancelAnimationFrame(this.timer); this.timer = window.requestAnimationFrame(this.narrow); }, }, }

常规的方式, 利用了cancelAnimationFrame停止动画

网上的文章一般都是像第二种这样使用, 但是我比较喜欢第一种方式, 嘤嘤嘤~

发布评论
还没有评论,快来抢沙发吧!