CSS3 transition动画的FLIP动画学习,反转动画来解决动画的卡顿,闪烁。
2017-03-18 16:06

FLIP动画

web前端可谓是个无底洞,永远学不到头,知道的东西越多,就明显感觉到自己不会的越多。细细一数,发现需要学的知识能列出上百条来。只能淡定下来,一个一个的学习。心急吃不了热豆腐,不论是js,还是CSS,都实际工作中应用了三年了,仍然深感掌握的肤浅。

今天学习了一个叫FLIP动画的知识,拿出来给大家分享一下。

FLIP是几个英文字母的缩写:First ,Last,Invert,Play。并不能算是一种新技术,只是CSS transition,CSS animation动画的一种新的致力于动画流畅的实现方式。

这个FLIP的重点就是将transition动画或animation动画反转过来实现,从而达到提高过渡动画的流畅度。什么叫把动画反转过来呢?

var rt=tg2.getBoundingClientRect();
tg2.style.left="400px";
var rt2=tg2.getBoundingClientRect();
var invert=rt.left-rt2.left;
console.log(invert);
tg2.style.transform="translateX("+invert+"px)";
requestAnimationFrame(function(){
    tg2.className=tg2.className+" trans2";
    tg2.style.transform="";
});


.trans2{
    transition:transform 3s linear;
}

上面的代码就是动画反转的实现代码:

先保存tg2当前的位置大小对象,然后将元素的left设置为动画终点位置“400px”,这时tg2其实已经到达了动画结束位置了。然后通过计算"rt.left-rt2.left"得到开始位置和结束位置的left差值。再通过设置transform属性,让tg2通过transform从结束位置恢复到开始位置。最后通过requestAnimationFrame在下一帧动画中添加过渡,移除transform。这样实现动画的方式外国人给起了个名字,就叫“FLIP”动画,翻译成中文就是“反转动画”。

    FLIP动画有什么好处呢?

    最大的好处就是提高动画的流畅度,就是提高动画流畅度,就是提高动画流畅度。重要的事情说三遍。如果你在WEB页面中无论是通过transition,还是animation实现的动画出现卡顿,闪烁,不流畅的瑕疵,并且你是一个较真的人,考虑用户体验的开发人员,那么你可以尝试用FLIP重构你的动画,来抹去这些动画上的瑕疵,让它看起来真的就是动画,让你或者用户看起来心情是那么舒服,痛快。

    FLIP动画为什么能提高动画流畅度?

    我们原来实现动画的方式是从开始位置一点点像结束位置进行动画,这样浏览器会在每一帧动画时进行大量复杂的计算,如果你的机器不是那么强悍,它看起来就会卡顿,闪烁。

    

    这是摘自别人网站的一个用户交互体验的原理图。用户在网页上进行交互时,比如click,touch,从交互结束到感知到程序的相应大约需要100ms的生理反应时间。如果你的网站在100ms内作出了相应的响应,那么在用户看来,就是得到了立即的响应。否则用户就会觉得反应延迟。这个玩游戏的都深有体验,你们在打Dota,撸啊撸的时候,如果网络状况是100ms+的话,你就会明显感觉到游戏的延迟,别人已经拿技能丢你了,在技能打到你身上时你才察觉到,想跑为时已晚,不得不说超过100ms那是一种多么糟糕的体验啊。在100ms+的情况竞技游戏还能打的那么好的,不能说你技术很好,只能赞叹你的思想很有深度,预判能力太强悍了。

    所以我们在用户交互后要做100ms内准备好动画,然后以60fps的帧速进行动画的运行。这些动画准备计算就是getBoundingClientRect等的计算,而60fps的真素,则需要通过transform或者opacity的反转动画来实现。我们先将元素设置到了结束位置,通过transform来模拟开始位置,然后去除transform这个反向的过程,使得浏览器知道了动画的开始位置和结束位置,计算量锐减,流畅度速度提升。

    这里你可能说那么我们普通的正向动画中,浏览器就不能按照先计算出结束位置,再计算其中每一帧的动画吗?

    这个呢,也许将来浏览器会这么做,但现在浏览器没有这么做,所以我们就需要先通过FLIP技巧来让浏览器这么做。

    多个动画的衔接可以利用对动画结束时100ms的感知时间

    如果你的动画是先将元素从左移动到右边,然后从上边移动到下边。那么第二个动画的准备计算要利用用户对动画结束的50-100ms感知时间,然后再通过FLIP进行我们的60fps动画,这么做,在观察者看来,动画是连贯并且流畅的。

    用户的感知时间是100ms,所以在动画准备阶段,即使你是使用了这种FLIP反转动画,也不要在动画准备阶段做太多的计算,这个时间控制你可以使用打印当前时间的方法,也可以使用开发工具查看。

    将高开销的动画转化成transform动画

    transform和opacity天生就是为动画准备的,他们不会导致重排或重绘,减少浏览器在每帧中的计算量。而诸如width,height,left,top,margin等的动画属于高开销动画,我们应该将他们转变成transform动画。例如width可以使用transform:scaleX(x)来代替,height可以使用transfrom:scaleY(y)来代替,left,top可以使用transform:translate(x,y)来代替。并且进行动画的元素最好是absolute定位的,absolute的元素不会影响其他元素进行重绘或重排。这样后,再利用我们的FLIP动画反转,就能大幅度提高动画的流畅度了。

   FLIP动画效果跟普通动画效果的对比

   虽说这PC端,计算机运算速度比较快,但是transition的动画过渡,还是有明显的卡顿现象。通过FLIP处理后,动画就显得流畅了,写了一个普通动画和FLIP动画的对比demo:FLIP动画和普通动画的transiton效果对比。当然要想看到效果,你得在支持transition的浏览器中运行。

    blob.png

     一个是改变div宽度的动画,一个时改变红色div位置的动画,这个可以说是最基础的动画了。但是这个动画在火狐下面是没有效果的,原因是,开始添加了transform,开始动画后去除transform,火狐不认为是进行了transform改变。这个应该说是一个bug。

        这个demo中还写了一个animation动画中的left,和transform的对比。

blob.png

两个小方块都是循环左右移动,上面的是animation中使用left来实现动画,第二个是animation中使用transform实现动画。这样在chrome浏览器中对比效果很明显,下面的比上面的流畅度高的多。

@keyframes myanimate {
    0%{
        transform:translateX(-400px);
    }
    50%{
        transform: none;
    }
    100%{
        transform: translate(-400px);
    }
}
@keyframes myanimate2 {
    0%{
        left:0px;
    }
    50%{
        left:400px;
    }
    100%{
       left:0px;
    }
}
.animte2{
    animation:myanimate2 5s linear infinite alternate;
}
.animte{
    animation:myanimate 5s linear infinite alternate;
}


总结

    FLIP动画,是一种动画机制,策略,通过反转动画来提高流畅度,只能说是一种hack技术。为此,谷歌还封装了一个叫flipjs的库用来处理此类的动画。这个动画优化我们只能是学习外国人整理的东西,国内没有环境让我们前端人员去深究浏览器的内部机制。就算想深究有时也不可行,比较好多前端就是前端,不是计算机科班出身,不会C语言,不懂C++,甚至java都看不明白。学习别人的东西也未尝不好,只要你认真学,那么学过来就是自己的了,而且省下了研究的时间还可以做很多有意义的事情,比如说把把妹纸,泡个妞啊,或者高雅的品品茶,享受享受生活。

原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(5982)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1