動畫,是指由許多幀靜止的畫面,以一定的速度(如每秒16張)連續播放時,肉眼因視覺殘象產生錯覺,而誤以為畫面活動的作品。
在 Web 開發中,經常需要實現各種動畫效果,例如:移動、變形、透明度變化等,今天我們主要來討論各種移動的實現。
直線移動
通常可以直接由各個點的位置,以及到點的時間與整個動畫持續時間的比值,寫出類似下面的程式碼並可實現動畫。
1 2 3 4 5 6 7 8 9 |
.cray { animation: move 2s alternate infinite; } @keyframes move { 0% { transform: translate(0, 0); } 30% { transform: translate(100px, 0); } 60% { transform: translate(100px, 100px); } 100% { transform: translate(200px, 0); } } |
曲線移動
在 CSS 中可以通過 transform-origin
配合 rotate
實現曲線移動,不過這種 曲線
都是圓的一部分且不太好控制。
這種移動我們可以把它拆分成兩個方向的運動疊加,如
更詳細的說明可以參考這篇文章 《curved-path-animations-in-css》。
路徑移動
這也是曲線移動,但是想像上面那樣,這個很難拆分成幾個方向的運動疊加。這樣的移動路徑可以嘗試以下幾個方法:
- SVG Animation
這樣的路徑可以比較好的用 SVG path 來描述,然後使用 SVG Animation 做跟隨動畫,並可以達到預期的軌跡效果。
主要程式碼(線上示例):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<svg width="420px" height="260px" viewBox="0 0 420 260" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g stroke="#979797" stroke-width="1" fill="none"> <path id="motionPath" d="M370.378234,219.713623 C355.497359,218.517659 ..." ></path> </g> <g id="cray" transform="translate(0, -24)" stroke="#979797"> <image id="cray-img" xlink:href="http://7xt5iu.com1.z0.glb.clouddn.com/img/cray.png" x="0" y="0" width="100px"/> </g> <animateMotion xlink:href="#cray" dur="5s" begin="0s" fill="freeze" repeatCount="indefinite" rotate="auto-reverse" > <mpath xlink:href="#motionPath" /> </animateMotion> </svg> |
效果:
- JavaScript
使用 JavaScript 可以直接操作元素進行運動,理論上可以實現任何動畫,只是實現一些複雜的動畫成本比較高,好在有各種已經開發好了的工具庫可以供我們使用。例如,使用 Greensock 的 TweenMax 和 MorphSVGPlugin(收費),通過 MorphSVGPlugin 提供的 pathDataToBezier 方法將 SVG path 轉成曲線陣列,然後給 TweenMax 使用:
1 2 3 4 5 6 7 8 9 10 11 |
var hill = document.getElementById('hill') var path = MorphSVGPlugin.pathDataToBezier("#motionPath"); TweenMax.to(hill, 5, { bezier:{ values:path, type:"cubic", autoRotate: 180 }, ease:Linear.easeNone, repeat: -1 }) |
- CSS
實現動畫,其實就是在相應的時間點做相應的“變化”。再回頭看直線移動的實現方式,其實如果能給出足夠多點的位置和該點的時間與持續時間的比值,那其實曲線也可以直接用 CSS 來實現。
很多時候設計師使用 AE 來設計動畫,當我們拿到設計稿後,可以給動畫增加關鍵幀,然後藉助一些工具把關鍵幀的資訊匯出來,這裡介紹一個 keyframes-cli,可以匯出這樣結構的資料
從屬性名字可以判斷出來 X_POSITION
和 Y_POSITION
是 x
和 y
的位置資訊,而 key_values
裡的 data
就是我們需要的點位置
, 該點的時間與持續時間的比值
可以根據 start_frame
得出,
寫個指令碼把這些資料處理下,可得到類似下面的 CSS 程式碼
設定的關鍵幀越多,動畫會越流暢,但 CSS 也會增多。
注意:不是 AE 關鍵幀裡所有的資訊都可以匯出來,還跟 AE 裡使用的過渡屬性有關,這裡有介紹。
最後,總結一下,移動動畫就是用一種合適的方式把時間和位置的變化關係展示出來。除了上面方法,肯定還有很多其他的方法和幫助工具,歡迎留言交流討論。