【前端動畫】實現動畫的6種方式

一般在前端中,實現動畫的方案主要有6種:javascript

  • javascript直接實現;
  • SVG(可伸縮矢量圖形);
  • CSS3 transition;
  • CSS3 animation;
  • Canvas動畫;
  • requestAnimationFrame;

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 實現動畫一般會致使頁面頻繁性重排重繪,消耗性能,通常應該在桌面端瀏覽器。在移動端上使用會有明顯的卡頓。前端

Tip:爲何是16ms

上面例子中,咱們設置的setInterval時間間隔是16ms。通常認爲人眼能辨識的流暢動畫爲每秒60幀,這裏16ms比(1000ms/60)幀略小一些,可是通常可仍爲該動畫是流暢的。 
在不少移動端動畫性能優化時,通常使用16ms來進行節流處理連續觸發的瀏覽器事件。例如對touchmove、scroll事件進行節流等。經過這種方式減小持續事件的觸發頻率,能夠大大提高動畫的流暢性。java

SVG

SVG動畫由SVG元素內部的元素屬性控制,通常經過一下幾個元素控制:css3

  • : 用於控制動畫延時
  • :對屬性的連續改變進行控制
  • :顏色變化,但用就能控制
  • :控制如縮放、旋轉等幾何變化
  • :控制SVG內元素的移動路徑

示例

 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

CSS3 transition

transition是過分動畫。可是transition並不能實現獨立的動畫,只能在某個標籤元素樣式或狀態改變時進行平滑的動畫效果過渡,而不是立刻改變。瀏覽器

注意

在移動端開發中,直接使用transition動畫會讓頁面變慢甚至卡頓。因此咱們一般添加transform:translate3D(0,0,0)或transform:translateZ(0)來開啓移動端動畫的GPU加速,讓動畫過程更加流暢。性能優化

CSS3 animation

animation 算是真正意義上的CSS3動畫。經過對關鍵幀和循環次數的控制,頁面標籤元素會根據設定好的樣式改變進行平滑過渡。並且關鍵幀狀態的控制是經過百分比來控制的。

比較

CSS3最大的優點是擺脫了js的控制,而且能利用硬件加速以及實現複雜動畫效果。

Canvas動畫

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

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調用。

總結

複雜的動畫是經過一個個簡單的動畫組合實現的。基於兼容性問題,一般在項目中,通常在

  • 桌面端瀏覽器推薦使用javascript直接實現動畫或SVG方式;
  • 移動端能夠考慮使用CSS3 transition、CSS3 animation、Canvas或requestAnimationFrame方式**。
相關文章
相關標籤/搜索