本文探讨在移动端硬件受限环境下,如何结合JavaScript与CSS3实现流畅动画。通过对比setTimeout/setInterval的缺陷,分析JS单线程阻塞与频繁重布局导致的卡顿问题。文章推荐利用CSS3 transition控制动画,并通过translate3d启用硬件加速、避免触发重布局属性,从而显著提升动画帧率与执行效率。
移动端动画开发的挑战与CSS3方案
当Html5,css3已渐渐成为主流的时候,我还非常习惯的用js去做一些简单的动画。因为在桌面浏览器上, 并非所有的都支持css3。用户也倒是很奇怪,用户习惯并不是每个用户都可以被培养。总有不少人会觉得win7.win8没xp好用。但手机方面就大不一样了,手机浏览器对html5和css3的支持还是很不错的。但手机硬件处理能力却又十分有限。在四核、八核手机横行的今天,依然有像我这样使用双核或单核手机的。js虽好,单奈何接触不多,调不好那种感觉。一个简单的页面滑动,在i7的pc上运行十分流畅,可是,在我的双核手机上就卡、顿、卡、顿。令人十分郁闷。为此,我也是寻找了很久很久,看了很多很多。终于在不就之前,找到了一种还算简单的方法:使用css3去执行动画。
传统JavaScript动画的局限性
过去,除了jQuery的animate等方法,动画多通过setTimeout或setInterval循环修改元素的margin、width、top等属性来实现。这种实现方式正是导致前述困惑的根源。
首先,setTimeout和setInterval并非设置0ms就能持续执行。在调试iscroll时曾发现此机制:定时器延时依赖浏览器内置时钟,而时钟精度取决于更新频率。例如IE8及更早版本的更新间隔为15.6毫秒。这意味着即使期望10ms执行1px位移,浏览器也无法精准按时执行。
卡顿与重布局的成因分析
卡顿的另一原因是代码质量。JavaScript是单线程的,若执行耗时操作,UI可能无响应。虽然使用setTimeout看似界面未死,但动作仍不流畅。因为setTimeout执行后,下次执行前的间隔内可能遇到其他耗时操作,导致setTimeout无限延迟,进而引发卡顿。此外,修改原始属性时可能意外触发浏览器重布局(Layout)。该问题有时可忽略,但很多时候不可忽略,需特别注意。
此外,在手机端常感觉动画是一帧一帧的,且帧长帧短不一。这同样与setTimeout的推迟有关,涉及丢帧问题,并与显示器刷新频率相关,情况较为复杂。
CSS3动画实现与性能优化技巧
最终选择CSS3方案,由JavaScript动态改变元素属性,并通过transition控制动画执行时间。示例如下:
代码如下:
<div id="test" style="transition:all 1s ease; width:100px;" ></div>
js:
代码如下:
$("#test").width(200);
这样1秒之后这个div的宽度会变成200px。不是孙悟空变桃子一样瞬间变大,慢慢的赶脚,不卡不顿。而且使用css动画有个好处,它不受耗时js的影响。虽然浏览器中UI线程与js线程是互斥,但这一点对css动画不成立,并且很多浏览器还能启用硬件加速(比如:Chrome)。虽然浏览器重布局普通情况下感觉不是很明显,但还是应该尽量避免大面积的重布局。so在动画元素上加上-webkit-transform: translateZ(0);或者-webkit-transform: translate3d(0,0,0);这样浏览器会独立渲染这一层。即便是重布局无法避免,这样面积也小些。而使用translate取代margin也确实是一个十分明智的决定。
触发重布局的常见属性列表
最后附上一些常用的改变时会触发重布局的属性:
代码如下:
width
height
padding
margin
display
border-width
border
min-height
以上就是本文所述的全部内容了,希望对大家学习javascript和CSS3能够有所帮助,同时不足之处烦请补充,谅解。