一般在前端中,實現動畫的方案主要有6種:javascript
其主要思想是經過setInterval或setTimeout方法的回調函數來持續調用改變某個元素的CSS樣式以達到元素樣式變化的效果。css
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <style type="text/css"> 6 #rect { 7 width: 200px; 8 height: 200px; 9 background: #ccc; 10 } 11 </style> 12 </head> 13 <body> 14 <div id="rect"></div> 15 <script> 16 let elem = document.getElementById('rect'); 17 let left = 0; 18 let timer = setInterval(function(){ 19 if(left<window.innerWidth-200){ 20 elem.style.marginLeft = left+'px'; 21 left ++; 22 }else { 23 clearInterval(timer); 24 } 25 },16); 26 </script> 27 </body> 28 </html>
Jquery的animate()方法就是這種方式實現的。html
javascript 實現動畫一般會致使頁面頻繁性重排重繪,消耗性能,通常應該在桌面端瀏覽器。在移動端上使用會有明顯的卡頓。前端
上面例子中,咱們設置的setInterval時間間隔是16ms。通常認爲人眼能辨識的流暢動畫爲每秒60幀,這裏16ms比(1000ms/60)幀略小一些,可是通常可仍爲該動畫是流暢的。
在不少移動端動畫性能優化時,通常使用16ms來進行節流處理連續觸發的瀏覽器事件。例如對touchmove、scroll事件進行節流等。經過這種方式減小持續事件的觸發頻率,能夠大大提高動畫的流暢性。java
SVG動畫由SVG元素內部的元素屬性控制,通常經過一下幾個元素控制:css3
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <style> 7 *{ 8 margin:0; 9 padding:0; 10 } 11 </style> 12 </head> 13 <body> 14 <svg id="box" width="800" height="400" xmlns="http://www.w3.org/2000/svg" version="1.1"> 15 <rect x="" y="" width="100" height="100" fill="rgb(255,0,0);" stroke="" stroke-width=""> 16 <set attributeName="x" attributeType="XML" to="100" begin="4s"/> 17 <animate attributeName="x" attributeType="XML" begin="0s" dur="4s" from="0" to="300"/> 18 <animate attributeName="y" attributeType="XML" begin="0s" dur="4s" from="0" to="0"/> 19 <animateTransform attributeName="transform" begin="0s" dur="4s" type="scale" from="1" to="2" repeatCount="1" /> 20 <animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="4s" repeatCount="1" /> 21 22 </rect> 23 </svg> 24 25 </body> 26 </html>
這裏推薦一個在sublime text3中使用svg提示插件:svg snippet。web
SVG的一大優點是含有較爲豐富的動畫功能,原生繪製各類圖形、濾鏡和動畫,而且能被js調用。html是對dom的渲染,那麼svg就是對圖形的渲染。
可是,另外一方面元素較多且複雜的動畫使用svg渲染會比較慢,並且SVG格式的動畫繪製方式必須讓內容嵌入到HTML中使用。CSS3的出現讓svg的應用變得相對少了。canvas
transition是過分動畫。可是transition並不能實現獨立的動畫,只能在某個標籤元素樣式或狀態改變時進行平滑的動畫效果過渡,而不是立刻改變。瀏覽器
在移動端開發中,直接使用transition動畫會讓頁面變慢甚至卡頓。因此咱們一般添加transform:translate3D(0,0,0)或transform:translateZ(0)來開啓移動端動畫的GPU加速,讓動畫過程更加流暢。性能優化
animation 算是真正意義上的CSS3動畫。經過對關鍵幀和循環次數的控制,頁面標籤元素會根據設定好的樣式改變進行平滑過渡。並且關鍵幀狀態的控制是經過百分比來控制的。
CSS3最大的優點是擺脫了js的控制,而且能利用硬件加速以及實現複雜動畫效果。
canvas做爲H5新增元素,是藉助Web API來實現動畫的。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> *{ margin:0; padding:0; } </style> </head> <body> <canvas id="canvas" width="700" height="550"></canvas> <script type="text/javascript"> let canvas = document.getElementById("canvas"); let ctx = canvas.getContext("2d"); let left = 0; let timer = setInterval(function(){ ctx.clearRect(0,0,700,550); ctx.beginPath(); ctx.fillStyle = "#ccc"; ctx.fillRect(left,0,100,100); ctx.stroke(); if(left>700){ clearInterval(timer); } left += 1; },16); </script> </body> </html>
註釋:經過getContext()獲取元素的繪製對象,經過clearRect不斷清空畫布並在新的位置上使用fillStyle繪製新矩形內容實現頁面動畫效果。
Canvas主要優點是能夠應對頁面中多個動畫元素渲染較慢的狀況,徹底經過javascript來渲染控制動畫的執行。可用於實現較複雜動畫。
requestAnimationFrame是另外一種Web API,原理與setTimeout和setInterval相似,都是經過javascript持續循環的方法調用來觸發動畫動做。可是requestAnimationFrame是瀏覽器針對動畫專門優化造成的APi,在性能上比另二者要好。
一般,咱們將執行動畫的每一步傳到requestAnimationFrame中,在每次執行完後進行異步回調來連續觸發動畫效果。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 * { 7 margin:0; 8 padding:0; 9 } 10 div { 11 width: 200px; 12 height: 200px; 13 background-color: #ccc; 14 } 15 </style> 16 </head> 17 <body> 18 <div id="rect"></div> 19 <script type="text/javascript"> 20 window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || 21 window.msRequestAnimationFrame; 22 23 let elem = document.getElementById("rect"); 24 let left = 0; 25 //自動執行持續性回調 26 requestAnimationFrame(step); 27 //持續該改變元素位置 28 function step() { 29 if(left<window.innerWidth-200){ 30 left+=1; 31 elem.style.marginLeft = left+"px"; 32 requestAnimationFrame(step); 33 } 34 } 35 </script> 36 </body> 37 </html>
咱們注意到,requestAnimationFrame只是將回調的方法傳入到自身的參數中執行,而不是經過setInterval調用。
複雜的動畫是經過一個個簡單的動畫組合實現的。基於兼容性問題,一般在項目中,通常在