国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 語(yǔ)言 > JavaScript > 正文

深入探究使JavaScript動(dòng)畫(huà)流暢的一些方法

2024-05-06 16:22:30
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

這篇文章主要介紹了使JavaScript動(dòng)畫(huà)流暢的一些方法,包括與CSS動(dòng)畫(huà)效果的一些對(duì)比,需要的朋友可以參考下

基于Javascript的動(dòng)畫(huà)暗中同CSS過(guò)渡效果一樣,甚至更加快,這怎么可能呢?而Adobe和Google持續(xù)發(fā)布的富媒體移動(dòng)網(wǎng)站的性能可媲美本地應(yīng)用,這又怎么可能呢?

本文逐一遍覽了基于Javascript的DOM動(dòng)畫(huà)庫(kù),如Velocity.js和GSAP,看其是如何比jQuery和CSS動(dòng)畫(huà)效果更具性能的.

jQuery

讓我們先從基礎(chǔ)的開(kāi)始: JavaScript 和 jQuery 被錯(cuò)誤的混為一談了. JavaScript 動(dòng)畫(huà)是很快的. jQuery 把它放慢了下來(lái)。為什么?因?yàn)?— 盡管jQuery非常強(qiáng)大 — 但成為一個(gè)性能強(qiáng)勁的動(dòng)畫(huà)引擎從來(lái)都不是jQuery的設(shè)計(jì)目標(biāo):

jQuery 不能避免 布局顛簸 ,這得歸因于它的代碼庫(kù)提供了動(dòng)畫(huà)之外的多種用途.

jQuery 的內(nèi)存消耗經(jīng)常會(huì)觸發(fā)垃圾回收,那樣會(huì) 時(shí)不時(shí)的讓動(dòng)畫(huà)定格下來(lái).

jQuery 使用 setInterval 而不是 requestAnimationFrame (RAF) 來(lái) 保護(hù)新技術(shù)不受其自身的影響.

應(yīng)該注意到布局顛簸就是在動(dòng)畫(huà)開(kāi)始部分的不順暢,垃圾回收就是造成動(dòng)畫(huà)期間不順暢的元兇, 而沒(méi)有使用RAF則會(huì)導(dǎo)致低幀率.

實(shí)現(xiàn)示例

避免造成布局顛簸的DOM查詢和更新組合:

 

 
  1. var currentTop, 
  2. currentLeft; 
  3.  
  4. /* With layout thrashing. */ 
  5. currentTop = element.style.top; /* QUERY */ 
  6. element.style.top = currentTop + 1; /* UPDATE */ 
  7.  
  8. currentLeft = element.style.left; /* QUERY */ 
  9. element.style.left = currentLeft + 1; /* UPDATE */ 
  10.  
  11. /* Without layout thrashing. */ 
  12. currentTop = element.style.top; /* QUERY */ 
  13. currentLeft = element.style.left; /* QUERY */ 
  14.  
  15. element.style.top = currentTop + 1; /* UPDATE */ 
  16. element.style.left = currentLeft + 1; /* UPDATE */ 

發(fā)生在更新之后的查詢會(huì)強(qiáng)制瀏覽器對(duì)頁(yè)面的計(jì)算式數(shù)據(jù)進(jìn)行重新計(jì)算 (同時(shí)會(huì)把新的更新效果考慮在內(nèi)). 這樣就會(huì)對(duì)動(dòng)畫(huà)產(chǎn)生顯著的開(kāi)銷,而這只是16毫秒微小間隔的運(yùn)行超時(shí).

類似的,實(shí)現(xiàn) RAF 并不必須是對(duì)你的現(xiàn)有代碼庫(kù)的顯著返工. 讓我們拿RAF的基礎(chǔ)實(shí)現(xiàn)同setInterval比較一下:

 

 
  1. var startingTop = 0; 
  2.  
  3. /* setInterval: Runs every 16ms to achieve 60fps (1000ms/60 ~= 16ms). */ 
  4. setInterval(function() { 
  5. /* Since this ticks 60 times a second, we divide the top property's increment of 1 unit per 1 second by 60. */ 
  6. element.style.top = (startingTop += 1/60); 
  7. }, 16); 
  8.  
  9. /* requestAnimationFrame: Attempts to run at 60fps based on whether the browser is in an optimal state. */ 
  10. function tick () { 
  11. element.style.top = (startingTop += 1/60); 
  12.  
  13. window.requestAnimationFrame(tick); 

RAF 產(chǎn)生了推動(dòng)動(dòng)畫(huà)性能的最大可能性,你可以對(duì)你的代碼進(jìn)行單一的變更.

CSS 轉(zhuǎn)換

CSS轉(zhuǎn)換通過(guò)把動(dòng)畫(huà)邏輯甩給瀏覽器本身去處理而超越了jQuery,這在以下幾方面是有效果的:(1)優(yōu)化DOM交互和內(nèi)存消耗以避免卡頓(顛簸),(2)利用引擎的RAF原則,(3)強(qiáng)制硬件加速(利用GPU的能力來(lái)提高動(dòng)畫(huà)性能)。

然而,現(xiàn)實(shí)是,這些優(yōu)化也可以在JavaScript中直接執(zhí)行。GSAP已經(jīng)這樣做了多年。Velocity.js,一個(gè)新的動(dòng)畫(huà)引擎,不僅利用了同樣的技術(shù),而且還向前多走了幾步——我們不久會(huì)探討這些。

面對(duì)事實(shí),JavaScript動(dòng)畫(huà)可以與CSS轉(zhuǎn)換競(jìng)爭(zhēng)只是我們康復(fù)計(jì)劃的第一步。第二步是實(shí)現(xiàn)“JavaScript動(dòng)畫(huà)實(shí)際上可以比CSS轉(zhuǎn)換更快”。

現(xiàn)在我們開(kāi)始談?wù)凜SS變換的弱點(diǎn):

