《JavaScript網(wǎng)頁動畫設(shè)計》讀書筆記

這兩天開始看《Javascript網(wǎng)頁動畫設(shè)計》,這里總結(jié)一下。這個庫我之前用過,很方便也很流暢。但是里面除了第四章介紹了動畫工作流和第七章介紹了動畫性能外,都是介紹 Velocity 這個庫的,或許叫『Velocity動畫設(shè)計』更為妥當(dāng)。

這里姑且記錄一下,過一陣開始總結(jié)『web動畫』這個主題。

JavaScript網(wǎng)頁動畫設(shè)計.jpg

第一章 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.js

Blast 能夠?qū)㈨撁嫔系奈谋具M行拆分

結(jié)合 velocity.jsvelocity-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

比如,點擊按鈕切換 noneblock,可能會先要檢查側(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);
    

減少圖片渲染

圖片的形式:

  1. img
  2. gradient
  3. box-shadow / text-shadow

視頻、圖片是多媒體元素類型,瀏覽器必須要加倍渲染才行。多媒體元素中包含上千萬的像素數(shù)據(jù),要改變它們的大小、尺寸或重新合成對瀏覽器計算開銷很大。

另外,滾動頁面幾乎可以視為設(shè)置整個頁面的動畫(可以把滾動頁面視為設(shè)置頁面的top屬性的動畫),在移動設(shè)備中,多媒體元素會造成滾動性能的巨幅下降。


解決辦法

盡可能少地加載圖片

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽?zāi)J的外補...
    _Yfling閱讀 13,796評論 1 92
  • 選擇qi:是表達式 標簽選擇器 類選擇器 屬性選擇器 繼承屬性: color,font,text-align,li...
    love2013閱讀 2,333評論 0 11
  • 選擇qi:是表達式 標簽選擇器 類選擇器 屬性選擇器 繼承屬性: color,font,text-align,li...
    wzhiq896閱讀 1,799評論 0 2
  • 讀《年輕人,你憑什么不加班》 第一次接觸自媒體是去年來自同事的啟蒙,說來慚愧,作為一名90后,與時俱進的思維真的有...
    楊梓珊閱讀 236評論 0 1
  • 從小就不是一個好學(xué)生,學(xué)霸貓半個多月前出的作業(yè),今天才完成吧,哈哈!! 學(xué)霸貓有一天在群里問到:失敗,真正的價值是...
    李智閱讀 876評論 2 10