作者:桂圓_noble
http://www.reibang.com/p/280e0ef90b96
作為一只前端開發(fā)者踊东,我們的使命就是在滿足產(chǎn)品需求吐咳、實現(xiàn)交互設(shè)計的基礎(chǔ)上厅目,將最好的體驗呈現(xiàn)給用戶爸爸們叙谨。在保證性能的同時棒口,我們通常會給頁面加一些動態(tài)效果嚼隘,以增強(qiáng)頁面的表現(xiàn)力并提升頁面的交互體驗诽里。故將前端實現(xiàn)動效的幾種常用方式整理成此篇小結(jié),以求溫故而知新飞蛹。
動畫即童年
動畫是指由許多幀靜止的畫面谤狡,以一定的速度(如每秒16張)連續(xù)播放時,肉眼因視覺殘象產(chǎn)生錯覺卧檐,而誤以為畫面活動的作品墓懂。——維基百科
以上是維基百科上給出的動畫的定義霉囚。相信每一個像我這樣有童年的孩子捕仔,應(yīng)該都玩過手翻書,或者就算你的童年稍微暗淡一點盈罐,應(yīng)該也看過動畫片吧...嗯嗯榜跌,并沒有跑題,其實這和我們今天提及的動畫本質(zhì)上是一樣的盅粪,只不過就是呈現(xiàn)方式或者說載體發(fā)生了改變钓葫。
超人大戰(zhàn)賽亞人
幾個基本概念
簡單介紹幾個關(guān)于動畫的基本概念。
幀:在動畫過程中票顾,每一幅靜止畫面即為一“幀”础浮;
幀率:即每秒鐘播放的靜止畫面的數(shù)量帆调,單位是fps(Frame per second)或赫茲(Hz);
幀時長:即每一幅靜止畫面的停留時間豆同,單位一般是ms(毫秒)贷帮;
丟幀:在幀率固定的動畫中,某一幀的時長遠(yuǎn)高于平均幀時長诱告,導(dǎo)致其后續(xù)數(shù)幀被擠壓而丟失的現(xiàn)象撵枢;
我們在顯示器上看到的動畫,每一幀變化都是系統(tǒng)繪制出來的(GPU或者CPU)精居。它的最高繪制頻率受限于顯示器的刷新頻率(而非顯卡锄禽,大多數(shù)是60Hz或者75Hz)。
幀頻越高靴姿,屏幕上圖片閃爍感就越小沃但,穩(wěn)定性也就越高。人的眼睛不容易察覺75Hz以上刷新頻率帶來的閃爍感佛吓。
實現(xiàn)方式
通常我們在前端實現(xiàn)動畫效果的幾種主要實現(xiàn)方式如下:
JavaScript:通過定時器(setTimeout 和 setIterval)來間隔來改變元素樣式宵晚,或者使用requestAnimationFrame;
CSS3:transition 和 animation维雇;
HTML5:使用HTML5提供的繪圖方式(canvas淤刃、svg、webgl)吱型;
requestAnimationFrame
requestAnimationFrame是瀏覽器用于定時循環(huán)操作的一個接口逸贾,類似于setTimeout,主要用途是按幀對網(wǎng)頁進(jìn)行重繪津滞。
設(shè)置這個API的目的是為了讓各種網(wǎng)頁動畫效果(DOM動畫铝侵、Canvas動畫、SVG動畫触徐、WebGL動畫)能夠有一個統(tǒng)一的刷新機(jī)制咪鲜,從而節(jié)省系統(tǒng)資源,提高系統(tǒng)性能撞鹉,改善視覺效果疟丙。代碼中使用這個API,就是告訴瀏覽器希望執(zhí)行一個動畫孔祸,讓瀏覽器在下一個動畫幀安排一次網(wǎng)頁重繪隆敢。
requestAnimationFrame使用一個回調(diào)函數(shù)作為參數(shù)发皿,這個回調(diào)函數(shù)會在瀏覽器重繪之前調(diào)用崔慧,由于功效只是一次性的,所以想實現(xiàn)連續(xù)的動效穴墅,需要遞歸調(diào)用惶室,示例如下:
<div id="demo"?style="position:absolute; width:100px; height:100px; background:#ccc; left:0; top:0;"></div>
<script>
var?demo?=?document.getElementById('demo');
function?render(){
????demo.style.left?=?parseInt(demo.style.left)?+?1?+?'px';?//每一幀向右移動1px
}
requestAnimationFrame(function(){
????render();
????//當(dāng)超過300px后才停止
????if(parseInt(demo.style.left)?<=?300)?requestAnimationFrame(arguments.callee);
});
</script>
cancelAnimationFrame方法用于取消重繪:
var?requestID?=?requestAnimationFrame(repeatOften);
cancelAnimationFrame(requestID);
使用requestAnimationFrameAPI的優(yōu)勢如下:
會把每一幀中的所有DOM操作集中起來温自,在一次重繪或回流中就完成,并且重繪或回流的時間間隔緊緊跟隨顯示器的刷新頻率(60 Hz或者75 Hz)皇钞;
在隱藏或不可見的元素中悼泌,將不會進(jìn)行重繪或回流,這當(dāng)然就意味著更少的的cpu夹界,gpu和內(nèi)存使用量馆里;
目前,主要瀏覽器Firefox 23 / IE 10 / Chrome / Safari)都支持這個方法可柿○伲可以用下面的方法,檢查瀏覽器是否支持這個API复斥。如果不支持营密,則自行模擬部署該方法。
window.requestAnimFrame?=?(function(){
??return??window.requestAnimationFrame?||
??????????window.webkitRequestAnimationFrame?||
??????????window.mozRequestAnimationFrame?||
??????????window.oRequestAnimationFrame?||
??????????window.msRequestAnimationFrame?||
??????????function(/* function FrameRequestCallback */?callback,?/* DOMElement Element */?element){
????????????window.setTimeout(callback,?1000?/?60);
??????????};
})();
所以目锭,可以這么說评汰,requestAnimationFrame就是一個性能優(yōu)化版、專為動畫量身打造的setTimeout痢虹,不同的是requestAnimationFrame不是自己指定回調(diào)函數(shù)運行的時間被去,而是跟著瀏覽器內(nèi)建的刷新頻率來執(zhí)行回調(diào),這當(dāng)然就能達(dá)到瀏覽器所能實現(xiàn)動畫的最佳效果了奖唯。
DEMO傳送門:https://jsfiddle.net/gaogy/wwaejvLn/
Transition
CSS 中的 transition 屬性允許塊級元素中的屬性在指定的時間內(nèi)平滑的改變编振,簡單看下其語法規(guī)則:
transition: property duration timing-function delay;
具體屬性值介紹如下:
DEMO傳送門:http://www.w3school.com.cn/tiy/t.asp?f=css3_transition
Animation
類似的CSS還提供了一個Animation屬性,不過區(qū)別于Transition臭埋,Animation作用于元素本身而不是樣式屬性瓢阴,可以使用關(guān)鍵幀的概念液斜,應(yīng)該說可以實現(xiàn)更自由的動畫效果硼被。
語法
具體屬性值介紹如下:
DEMO傳送門:http://www.w3school.com.cn/tiy/t.asp?f=css3_animation
Canvas
<canvas>
是HTML5新增的元素始鱼,作為頁面圖形繪制的容器医清,可用于通過使用JavaScript中的腳本來繪制圖形筒捺。例如,它可以用于繪制圖形贫导,制作照片逾滥,創(chuàng)建動畫,甚至可以進(jìn)行實時視頻處理或渲染欢顷,Canvas具有如下特點:
依賴分辨率缆巧,基于位圖;
不支持事件處理器逞敷;
弱的文本渲染能力侧啼;
能夠以 .png 或 .jpg 格式保存結(jié)果圖像哪审;
最適合圖像密集型的游戲,其中的許多對象會被頻繁重繪舌狗;
大多數(shù) Canvas 繪圖 API 都沒有定義在?<canvas>
元素本身上叽奥,而是定義在通過畫布的getContext()方法獲得的一個“繪圖環(huán)境”對象上。Canvas API也使用了路徑的表示法痛侍。但是朝氓,路徑由一系列的方法調(diào)用來定義,而不是描述為字母和數(shù)字的字符串主届,比如調(diào)用 beginPath() 和 arc() 方法赵哲。一旦定義了路徑,其他的方法君丁,如 fill()誓竿,都是對此路徑操作。
DEMO傳送門:https://jsfiddle.net/gaogy/rzss4mmr/
SVG
SVG是英文Scalable Vector Graphics的縮寫谈截,意為可縮放矢量圖形筷屡,用來定義用于網(wǎng)絡(luò)的基于矢量的圖形,其使用 XML 格式定義圖像簸喂,并且具有如下特點:
不依賴分辨率毙死,基于矢量圖;
支持事件處理器喻鳄;
最適合帶有大型渲染區(qū)域的應(yīng)用程序(比如谷歌地圖)扼倘;
復(fù)雜度高會減慢渲染速度(任何過度使用 DOM 的應(yīng)用都不快);
不適合游戲應(yīng)用;
來看一個簡單的示例再菊,用SVG畫了一個圓:
<svg xmlns="http://www.w3.org/2000/svg"?version="1.1">
??<rect?x="50"?y="20"?rx="20"?ry="20"?width="150"?height="150"
??style="fill:red;stroke:black;stroke-width:5;opacity:0.5"/>
</svg>
SVG 代碼以?<svg>?元素開始爪喘,包括開啟標(biāo)簽<svg>?和關(guān)閉標(biāo)簽</svg>?。這是根元素纠拔。width 和 height 屬性可設(shè)置此 SVG 文檔的寬度和高度秉剑。version 屬性可定義所使用的 SVG 版本,xmlns 屬性可定義 SVG 命名空間稠诲。
SVG 的?<circle>?用來創(chuàng)建一個圓侦鹏。cx 和 cy 屬性定義圓中心的 x 和 y 坐標(biāo)。如果忽略這兩個屬性臀叙,那么圓點會被設(shè)置為 (0, 0)略水。r屬性定義圓的半徑。
下面主要是介紹SVG中的幾個用于動畫的元素劝萤,它們分別是:
<animate>:通常放置到一個SVG圖像元素里面渊涝,用來定義這個圖像元素的某個屬性的動畫變化過程;?
<animateMotion>:元素也是放置一個圖像元素里面床嫌,它可以引用一個事先定義好的動畫路徑跨释,讓圖像元素按路徑定義的方式運動;
?<animateTransform>:元素對圖形的運動和變換有更多的控制既鞠,它可以指定圖形的變換煤傍、縮放、旋轉(zhuǎn)和扭曲等嘱蛋;
?<mpath>:元素的用法在上面的例子里出現(xiàn)過蚯姆,它是一個輔助元素,通過它洒敏,<animateMotion>等元素可以引用一個外部的定義的<path>龄恋。讓圖像元素按這個<path>軌跡運動;
DEMO傳送門:https://jsfiddle.net/gaogy/ac4avoqk/
WebGL
WebGL使得網(wǎng)頁在支持HTML?<canvas>
標(biāo)簽的瀏覽器中凶伙,不需要安裝任何插件郭毕,便可以使用基于 OpenGL ES 2.0 的 API 在 canvas 中進(jìn)行3D渲染。 WebGL 程序由JavaScript的控制代碼函荣,和在計算機(jī)的圖形處理單元(GPU)中執(zhí)行的特效代碼(shader code显押,渲染代碼) 組成。
WebGL.png WebGL 本質(zhì)上是基于光柵化的 API傻挂,而不是基于 3D 的 API乘碑。WebGL 只關(guān)注兩個方面,即投影矩陣的坐標(biāo)和投影矩陣的顏色金拒。使用 WebGL 程序的任務(wù)就是實現(xiàn)具有投影矩陣坐標(biāo)和顏色的 WebGL 對象即可兽肤。可以使用“著色器”來完成上述任務(wù)。頂點著色器可以提供投影矩陣的坐標(biāo)资铡,片段著色器可以提供投影矩陣的顏色电禀。
由于WebGL的體系比較龐大,三言兩語說不完笤休,所以以下僅提供各種傳送門了:
WebGL 參考資料:https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL
WebGL API:https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API
感興趣的小伙伴尖飞,可以關(guān)注公眾號【grain先森】,回復(fù)關(guān)鍵詞 “小程序”宛官,獲取更多資料葫松,更多關(guān)鍵詞玩法期待你的探索~