transition強(qiáng)制硬件加速會(huì)加大GPU消耗,高負(fù)荷情形下將導(dǎo)致運(yùn)行不流暢。這種情況在移動(dòng)設(shè)備上尤為明顯。(特殊情況下,比如當(dāng)數(shù)據(jù)在瀏覽器主線程和排版線程之間傳遞產(chǎn)生的瓶頸也會(huì)導(dǎo)致不流暢)。某些CSS屬性,比如transform和opacity,則不受這些瓶頸影響。Adobe在這里精心總結(jié)了這些問(wèn)題。

transition在IE10以下沒(méi)有用,造成的自IE8和IE9以來(lái)的桌面站點(diǎn)可用性問(wèn)題至今仍然廣泛存在。

由于transition并不是由JavaScript原生控制(而僅僅是由JavaScript觸發(fā)),瀏覽器無(wú)法獲知如何與控制這些transition的JavaScript代碼同步地優(yōu)化他們。

相反的,基于JavaScript的動(dòng)畫(huà)庫(kù)則可以自行確定合適開(kāi)啟硬件。它們?cè)С指靼姹綢E瀏覽器,并且它們尤其適合批量動(dòng)畫(huà)優(yōu)化。

我的建議是僅當(dāng)你單獨(dú)為移動(dòng)端開(kāi)發(fā)且僅實(shí)現(xiàn)簡(jiǎn)單動(dòng)畫(huà)時(shí)使用原生CSS變換。這種環(huán)境下,transition是一種原生有效的解決方案,可以使你在樣式表中實(shí)現(xiàn)所有動(dòng)畫(huà)邏輯,而不用添加額外的JavaScript庫(kù),從而避免你的頁(yè)面變得臃腫。然而,當(dāng)你在設(shè)計(jì)復(fù)雜的UI,或者是開(kāi)發(fā)存在不同狀態(tài)的UI的App時(shí),你就應(yīng)該使用動(dòng)畫(huà)庫(kù)以使動(dòng)畫(huà)保持流暢,同時(shí)使工作流程易于管理。Transit是一個(gè)在管理CSS變換方面做得尤其優(yōu)秀的庫(kù)。

JavaScript 動(dòng)畫(huà)

好了,那JavaScript可就在性能方面占據(jù)上風(fēng)了. 但Javascript究竟具體快了多少呢? 好吧 — 最初 — 對(duì)于構(gòu)建一個(gè)實(shí)在的 3D動(dòng)畫(huà)示例 是足夠快的,通常在構(gòu)建中你只會(huì)看到有使用WebGL. 而構(gòu)建一個(gè) 多媒體小動(dòng)畫(huà) 也夠了,通常你看到只會(huì)使用Flash或者After Effects構(gòu)建. 而構(gòu)建一個(gè) 虛擬世界 也夠了,通常你只會(huì)看到使用canvas構(gòu)建.

為了對(duì)領(lǐng)先的動(dòng)畫(huà)庫(kù),當(dāng)然還要包含Transit(它使用CSS漸變效果),進(jìn)行直接的對(duì)比, 回頭去看看Velocity在VelocityJS.org上的文檔.

問(wèn)題仍然是: JavaScript是怎樣具體的達(dá)成其高水平性能的? 下面是對(duì)基于Javascript動(dòng)畫(huà)能夠被執(zhí)行這一目標(biāo)的優(yōu)化的一個(gè)簡(jiǎn)短清單:

同步 DOM → 在整個(gè)動(dòng)畫(huà)鏈中間入棧以最小化布局抖動(dòng).

