這兩天開始看《Javascript網(wǎng)頁(yè)動(dòng)畫設(shè)計(jì)》,這里總結(jié)一下僵控。這個(gè)庫(kù)我之前用過香到,很方便也很流暢。但是里面除了第四章介紹了動(dòng)畫工作流和第七章介紹了動(dòng)畫性能外报破,都是介紹 Velocity
這個(gè)庫(kù)的悠就,或許叫『Velocity動(dòng)畫設(shè)計(jì)』更為妥當(dāng)。
這里姑且記錄一下充易,過一陣開始總結(jié)『web動(dòng)畫』這個(gè)主題梗脾。
第一章 JavaScript動(dòng)畫與CSS動(dòng)畫
JS動(dòng)畫性能不是問題
- CSS 適合懸停狀態(tài)的動(dòng)畫
- JS動(dòng)畫和CSS動(dòng)畫一樣快
- 不要將JS與jQuery混為一談
- Velocity.js
JS動(dòng)畫獨(dú)有的功能
- 頁(yè)面滾動(dòng):頁(yè)面滾動(dòng)到某個(gè)元素上
- 動(dòng)畫反轉(zhuǎn):元素以動(dòng)畫形式變動(dòng)回上一個(gè)動(dòng)畫開始之前的值
- 物理動(dòng)效:摩擦力
第二章 使用Velocity.js實(shí)現(xiàn)動(dòng)畫
動(dòng)畫的種類:
- CSS動(dòng)畫:
transition
/animation
- JS動(dòng)畫:GSAP、Velocity.js
- canvas動(dòng)畫:Fabric.js
- SVG動(dòng)畫:Snap.js 盹靴、SVG.js
- WebGL動(dòng)畫:Three.js
詳情可以看這里
第三章 動(dòng)效設(shè)計(jì)理論
這一章全是在講理論的東西炸茧,難道買錯(cuò)書了?
第四章 動(dòng)畫工作流
CSS動(dòng)畫工作流
為了更好地管理UI動(dòng)畫工作流稿静,開發(fā)人員有時(shí)會(huì)放棄JS而使用CSS梭冠。但是,一旦動(dòng)畫的復(fù)雜度達(dá)到了中等或更高水平改备,那么使用CSS動(dòng)畫通常會(huì)使工作流變得明顯比用JS更加糟糕控漠。
CSS的問題
CSS利用關(guān)鍵幀來(lái)實(shí)現(xiàn)復(fù)雜動(dòng)畫序列:
@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 動(dòng)畫時(shí)長(zhǎng)增加1秒,其他屬性動(dòng)畫時(shí)長(zhǎng)不變悬钳,就必須要重新計(jì)算盐捷,才能使百分比各處的屬性值與增加1秒后的時(shí)長(zhǎng)匹配起來(lái)。
什么時(shí)候用CSS
當(dāng)用戶鼠標(biāo)懸停在元素上時(shí)觸發(fā)的簡(jiǎn)單樣式變化默勾,使用 transition
代碼技巧:將樣式與邏輯分離
一般做法
在jQuery中碉渡,主要由兩種動(dòng)畫方式:
- 利用
addClass()
和removeClass()
切換樣式 - 使用
animate()
:$ele.animate({opacity:1,top:50},1000)
第一種方法更值得推薦,因?yàn)樗拇a組織得清楚母剥,改樣式就改CSS滞诺,改邏輯就改JS。
優(yōu)化做法
定義一個(gè)JS對(duì)象媳搪,該對(duì)象的內(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
有一個(gè)獨(dú)有的能力——定義動(dòng)畫選項(xiàng)秦爆。
代碼技巧:組織排序動(dòng)畫
Velocity 有一個(gè)名為 UI pack 的插件,能夠優(yōu)化UI動(dòng)畫工作流憔披。
$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")
第五章 文本動(dòng)畫
網(wǎng)頁(yè)上很少使用文本動(dòng)畫等限,這里介紹幾種工具幫你免于文本動(dòng)畫枯燥乏味的一面爸吮,提供高效的工作流。
Blast 能夠?qū)㈨?yè)面上的文本進(jìn)行拆分
結(jié)合 velocity.js
和 velocity-ui
第六章 SVG入門
Snap.svg
SVG 動(dòng)畫望门,在原本應(yīng)該使用圖片的位置使用它:
- 具有復(fù)雜動(dòng)畫序列的按鈕形娇,用戶懸停鼠標(biāo)或點(diǎn)擊鼠標(biāo)時(shí)會(huì)觸發(fā)這些動(dòng)畫序列
- 獨(dú)特的加載狀態(tài)圖形,可以用來(lái)替代老掉牙的gif圖
- 公司logo筹误,頁(yè)面加載時(shí)桐早,logo的各個(gè)部分可以一起以動(dòng)畫形式呈現(xiàn)
第七章 動(dòng)畫性能
布局顛簸
設(shè)置(set)、查詢(get)一個(gè)元素的CSS屬性是引發(fā)性能開銷的兩個(gè)核心瀏覽器進(jìn)程(另外還有圖形渲染)厨剪。
在為元素設(shè)置新屬性后哄酝,瀏覽器必須計(jì)算你這次更改所產(chǎn)生的后續(xù)影響。例如祷膳,改變一個(gè)元素的寬度會(huì)導(dǎo)致一系列連鎖反應(yīng)陶衅;它的父級(jí)元素、兄弟元素和子元素的寬度根據(jù)自己的CSS屬性也要調(diào)整直晨。
由設(shè)置和獲取樣式的交替而導(dǎo)致的UI性能降低稱為布局顛簸搀军。
瀏覽器已經(jīng)為頁(yè)面布局的重新計(jì)算進(jìn)行了高度優(yōu)化,但由于布局顛簸勇皇,優(yōu)化效果大打折扣罩句。
例如,瀏覽器已經(jīng)可以將同一時(shí)間的獲取操作優(yōu)化成一個(gè)單一敛摘、流暢的操作的止,因?yàn)闉g覽器在第一次獲取之后可以緩存頁(yè)面的狀態(tài),然后在后續(xù)每次獲取操作時(shí)着撩,參考那個(gè)狀態(tài)诅福。但是,如果反復(fù)執(zhí)行獲取后又設(shè)置拖叙,就讓瀏覽器去做了很多繁重的工作氓润,因?yàn)樵O(shè)置所做的更改會(huì)不斷地使其緩存失效。
布局顛簸在動(dòng)畫循環(huán)中出現(xiàn)的話薯鳍,對(duì)性能更是雪上加霜咖气,最后就是讓動(dòng)畫變得卡頓。
解決辦法
把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
比如斩松,點(diǎn)擊按鈕切換 none
和 block
伶唯,可能會(huì)先要檢查側(cè)邊菜單的display
屬性是設(shè)置成 none
還是 block
,然后再相應(yīng)地進(jìn)行值得替換惧盹。檢查是一次『獲取』乳幸,之后無(wú)論設(shè)置成什么是一次『設(shè)置』瞪讼。
想要優(yōu)化的話,可以在設(shè)置一個(gè)變量粹断,每當(dāng)按鈕點(diǎn)擊的時(shí)候符欠,這個(gè)變量跟著更新,然后在切換可見性之前瓶埋,查詢這個(gè)變量就可以得知菜單的當(dāng)前狀態(tài)了希柿。『獲取』的過程就可以省掉了养筒。
避免影響臨近的元素
有很多CSS屬性狡汉,一經(jīng)改變,就會(huì)造成臨近元素尺寸或位置的調(diào)整闽颇,其中包括 top盾戴、right、bottom兵多、left尖啡,margin、padding剩膘,border衅斩,以及width、height
解決辦法
盡可能設(shè)置CSS的transform屬性(translate怠褐、scale畏梆、rotate)的動(dòng)畫。transform屬性的特殊之處在于它們將目標(biāo)元素提升至一個(gè)單獨(dú)的層奈懒,這個(gè)層可以獨(dú)立于頁(yè)面其他內(nèi)容單獨(dú)渲染(通過GPU加速提升性能)奠涌,因此相鄰的元素不會(huì)受到影響。
優(yōu)先考慮 opacity勝于 color
opacity是另一個(gè)可以讓GPU渲染加速的CSS屬性磷杏,因?yàn)樗挥绊懺氐奈恢谩?/p>
比如溜畅,當(dāng)用戶鼠標(biāo)懸停在元素上時(shí)color屬性會(huì)改變,那么請(qǐng)考慮使用opacity動(dòng)畫來(lái)替代极祸。如果最終效果和設(shè)置顏色的動(dòng)畫效果差不多慈格,那么留用設(shè)置opacity動(dòng)畫吧。
請(qǐng)查看 CSSTrigger.com 上的內(nèi)容遥金,了解每個(gè)CSS屬性如何影響瀏覽器性能浴捆。
不用持續(xù)響應(yīng)scroll和resize事件
瀏覽器的scroll和resize是兩個(gè)觸發(fā)頻率非常頻繁的事件類型:每當(dāng)用戶調(diào)整或滾動(dòng)瀏覽器窗口時(shí),瀏覽器都會(huì)在每秒內(nèi)觸發(fā)多次與這些事件相關(guān)的回調(diào)函數(shù)稿械。窗口scroll或resize的時(shí)候會(huì)多次觸發(fā)事件选泻,如果其中有布局顛簸,那么會(huì)給瀏覽器帶來(lái)巨大負(fù)擔(dān)溜哮。
解決辦法
定義一個(gè)時(shí)間間隔滔金,在此事件間隔期間色解,事件回調(diào)僅會(huì)被調(diào)用一次茂嗓。這就是所謂的『反跳』餐茵。
例如定義了一個(gè)250毫秒的反跳間隔,而用戶滾動(dòng)頁(yè)面時(shí)間為1000毫秒述吸,這時(shí)候忿族,事件回調(diào)僅僅會(huì)觸發(fā)四次。
undersocre的
debounce
函數(shù)就是這個(gè)作用-
flexible中是用的定時(shí)器:
win.addEventListener('resize', function() { clearTimeout(tid); tid = setTimeout(refreshRem, 300); }, false);
減少圖片渲染
圖片的形式:
- img
- gradient
- box-shadow / text-shadow
視頻蝌矛、圖片是多媒體元素類型道批,瀏覽器必須要加倍渲染才行。多媒體元素中包含上千萬(wàn)的像素?cái)?shù)據(jù)入撒,要改變它們的大小隆豹、尺寸或重新合成對(duì)瀏覽器計(jì)算開銷很大。
另外茅逮,滾動(dòng)頁(yè)面幾乎可以視為設(shè)置整個(gè)頁(yè)面的動(dòng)畫(可以把滾動(dòng)頁(yè)面視為設(shè)置頁(yè)面的top屬性的動(dòng)畫)璃赡,在移動(dòng)設(shè)備中,多媒體元素會(huì)造成滾動(dòng)性能的巨幅下降献雅。
解決辦法
盡可能少地加載圖片