9.淺談前端實現動畫效果的一些方式

淺談前端實現動畫效果的一些方式(包括但不限於)。javascript

如下內容是我16年3月份在公司作內部分享時的一些內容,雖然時間有點遠,可是我以爲仍是比較適用的。css

1. Flash,好久之前都會使用的一個方式,在十年之前甚至有不少用純flash作的網站,我本身還作過一個,仍是比較有意思的。到了中期,用flash來作動畫效果後再引到html內,在html5 video以前也基本用flash的音視頻播放器。如今基本已經棄用。html

  • 功能強大:動畫、視頻、播放器、特效等。
  • 有flash的腳本語言ActionScript,簡稱AS。能作網頁、能作事件交互、可以完成js作不了的BOM操做和本地操做等
  • 移動端不兼容
  • 過期-adobe已放棄-正式中止更新

2. GIF圖片
gif.gif前端

  • 兼容性最好
  • 畫質差,PNG有毛邊
  • 無交互、圖片大
  • 前端人員不太擅長製做

3.javascript 定時器動畫 setInterval setTimeouthtml5

定時器:實現上就是經過一個定時器setInterval 每隔必定時間來改變元素的樣式,動畫結束時clearInterval便可。早期的類庫包括 jquery、prototype等等都是這種方式。在CSS3以前,最初的前端動畫大多都是JS來實現。java

  • 使用簡單,能夠交互,可控性很強,兼容好
  • 性能不佳,由於須要不斷獲取和修改Dom的佈局,因此致使了大量頁面重繪
  • 缺少標準,不一樣的庫使用了不一樣的API,致使即便是簡單的動畫也有各不相同的實現方式
  • 複雜和長時間的定時器在移動端效果不穩定
  • 定時器不靠譜:setInterval多個間隔可能會被跳過,setInterval多個間隔可能比預期小,不一樣瀏覽器的精度不一樣

4. css3動畫
transition過渡:顧名思議,能夠實現一些簡單的不須要太多的控制與步驟的過渡動畫。jquery

animation動畫:與transition不一樣的是,animation屬性能夠像FLASH製做動畫同樣,經過關鍵幀控制動畫的每一步,實現更爲複雜的效果。而且功能更強大。ios

css3動畫相比與JS動畫更輕量,性能更好,更易於實現。animation相比 transtion 使用起來更爲複雜,但也提供了更多的控制。css3

css3動畫缺點:不一樣的動畫沒法實現同步,多個動畫彼此沒法堆疊,複雜的動畫編輯麻煩,低版本兼容性很差。web

關於CSS3動畫,網上案例太多,就不細說了。

5.SVG實現動畫
svg動畫可以實現的:

  • 動畫元素的數值屬性(X, Y, …)
  • 動畫屬性變換(平移或旋轉)
  • 動畫顏色屬性
  • 沿着運動路徑運動

前面的三條CSS3都是能夠有所擔當的,最後這一條,呵呵。

示例1:

<svg width="120" height="420" >
    <rect x="10" y="10" width="100" height="100">
        <animate attributeType="XML"
                 attributeName="y"
                 from="-100" to="120"
                 dur="5s"
                 repeatCount="1"
                 fill="remove"/>
    </rect>
</svg>

attributeType:CSS|XML|auto,變化的是屬性仍是CSS仍是自動匹配,能夠省
attributeName:要變化的元素屬性名稱,也能夠是CSS名稱
from:開始值
to:結束值
repeatCount:表示動畫執行次數,能夠是合法數值或者無限「indefinite」
dur:動畫時間,常見單位有 "h"|"min"|"s"|"ms"
fill:表示動畫結束狀態。支持參數有:freeze | remove. 其中remove是默認值,表示動畫結束直接回到開始的地方。freeze「凍結」表示動畫元素保持了動畫結束以後的狀態。
不寫form to的狀況下,能夠寫values="300;200;300"

示例2:多個變化一塊兒

<svg width="800" height="300" >
 <g transform="translate(100,100)" >
    <text id="TextElement" x="0" y="0"
          font-family="Verdana" font-size="35.27" visibility="hidden"  >
      It's alive!
      <set attributeName="visibility" attributeType="CSS" to="visible"
           begin="1s" dur="6s" fill="freeze" />
      <animateMotion path="M 0 0 L 100 100"
           begin="1s" dur="6s" fill="freeze" />
      <animate attributeName="fill" attributeType="CSS"
           from="rgb(0,0,255)" to="rgb(128,0,0)"
           begin="1s" dur="6s" fill="freeze" />
      <animateTransform attributeName="transform" attributeType="XML"
           type="rotate" from="-30" to="0"
           begin="1s" dur="6s" fill="freeze" />
      <animateTransform attributeName="transform" attributeType="XML"
           type="scale" from="1" to="3" additive="sum"
           begin="1s" dur="6s" fill="freeze" />
    </text>
  </g>
</svg>

set:是animate的簡化,主要用來改變非數值屬性的屬性值。
begin:延時開始
animateMotion:沿某運動路線移動SVG元素。
additive控制動畫是否附加。支持參數有:replace | sum. 默認值是replace.

示例3:延着某一路徑

<body>


<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
  <text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#cd0000">馬
    <animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" repeatCount="indefinite"/>
  </text>
  <path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>

<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
  <text font-family="microsoft yahei" font-size="40" x="0" y="0" fill="#cd0000">馬
    <animateMotion path="M10,80 q100,120 120,20 q140,-50 160,0" begin="0s" dur="3s" rotate="auto" repeatCount="indefinite"/>
  </text>
  <path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>