為整個(gè)鏈?zhǔn)秸{(diào)用緩存屬性值,以最小化DOM查詢發(fā)生 (這些就是高性能DOM動(dòng)畫(huà)的坑).

在同樣的調(diào)用中緩存整個(gè)同級(jí)別元素的單元轉(zhuǎn)換率 (比如 px 到 %, em, 等等.).

當(dāng)更新可能會(huì)在視覺(jué)上不可見(jiàn)時(shí)跳過(guò)樣式更新.

回顧一下我們先前學(xué)過(guò)的關(guān)于布局顛簸的知識(shí),Velocity.js利用這些最佳實(shí)踐來(lái)緩存動(dòng)畫(huà)結(jié)束值以復(fù)用為隨后動(dòng)畫(huà)的開(kāi)始值,從而避免了重新查詢DOM以獲取元素的開(kāi)始值:

 

 
  1. $element 
  2. /* Slide the element down into view. */ 
  3. .velocity({ opacity: 1, top: "50%" }) 
  4. /* After a delay of 1000ms, slide the element out of view. */ 
  5. .velocity({ opacity: 0, top: "-50%" }, { delay: 1000 }); 

在上面例子中,第二個(gè) Velocity 調(diào)用知道它應(yīng)該自動(dòng)從 opacity為1 和 top為50% 開(kāi)始。

瀏覽器本身最終能夠執(zhí)行許多這些相同的優(yōu)化,但這樣做會(huì)明顯減少開(kāi)發(fā)者能夠制作的動(dòng)畫(huà)代碼的方式。因此,出于同樣原因,由于jQuery不使用RAF(如上所述),瀏覽器就不會(huì)強(qiáng)制優(yōu)化它,甚至給出一個(gè)很小的機(jī)會(huì)去打破規(guī)格或偏離預(yù)期的行為。

最后,我們對(duì)這兩個(gè)JavaScript動(dòng)畫(huà)庫(kù)(Velocity.js 和 GSAP)互相比較一下。

GSAP 是首個(gè)動(dòng)畫(huà)庫(kù),用在演示JavaScript DOM 令人印象深刻的動(dòng)畫(huà)表現(xiàn)。它確實(shí)是這樣,但有些缺點(diǎn):

在中到高負(fù)荷動(dòng)畫(huà)中,GSAP 的 DOM 交互開(kāi)銷導(dǎo)致動(dòng)畫(huà)在開(kāi)始時(shí)和過(guò)程中失幀。

相反于Velocity.js 是在超寬松的 MIT 許可下發(fā)布的, GSAP 是閉源的, 并且在很多類商用時(shí)候需要許可年費(fèi)。

因?yàn)?GSAP 是一個(gè)完整的動(dòng)畫(huà)套件,是 Velocity 大小的三倍。然而,GSAP 有如此豐富功能,有助于其成為動(dòng)畫(huà)的瑞士軍刀。

我推薦做法是在你需要精確控制定時(shí)(比如 重繪,暫停/恢復(fù))和運(yùn)動(dòng)(比如貝塞爾曲線路徑)的時(shí)候用 GSAP 。這些特性在游戲開(kāi)發(fā)和某些特殊應(yīng)用中是至關(guān)重要的,但是通常不需要用在網(wǎng)頁(yè)應(yīng)用的 UI中。

Velocity.js

引用 GSAP 豐富的特性并不代表Velocity自身在特性上是輕量級(jí)的. 相反,在壓縮后僅有的7kb中,Velocity不僅僅復(fù)制了jQuery $.animate()的所有功能, 它還把顏色動(dòng)畫(huà),轉(zhuǎn)換,循環(huán),easing效果,類動(dòng)畫(huà)還有滾動(dòng)都打包了進(jìn)去.

總之,Velocity是jQuery,jQuery UI,以及CSS漸變效果的最佳組合.

此外,從便利的角度看,Velocity在hood(蓋子,大概意思是公共的接口)之下使用jQuery的 $.queue() 方法, 如此就可以實(shí)現(xiàn)同 jQuery 的 $.animate(), $.fade(), 和 $.delay() 函數(shù)的無(wú)縫互操作. 而且,由于Velocity的語(yǔ)法同 $.animate() 的語(yǔ)法是相同的, 你不需要改變頁(yè)面的任何代碼.

讓我們快速地來(lái)看一看 Velocity.js. 在基礎(chǔ)的層面,Velocity的行為同$.animate()一樣:

 

 
  1. $element 
  2. .delay(1000) 
  3. /* Use Velocity to animate the element's top property over a duration of 2000ms. */ 
  4. .velocity({ top: "50%" }, 2000) 
  5. /* Use a standard jQuery method to fade the element out once Velocity is done animating top. */ 
  6. .fadeOut(1000); 

在其最高級(jí)的層面,可以創(chuàng)建帶有3D動(dòng)畫(huà)的復(fù)雜滾動(dòng)場(chǎng)景 — 幾乎只要用到兩行簡(jiǎn)單的代碼:

 

 
  1. $element 
  2. /* Scroll the browser to the top of this element over a duration of 1000ms. */ 
  3. .velocity("scroll", 1000) 
  4. /* Then rotate the element around its Y axis by 360 degrees. */ 
  5. .velocity({ rotateY: "360deg" }, 1000); 

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 甘孜| 富川| 上思县| 灵台县| 高淳县| 鄄城县| 涡阳县| 萝北县| 泾阳县| 封丘县| 万源市| 五原县| 荣成市| 郴州市| 色达县| 措勤县| 宜兰县| 兰州市| 湖北省| 日喀则市| 旺苍县| 眉山市| 碌曲县| 贵溪市| 民勤县| 扬中市| 东山县| 尚义县| 敦煌市| 鹿泉市| 浦东新区| 乐昌市| 保亭| 沁阳市| 巴林右旗| 夏河县| 陇西县| 灵石县| 闸北区| 新郑市| 察隅县|