本文你将看到:
- Vue页面初始化加载进度条动画:animation方式
- transition ,transform, translate三者的用法(一年之内不写就忘)
- 动画性能对比
1. Vue页面初始化加载进度条动画 :animation方式
场景:
今天要写一个进度条动画,但是我平时写简单的动效都是用transition+transform的方式,已经习惯了,但这个动画的场景是页面一载入就执行,transition的方式的话,常用方式总是需要hover或者一些动作才能触发。所以我选择了animation,以为很简单,但实际写起来没想到真的很简单。印象中有动画性能比较这件事,所以我又学了点东西,后续有写到。
效果:
进入页面时播放动画,浮标从头移动,停在指定位置。我不方便录屏。
思路:
元素分为两部分:浮标buoy和进度条bar
页面挂载完成mounted时执行函数,为元素添加动画类。
此处注意ref是空对象,因此在mounted阶段取值,nextTick方式也可以。进度条bar思路相同,只不过如图,灰色底色不动,上层黄色用遮罩方式,执行动画。
animation还有许多属性,可以做复杂的动画,可以自己去学习。
HTML
<!--动画进度条-->
<div class="bar-wrapper">
<!--浮标-->
<img ref="buoy"
src="http://p0.meituan.net/scarlett/127d53efa1189f26053b702c15771db4547.png"
alt
class="buoy"/>
<!--进度条-->
<div class="bar">
<span v-if="grade <= 35" class="text text-mid">中</span>
<span v-if="grade <= 65" class="text text-high">高</span>
<!--黄色条-->
<div ref="bar" class="bar-yellow-modal">
<span class="text-in-yellow yellow-low">低</span>
<span v-if="grade > 35" class="text-in-yellow yellow-mid">中</span>
<span v-if="grade > 65" class="text-in-yellow yellow-high">高</span>
</div>
</div>
</div>
JS
mounted() {
// 执行进度条动画
this.animation();
},
methods: {
animation() {
if (this.$refs && this.$refs.buoy && this.$refs.bar) {
let elBuoy = this.$refs.buoy;
let elBar = this.$refs.bar
console.log(this.$refs)
if (this.grade && this.grade > 0) {
switch (true) {
case 0 < this.grade && this.grade <= 35 :
elBuoy.className = 'buoy buoy-moving-step-1';
elBar.className = 'bar-yellow-modal bar-step-1';
break;
case 35 < this.grade && this.grade <= 65 :
elBuoy.className = 'buoy buoy-moving-step-2';
elBar.className = 'bar-yellow-modal bar-step-2';
break;
case 65 < this.grade :
elBuoy.className = 'buoy buoy-moving-step-3';
elBar.className = 'bar-yellow-modal bar-step-3';
break;
}
}
}
}
}
CSS,只贴了浮标的样式,bar同理。
.buoy {
width: 12px;
height: 12px;
margin-bottom: 5px;
}
.buoy-moving-step-1{
animation: buoy-moving-step-1 1s ease-out;
animation-fill-mode: forwards;
}
.buoy-moving-step-2{
animation: buoy-moving-step-2 1.5s ease-out;
animation-fill-mode: forwards;
}
.buoy-moving-step-3{
animation: buoy-moving-step-3 1.8s ease-out;
animation-fill-mode: forwards;
}
@keyframes buoy-moving-step-1 {
0% {
margin-left: 0;
}
100% {
margin-left: 111px;
}
}
@keyframes buoy-moving-step-2 {
0% {
margin-left: 0;
}
100% {
margin-left: 222px;
}
}
@keyframes buoy-moving-step-3 {
0% {
margin-left: 0;
}
100% {
margin-left: 300px;
}
}
2. transition ,transform, translate三者的用法
从英文释义上来理解:
transform:变换,参数可以是translate,scale,rotate等;
translate:位移,是transform的一个属性;
transition:过渡,是唯一有时间参数的!transform可以作为他的一个参数。
例子:
transition:transform 2s ease-in , border-radius 3s ease-out; //可同时设置多个属性的动画,用逗号隔开
transform:translateX(50px);
3. 动画性能对比 transition < transform ,position < translate,animation适合场景
写法举例,我们实现一个动画,鼠标悬浮在元素上,元素的宽度变化。
transition方式:
<body>
<div class="foo"></div>
</body>
<style>
.foo {
height: 100px;
width: 100px;
transition: height 1s linear;
}
.foo:hover {
width: 200px;
}
</style>
transform 方式:(也是要使用transition的)
<body>
<div class="foo"></div>
</body>
<style>
.foo {
height: 100px;
width: 100px;
transition: transform 1s linear;
}
.foo:hover {
transform: scaleX(2);
}
</style>
animation 方式:
.block {
animation: widen 2s ease;
animation-fill-mode: forwards;
}
@keyframes widen {
from {
width: 100px;
}
to {
width: 200px;
}
}
铺垫知识
- 浏览器渲染页面的任务由两个线程完成:主线程 和 排版线程
- GPU:
GPU上合成涂层可以在涉及大量像素的绘图和合成操作中实现比CPU还要好的效率,硬件专为这些类型的负载而设计。更详细的知识参考链接:https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/ - 渲染过程:
不同属性值引起的重新绘制有3种路径:- layout->paint->composite
- paint->composite
- composite
CSS的属性也就此分为3大类:布局类(layout),绘制类(paint),合成类(composite)
composite 属性目前只有两个:transform和opacity
transition:
transition做动画时两个线程的工作情况是:对于浏览器来说,元素的高度一直在变化,因此这个动画的每一帧都需要主线程对元素进行布局,绘制成位图,将位图交由GPU线程,GPU将位图绘制到屏幕。两个线程来回切换工作,即使是移动十几个像素,主线程也需要对元素布局很多次,这部分的工作消耗相当大,相对较慢,这也是transition动画经常卡顿的原因。
transform:
使用transform时浏览器的工作情况是:主线程对元素进行布局,绘制成位图,交由GPU线程,transform执行的整个过程都在GPU进程执行绘制,两个线程来回切换的情况不多,而且transform不会触发浏览器的重新排版,不会影响周围的布局,这也意味着这种情况的动画比transition流畅一些。
position VS translate
当页面需要位移动画时,可能会用到这两种,position的原理和transition符合,会触发浏览器的重排,translate不会,所以最好选择transform的translate,rotate,scale等方法。
animation
transition是使一个或多个属性值产生过渡效果,animation则作用于元素本身,强调流程与控制,是关键帧动画的范畴。简单的效果可以用animation,复杂的或想要更自由地掌控应该选择animation。我认为animation会更占资源一些。
硬件加速 will-change + translateZ(0)
transform:translate3d(0,0,0);
transform:translateZ(0);
will-change:transform;
参考:
https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/
https://juejin.im/entry/59dc9aedf265da43200232f9