<svg width="5cm" height="3cm"  viewBox="0 0 500 300">
  <path id="path1" d="M100,250 C 100,50 400,50 400,250"
        fill="none" stroke="blue" stroke-width="7.06"  />
  <circle cx="100" cy="250" r="17.64" fill="blue"  />
  <circle cx="250" cy="100" r="17.64" fill="blue"  />
  <circle cx="400" cy="250" r="17.64" fill="blue"  />

  <path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z" fill="yellow" stroke="red" stroke-width="7.06"  >
    <animateMotion dur="6s" repeatCount="indefinite" rotate="auto" >
       <mpath xlink:href="#path1"/>
    </animateMotion>
  </path>
</svg>
</body>

經過將 rotate="auto" ,用來控制是否自動旋轉

示例4:SVG結合CSS3作點有意思的事情:

<style>
* {
     margin: 0;
     padding: 0;
}
path {
  stroke-dasharray:44;animation: dash 5s linear infinite;
}
@keyframes dash {
  to {
    stroke-dashoffset: 1000;
  }
}
</style>
</head>
<body>
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
  <path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>
</body>

<style>
* {
     margin: 0;
     padding: 0;
}
path {
   stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: dash 5s linear infinite;
}
@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}
</style>
</head>
<body>
<svg width="360" height="200" xmlns="http://www.w3.org/2000/svg">
  <path d="M10,80 q100,120 120,20 q140,-50 160,0" stroke="#cd0000" stroke-width="2" fill="none" />
</svg>
</body>

svg動畫總結

  • svg能夠實現比DIV更復雜的圖形,因此也能夠實現更復雜的動畫
  • svg DOM結構能夠被其特定語法(animate)或者Javascript控制,從而輕鬆的實現動畫
  • 整個SVG做爲一個動畫,而且動畫複雜編輯麻煩
  • 效率不高,並且若是其結構多而雜,就更慢
  • 瀏覽器兼容性很差,IE8-以及Android 2.3如下是不支持SVG,移動端未測

html5 的canvas、webgl,只是增長了繪畫方式的選擇,與動畫的怎麼變化無關,沒有實現動畫的API,你必須依靠定時器和其餘事件來更新畫布。因此與本次說的主題動畫無關。可是html5也提供了一個新的動畫接口....

6.RAF
性能更好的js動畫實現方式——requestAnimationFrame。

前面說過,JS定時器有着嚴重的性能問題,雖然某些現代瀏覽器對這兩函個數進行了一些優化,但仍是沒法跟css3的動畫性能相提並論。可是css3動畫仍是有很多侷限性,好比不是全部屬性都能參與動畫、動畫緩動效果太少、沒法徹底控制動畫過程等等。這個時候,就該requestAnimationFrame出馬了。

這專門爲實現高性能的幀動畫而設計的一個API,目前已在多個瀏覽器獲得了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移動設備上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,惟一比較遺憾的是目前低版本安卓上並不支持,不過將來全面支持這已是大勢所趨。

<body>
<div id="box" style="width:1px;height:100px; background:red"></div>
<script>
var oBox=document.getElementById('box');
var w=1,id;
function render(t){    
    console.log(t);//返回的間隔時間
    w++;
    oBox.style.width=w+'px';
    if(w<500)id=requestAnimationFrame( render );
    console.log(id);
};
id=requestAnimationFrame( render );
oBox.onclick=function(){
    cancelAnimationFrame(id);    //經過id中止
};

</script>

</body>

是否是看起來很簡單就能夠實現。

  • requestAnimationFrame 會把每一幀中的全部DOM操做集中起來,在一次重繪中就完成,而且重繪或迴流的時間間隔牢牢跟隨瀏覽器的刷新頻率,通常來講,這個頻率約爲每秒60幀(每幀約16MS)。
  • 若是頁面不是激活狀態下或在隱藏或不可見的元素中,將不會進行重繪,這固然就意味動畫會自動暫停,有效節省了cpu和內存使用量。
  • 原理其實也就跟定時器差很少,經過遞歸調用同一方法來不斷更新畫面以達到動起來的效果,但它優於定時器的地方在於它是由瀏覽器專門爲動畫提供的API,在運行時瀏覽器會自動優化方法的調用。
  • 因此,能夠這麼說,requestAnimationFrame就是一個性能優化版、專爲動畫量身打造的setTimeout,不一樣的是requestAnimationFrame不是本身指定回調函數運行的時間。
  • 在前幾年各個支持requestAnimationFrame的瀏覽器有些仍是本身的私有實現,因此必須加前綴,對於不支持requestAnimationFrame的瀏覽器,咱們只能使用setTimeout,由於二者的使用方式幾近相同,因此這二者的兼容並不難。對於支持requestAnimationFrame的瀏覽器,咱們使用requestAnimationFrame,而不支持的咱們優雅降級使用傳統的setTimeout。把它們封裝一下,就能獲得一個統一兼容各大瀏覽器的API了。

*總結:
不管何種需求,首選RAF
輕量級簡單動畫用css3
複雜動畫效果CSS3不能知足的狀況下用JS定時器
以上都沒法知足的狀況下仍是網上找相應的動畫庫吧(js庫、css3庫、svg動畫庫)*

附:簡單封裝RAF:requestAnimationFrame

相關文章
相關標籤/搜索