這兩天開始看《Javascript網(wǎng)頁動畫設(shè)計》,這里總結(jié)一下。這個庫我之前用過,很方便也很流暢。但是里面除了第四章介紹了動畫工作流和第七章介紹了動畫性能外,都是介紹 Velocity
這個庫的,或許叫『Velocity動畫設(shè)計』更為妥當(dāng)。
這里姑且記錄一下,過一陣開始總結(jié)『web動畫』這個主題。
第一章 JavaScript動畫與CSS動畫
JS動畫性能不是問題
- CSS 適合懸停狀態(tài)的動畫
- JS動畫和CSS動畫一樣快
- 不要將JS與jQuery混為一談
- Velocity.js
JS動畫獨有的功能
- 頁面滾動:頁面滾動到某個元素上
- 動畫反轉(zhuǎn):元素以動畫形式變動回上一個動畫開始之前的值
- 物理動效:摩擦力
第二章 使用Velocity.js實現(xiàn)動畫
動畫的種類:
- CSS動畫:
transition
/animation
- JS動畫:GSAP、Velocity.js
- canvas動畫:Fabric.js
- SVG動畫:Snap.js 、SVG.js
- WebGL動畫:Three.js
詳情可以看這里
第三章 動效設(shè)計理論
這一章全是在講理論的東西,難道買錯書了?
第四章 動畫工作流
CSS動畫工作流
為了更好地管理UI動畫工作流,開發(fā)人員有時會放棄JS而使用CSS。但是,一旦動畫的復(fù)雜度達到了中等或更高水平,那么使用CSS動畫通常會使工作流變得明顯比用JS更加糟糕。
CSS的問題
CSS利用關(guān)鍵幀來實現(xiàn)復(fù)雜動畫序列:
@keyframes myAnimation{
0%{opacity:0;transform:scale(0,0)}
25%{opacity:1;transform:scale(1,1)}
50%{transform:translate(100px,0)}
100%{transform:translate(100px,100px)}
}
#box{animation:myAnimation 2.75s}
如果要把 opacity 動畫時長增加1秒,其他屬性動畫時長不變,就必須要重新計算,才能使百分比各處的屬性值與增加1秒后的時長匹配起來。
什么時候用CSS
當(dāng)用戶鼠標懸停在元素上時觸發(fā)的簡單樣式變化,使用 transition
代碼技巧:將樣式與邏輯分離
一般做法
在jQuery中,主要由兩種動畫方式:
- 利用
addClass()
和removeClass()
切換樣式 - 使用
animate()
:$ele.animate({opacity:1,top:50},1000)
第一種方法更值得推薦,因為它的代碼組織得清楚,改樣式就改CSS,改邏輯就改JS。
優(yōu)化做法
定義一個JS對象,該對象的內(nèi)容是要設(shè)置的CSS屬性。然后將其傳入Velocity或jQuery中。
//style.js
var fadeIn = {
p: {
opacity: 1,
top: "50px"
},
o: {
duration: 1000,
easing: "linear"
}
}
//main.js
$element.velocity(fadeIn.p,fadeIn.o);
這樣使用 style.js
有一個獨有的能力——定義動畫選項。
代碼技巧:組織排序動畫
Velocity 有一個名為 UI pack 的插件,能夠優(yōu)化UI動畫工作流。
$element
.velocity({translateX:100})
.velocity({translateY;100})
代碼技巧:打包效果
$.Velocity.RegisterEffect("growIn",{
defaultDuration: duration,
calls: [
[ {opacity:1,scale:1},0.4 ],
[ {boxShadowBlur:50},0.6 ]
]
})
$element.velocity("growIn")
第五章 文本動畫
網(wǎng)頁上很少使用文本動畫,這里介紹幾種工具幫你免于文本動畫枯燥乏味的一面,提供高效的工作流。
Blast 能夠?qū)㈨撁嫔系奈谋具M行拆分
結(jié)合 velocity.js
和 velocity-ui
第六章 SVG入門
Snap.svg
SVG 動畫,在原本應(yīng)該使用圖片的位置使用它:
- 具有復(fù)雜動畫序列的按鈕,用戶懸停鼠標或點擊鼠標時會觸發(fā)這些動畫序列
- 獨特的加載狀態(tài)圖形,可以用來替代老掉牙的gif圖
- 公司logo,頁面加載時,logo的各個部分可以一起以動畫形式呈現(xiàn)
第七章 動畫性能
布局顛簸
設(shè)置(set)、查詢(get)一個元素的CSS屬性是引發(fā)性能開銷的兩個核心瀏覽器進程(另外還有圖形渲染)。
在為元素設(shè)置新屬性后,瀏覽器必須計算你這次更改所產(chǎn)生的后續(xù)影響。例如,改變一個元素的寬度會導(dǎo)致一系列連鎖反應(yīng);它的父級元素、兄弟元素和子元素的寬度根據(jù)自己的CSS屬性也要調(diào)整。
由設(shè)置和獲取樣式的交替而導(dǎo)致的UI性能降低稱為布局顛簸。
瀏覽器已經(jīng)為頁面布局的重新計算進行了高度優(yōu)化,但由于布局顛簸,優(yōu)化效果大打折扣。
例如,瀏覽器已經(jīng)可以將同一時間的獲取操作優(yōu)化成一個單一、流暢的操作,因為瀏覽器在第一次獲取之后可以緩存頁面的狀態(tài),然后在后續(xù)每次獲取操作時,參考那個狀態(tài)。但是,如果反復(fù)執(zhí)行獲取后又設(shè)置,就讓瀏覽器去做了很多繁重的工作,因為設(shè)置所做的更改會不斷地使其緩存失效。
布局顛簸在動畫循環(huán)中出現(xiàn)的話,對性能更是雪上加霜,最后就是讓動畫變得卡頓。
解決辦法
把DOM的設(shè)置和獲取的操作分別集合在一起批量操作
//糟糕的做法
var currentTop = $('element').css('top'); //get
$('element').style.top = currentTop + 1; //set
var currentLeft = $('element').css('left'); //get
$('element').style.left = currentLeft + 1; //set
如果把查詢放在一起,把設(shè)置放在一起,那么瀏覽器就可以打包相應(yīng)操作,減少代碼造成的布局顛簸的影響:
var currentTop = $('element').css('top'); //get
var currentLeft = $('element').css('left'); //get
$('element').style.top = currentTop + 1; //set
$('element').style.left = currentLeft + 1; //set
比如,點擊按鈕切換 none
和 block
,可能會先要檢查側(cè)邊菜單的display
屬性是設(shè)置成 none
還是 block
,然后再相應(yīng)地進行值得替換。檢查是一次『獲取』,之后無論設(shè)置成什么是一次『設(shè)置』。
想要優(yōu)化的話,可以在設(shè)置一個變量,每當(dāng)按鈕點擊的時候,這個變量跟著更新,然后在切換可見性之前,查詢這個變量就可以得知菜單的當(dāng)前狀態(tài)了。『獲取』的過程就可以省掉了。
避免影響臨近的元素
有很多CSS屬性,一經(jīng)改變,就會造成臨近元素尺寸或位置的調(diào)整,其中包括 top、right、bottom、left,margin、padding,border,以及width、height
解決辦法
盡可能設(shè)置CSS的transform屬性(translate、scale、rotate)的動畫。transform屬性的特殊之處在于它們將目標元素提升至一個單獨的層,這個層可以獨立于頁面其他內(nèi)容單獨渲染(通過GPU加速提升性能),因此相鄰的元素不會受到影響。
優(yōu)先考慮 opacity勝于 color
opacity是另一個可以讓GPU渲染加速的CSS屬性,因為它不影響元素的位置。
比如,當(dāng)用戶鼠標懸停在元素上時color屬性會改變,那么請考慮使用opacity動畫來替代。如果最終效果和設(shè)置顏色的動畫效果差不多,那么留用設(shè)置opacity動畫吧。
請查看 CSSTrigger.com 上的內(nèi)容,了解每個CSS屬性如何影響瀏覽器性能。
不用持續(xù)響應(yīng)scroll和resize事件
瀏覽器的scroll和resize是兩個觸發(fā)頻率非常頻繁的事件類型:每當(dāng)用戶調(diào)整或滾動瀏覽器窗口時,瀏覽器都會在每秒內(nèi)觸發(fā)多次與這些事件相關(guān)的回調(diào)函數(shù)。窗口scroll或resize的時候會多次觸發(fā)事件,如果其中有布局顛簸,那么會給瀏覽器帶來巨大負擔(dān)。
解決辦法
定義一個時間間隔,在此事件間隔期間,事件回調(diào)僅會被調(diào)用一次。這就是所謂的『反跳』。
例如定義了一個250毫秒的反跳間隔,而用戶滾動頁面時間為1000毫秒,這時候,事件回調(diào)僅僅會觸發(fā)四次。
undersocre的
debounce
函數(shù)就是這個作用-
flexible中是用的定時器:
win.addEventListener('resize', function() { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false);
減少圖片渲染
圖片的形式:
- img
- gradient
- box-shadow / text-shadow
視頻、圖片是多媒體元素類型,瀏覽器必須要加倍渲染才行。多媒體元素中包含上千萬的像素數(shù)據(jù),要改變它們的大小、尺寸或重新合成對瀏覽器計算開銷很大。
另外,滾動頁面幾乎可以視為設(shè)置整個頁面的動畫(可以把滾動頁面視為設(shè)置頁面的top屬性的動畫),在移動設(shè)備中,多媒體元素會造成滾動性能的巨幅下降。
解決辦法
盡可能少地加載圖片