自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

攜程火車票七個(gè)優(yōu)化動(dòng)畫性能的方法

人工智能 新聞
我們借助性能檢測工具定位問題,并查閱源碼、文檔等資源解決問題,形成了這篇文章。

作者簡介

Kay Huang,攜程高級視覺設(shè)計(jì)師,專注于前端樣式與動(dòng)畫領(lǐng)域。

一 、背景

攜程火車票營銷頁使用 css 制作動(dòng)畫很多年了,這大大提高了動(dòng)畫給予頁面豐富的視覺體驗(yàn)。不過,在開發(fā)的過程中,也遇到了一些性能相關(guān)問題和用戶反饋,比如頭部動(dòng)畫卡頓、頁面打開時(shí)間較長、頁面打開后部分?jǐn)?shù)據(jù)加載時(shí)間較長等問題。為解決這些問題,我們借助性能檢測工具定位問題,并查閱源碼、文檔等資源解決問題,形成了這篇文章。

二、渲染優(yōu)化

要優(yōu)化動(dòng)畫性能,首先要了解瀏覽器是如何進(jìn)行元素渲染的,瀏覽器的渲染流程有以下四步:

a. 計(jì)算元素的樣式(可能通過腳本重新計(jì)算);

b. 生成每個(gè)元素的幾何形狀和位置(布局);

c. 繪制圖層的每個(gè)像素(初始化繪圖并且進(jìn)行繪圖);

圖片

d. 將圖層繪制到屏幕上(合并渲染層)。

對于 CSS3 動(dòng)畫來說,每一幀都要經(jīng)歷上述過程。關(guān)于最后一步合并渲染層(可以類比 Photoshop 的圖層),瀏覽器會(huì)在特定的場合創(chuàng)建獨(dú)立的渲染層,每個(gè)渲染層由 GPU 獨(dú)立繪制,互不影響,最后瀏覽器再把各個(gè)渲染層合并。這是一種代價(jià)較低的操作。

理論上說,F(xiàn)PS 越高,動(dòng)畫會(huì)越流暢,目前大多數(shù)設(shè)備的屏幕刷新率為 60 次/秒,所以通常來講 FPS 為 60frame/s 時(shí)動(dòng)畫效果最好,也就是每幀的消耗時(shí)間(幀預(yù)算)為 16.67ms。

三、解決方案

如上所說瀏覽器有整理工作要做,因此所有工作需要盡量在 10 ms 內(nèi)完成。如果制作的動(dòng)畫觸發(fā)了布局,那就相當(dāng)于要進(jìn)行第二步重新繪制,如果重新繪制的話瀏覽器渲染的時(shí)間肯定超過 16ms,那么我們的頁面就會(huì)出現(xiàn)卡頓,如果是移動(dòng)端的話那就會(huì)更慢,所以我們?nèi)绻獌?yōu)化的話那就要從第一步直接跳到第四步。

圖片

下面我寫了七種優(yōu)化動(dòng)畫性能的方法,有直接從第一步跳到第四步的也有一些其他平時(shí)優(yōu)化注意事項(xiàng)。

3.1 開啟 GPU 加速

Transform 屬性可以向元素應(yīng)用 2D 或者 3D 轉(zhuǎn)換,可以對元素進(jìn)行選擇、縮放、移動(dòng)和傾斜。

在日常中我們可以使用 left/top,translate 來實(shí)現(xiàn)元素的位移,但是其實(shí)性能上還是有一定區(qū)別的因?yàn)?transform 屬性不會(huì)改變自己和他周圍元素的布局,他會(huì)對元素的整體產(chǎn)生影響。

讓我們先用 top/left 屬性創(chuàng)建一個(gè)動(dòng)畫看看效果。

<style>
      .heart{animation: heartbeat 4s infinite;width:50px;height:50px;background:red;position:absolute;left:30px;top:30px;}
      @keyframes heartbeat{
          0%{top:30px;left:30px;}
          25%{top:30px;left:230px;}
          50%{top:230px;left:230px;}
          75%{top:230px;left:30px;}
      }
</style>

用 chrome 瀏覽器的 DevTools 查看可以看到紅色方塊都是布局重繪。

圖中有那么多的紅色方框與幀數(shù)是因?yàn)闉g覽器會(huì)做大量的計(jì)算,動(dòng)畫就會(huì)卡頓。

因?yàn)槊恳粠淖兓癁g覽器都在進(jìn)行布局、繪制、把新的位圖交給 GPU 內(nèi)存,雖然只改變元素位置但是很可能要同步改變他的子元素的位置,那瀏覽器就要重新計(jì)算布局,計(jì)算完后主線程再來重新生成該元素的位圖。

圖片

現(xiàn)在,將動(dòng)畫用 transform 代替:

<style>
      .heart{animation: heartbeat 1s;width:50px;height:50px;background:red;}
      @keyframes heartbeat{
          0%{transform: translate(30px,30px);}
     25%{transform: translate(30px,230px);}
       50%{transform: translate(230px,230px);}
          75%{transform: translate(230px,30px);}
      }
</style>

再次分析,可以看到,沒有發(fā)生紅色的重繪方塊且只有一條幀數(shù),就知道動(dòng)畫肯定會(huì)流暢絲滑。

因?yàn)?transform 屬性不會(huì)改變自己和他周圍元素的布局,他會(huì)對元素的整體產(chǎn)生影響。

圖片

我們通過節(jié)點(diǎn)的 transform 可以修改節(jié)點(diǎn)的位置、旋轉(zhuǎn)、大小等。我們平常會(huì)使用 left 和 top 屬性來修改節(jié)點(diǎn)的位置,但正如上面所述,left 和 top 會(huì)觸發(fā)重布局,修改時(shí)的代價(jià)相當(dāng)大。取而代之的更好方法是使用 translate,這個(gè)不會(huì)觸發(fā)重布局。

3.2 避免使用影響性能的 CSS 屬性

這些屬性會(huì)影響性能,因?yàn)樗鼈冃枰M(jìn)行復(fù)雜的計(jì)算和渲染,尤其是在動(dòng)畫中使用時(shí)。這些屬性可能會(huì)導(dǎo)致瀏覽器進(jìn)行重排和重繪,從而影響頁面的性能和流暢度。

如果您必須使用這些屬性,請盡可能減少它們的使用。例如,您可以嘗試使用 CSS3 的 transform 屬性來實(shí)現(xiàn) box-shadow 和 border-radius 的效果,因?yàn)樗鼈兛梢愿玫乩脼g覽器的硬件加速。

例如,下面是一個(gè)使用 box-shadow 屬性的示例:

.box {
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

這個(gè) box-shadow 屬性會(huì)在元素周圍添加一個(gè)陰影效果,但是它會(huì)影響性能,因?yàn)闉g覽器需要進(jìn)行復(fù)雜的計(jì)算和渲染。為了優(yōu)化性能,我們可以使用 CSS3 的 transform 屬性來實(shí)現(xiàn)相同的效果:

.box {  transform: translateZ(0);  box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);}

這個(gè) transform 屬性會(huì)啟用硬件加速,從而提高性能。同時(shí),我們?nèi)匀豢梢允褂?box-shadow 屬性來添加陰影效果。

3.3 避免使用復(fù)雜的選擇器

選擇器和動(dòng)畫之間存在一定的關(guān)系。在 CSS 動(dòng)畫中,選擇器的復(fù)雜度越高,樣式計(jì)算的時(shí)間就越長。在動(dòng)畫中使用復(fù)雜的選擇器會(huì)導(dǎo)致瀏覽器需要更長的時(shí)間來計(jì)算樣式,從而影響動(dòng)畫的性能和流暢度。

例如,當(dāng)我們使用復(fù)雜的選擇器來選擇元素,并為它們添加動(dòng)畫效果時(shí),瀏覽器需要花費(fèi)更長的時(shí)間來計(jì)算樣式,從而影響動(dòng)畫的性能和流暢度。相反,當(dāng)我們使用簡單的選擇器來選擇元素,并為它們添加動(dòng)畫效果時(shí),瀏覽器可以更快地計(jì)算樣式,從而提高動(dòng)畫的性能和流暢度。

假設(shè)我們有一個(gè)列表,其中包含多個(gè)項(xiàng)目。我們想要為這些項(xiàng)目添加一個(gè)簡單的動(dòng)畫效果,當(dāng)鼠標(biāo)懸停在項(xiàng)目上時(shí),項(xiàng)目的背景色會(huì)漸變?yōu)樗{(lán)色。我們可以使用以下 CSS 代碼來實(shí)現(xiàn)這個(gè)效果:

/* 使用類選擇器來選擇所有項(xiàng)目 */
.item {
  background-color: #fff; /* 初始背景色為白色 */
  transition: background-color 0.3s ease; /* 添加背景色漸變動(dòng)畫 */
}


/* 當(dāng)鼠標(biāo)懸停在項(xiàng)目上時(shí),將背景色漸變?yōu)樗{(lán)色 */
.item:hover {
  background-color: #007bff; /* 背景色漸變?yōu)樗{(lán)色 */
}

在這個(gè)例子中,我們使用了類選擇器來選擇所有的項(xiàng)目,并為它們添加了一個(gè)初始的背景色和一個(gè)背景色漸變動(dòng)畫。當(dāng)鼠標(biāo)懸停在項(xiàng)目上時(shí),我們使用: hover 偽類選擇器來選擇當(dāng)前懸停的項(xiàng)目,并將其背景色漸變?yōu)樗{(lán)色。

這個(gè)例子中的選擇器非常簡單,瀏覽器可以很快地計(jì)算樣式,從而提高動(dòng)畫的性能和流暢度。相比之下,如果我們使用復(fù)雜的選擇器來選擇項(xiàng)目,并為它們添加動(dòng)畫效果,瀏覽器需要花費(fèi)更長的時(shí)間來計(jì)算樣式,從而影響動(dòng)畫的性能和流暢度。

3.4 使用 will-change

使用 will-change 屬性來告訴瀏覽器哪些元素將要進(jìn)行動(dòng)畫,以便瀏覽器提前進(jìn)行優(yōu)化。

will-change 屬性是 CSS3 的一個(gè)新屬性,它可以告訴瀏覽器哪些元素將要進(jìn)行動(dòng)畫,從而使瀏覽器可以提前進(jìn)行優(yōu)化,提高動(dòng)畫的性能和流暢度。

例如,如果您要對某個(gè)元素進(jìn)行動(dòng)畫,您可以在 CSS 中添加以下代碼:

#textbox {
  opacity: 1; /* 初始透明度為1 */
  transition: opacity 0.3s ease; /* 添加透明度漸變動(dòng)畫 */
  will-change: opacity; /* 告知瀏覽器我們將會(huì)修改透明度 */
}

在這個(gè)例子中,我們使用 will-change 屬性來告知瀏覽器我們將會(huì)修改文本框的透明度,從而使瀏覽器可以提前進(jìn)行優(yōu)化。當(dāng)動(dòng)畫開始時(shí),瀏覽器已經(jīng)準(zhǔn)備好了相應(yīng)的資源,從而可以更快地渲染動(dòng)畫,提高動(dòng)畫的性能和流暢度。

需要注意的是,will-change 屬性應(yīng)該謹(jǐn)慎使用,因?yàn)樗赡軙?huì)導(dǎo)致瀏覽器提前分配額外的內(nèi)存和資源,從而影響頁面的性能。因此,只有在必要的情況下才應(yīng)該使用 will-change 屬性。

CSS3 will-change 屬于 web 標(biāo)準(zhǔn)屬性,兼容性這塊 Chrome/FireFox/Opera 都是支持的。

使用 will-change 屬性是優(yōu)化 CSS 動(dòng)畫的重要技巧之一,可以提高動(dòng)畫的性能和流暢度。

3.5 使用 requestAnimationFrame

requestAnimationFrame 代替 setTimeout 或 setInterval 來執(zhí)行動(dòng)畫,因?yàn)樗梢宰畲蟪潭鹊乩脼g覽器的優(yōu)化。

requestAnimationFrame 是瀏覽器提供的一個(gè) API,它可以讓我們在下一次瀏覽器繪制之前執(zhí)行動(dòng)畫。與 setTimeout 或 setInterval 相比,requestAnimationFrame 可以更好地利用瀏覽器的優(yōu)化,從而提高動(dòng)畫的性能和流暢度。

例如,如果您要對某個(gè)元素進(jìn)行動(dòng)畫,您可以使用 requestAnimationFrame 來執(zhí)行動(dòng)畫:

function animate() {
  // 更新元素的樣式
  element.style.transform = 'translateX(100px)';

  // 使用requestAnimationFrame執(zhí)行下一幀動(dòng)畫
  requestAnimationFrame(animate);
}


// 開始執(zhí)行動(dòng)畫
requestAnimationFrame(animate);

在上面的代碼中,我們使用 requestAnimationFrame 來執(zhí)行動(dòng)畫。在每一幀動(dòng)畫中,我們更新元素的樣式,然后使用 requestAnimationFrame 執(zhí)行下一幀動(dòng)畫。這樣可以最大程度地利用瀏覽器的優(yōu)化,提高動(dòng)畫的性能和流暢度。

需要注意的是,requestAnimationFrame 并不是所有瀏覽器都支持,因此在使用它時(shí)需要進(jìn)行兼容性處理。通常情況下,我們可以使用一個(gè)polyfill來實(shí)現(xiàn) requestAnimationFrame 的兼容性。

3.6 避免在動(dòng)畫中使用 JavaScript 操作 DOM

在動(dòng)畫中使用 JavaScript 操作 DOM 會(huì)影響性能,主要是因?yàn)?DOM 操作是非常耗費(fèi)資源的,因?yàn)檫@會(huì)引起重排和重繪。每次操作 DOM 都會(huì)觸發(fā)瀏覽器重新計(jì)算元素的布局和重新繪制元素,這些操作會(huì)消耗大量的 CPU 資源和內(nèi)存,導(dǎo)致動(dòng)畫卡頓或者不流暢。

在動(dòng)畫中,如果需要頻繁地操作DOM,就會(huì)導(dǎo)致性能問題。例如,如果在動(dòng)畫中使用 JavaScript 來改變元素的位置、尺寸、樣式等屬性,就會(huì)觸發(fā) DOM 操作,影響動(dòng)畫的流暢度。

如果必須使用 JavaScript 操作 DOM,請盡可能減少它們的使用。例如,您可以在動(dòng)畫開始前將需要操作的元素緩存到變量中,然后在動(dòng)畫中直接使用這些變量,而不是每次都重新查找元素。

另外,還可以使用 CSS3 的動(dòng)畫屬性來代替 JavaScript 操作 DOM。例如,使用 animation 屬性可以實(shí)現(xiàn)復(fù)雜的動(dòng)畫效果,而不需要使用 JavaScript 操作 DOM,下面會(huì)詳細(xì)說為什么用盡量用 css 動(dòng)畫而不使用 javascript 動(dòng)畫。

3.7 用 CSS 動(dòng)畫盡量不使用 JavaScript 動(dòng)畫

因?yàn)榍罢呖梢愿玫乩脼g覽器的優(yōu)化。

假設(shè)我們有一個(gè)按鈕,當(dāng)用戶點(diǎn)擊按鈕時(shí),我們想要將一個(gè)文本框從屏幕上移除,并在移除時(shí)添加一個(gè)簡單的動(dòng)畫效果。我們可以使用以下 JavaScript 代碼來實(shí)現(xiàn)這個(gè)效果:

var textbox = document.getElementById('textbox'); // 獲取文本框元素
var button = document.getElementById('button'); // 獲取按鈕元素


button.addEventListener('click', function() {
  textbox.style.opacity = 0; // 文本框透明度漸變?yōu)?
  setTimeout(function() {
    textbox.parentNode.removeChild(textbox); // 移除文本框元素
  }, 300); // 延遲300毫秒后移除文本框元素
});

在這個(gè)例子中,我們使用 JavaScript 操作 DOM 元素,通過獲取文本框和按鈕元素,并在按鈕被點(diǎn)擊時(shí)逐漸將文本框的透明度降低到 0,然后在 300 毫秒后移除文本框元素。

然而,這種方法會(huì)導(dǎo)致瀏覽器進(jìn)行重排和重繪,從而影響動(dòng)畫的性能和流暢度。相反,我們可以使用 CSS3 的 transition 屬性來實(shí)現(xiàn)一個(gè)簡單的動(dòng)畫效果,而無需使用 JavaScript 操作 DOM 元素。

例如,我們可以使用以下 CSS 代碼來實(shí)現(xiàn)一個(gè)簡單的動(dòng)畫效果,當(dāng)用戶點(diǎn)擊按鈕時(shí),文本框會(huì)逐漸消失:

#textbox {
  opacity: 1; /* 初始透明度為1 */
  transition: opacity 0.3s ease; /* 添加透明度漸變動(dòng)畫 */
}


#textbox.hide {
  opacity: 0; /* 透明度漸變?yōu)? */
}

在這個(gè)例子中,我們使用 CSS3 的 transition 屬性來實(shí)現(xiàn)一個(gè)簡單的透明度漸變動(dòng)畫。當(dāng)用戶點(diǎn)擊按鈕時(shí),我們使用 JavaScript 為文本框添加一個(gè) hide 類,這個(gè)類會(huì)將文本框的透明度逐漸降低到 0,從而實(shí)現(xiàn)文本框逐漸消失的動(dòng)畫效果。

這個(gè)例子中的動(dòng)畫效果可以直接作用于 DOM 元素,而無需使用 JavaScript 操作 DOM 元素,從而提高動(dòng)畫的性能和流暢度。

在動(dòng)畫中使用 CSS 動(dòng)畫可以更好地利用瀏覽器的硬件加速,從而提高動(dòng)畫的性能和流暢度。相比之下,JavaScript 動(dòng)畫通常需要更多的計(jì)算和操作,從而影響動(dòng)畫的性能和流暢度。

當(dāng)然,在某些情況下,JavaScript 動(dòng)畫可能是必要的。例如,在需要與用戶交互的動(dòng)畫中,JavaScript 動(dòng)畫可以更好地控制動(dòng)畫的行為。但是,在這種情況下,我們?nèi)匀粦?yīng)該盡可能減少 JavaScript 操作的次數(shù),以提高動(dòng)畫的性能和流暢度。

四、結(jié)論

動(dòng)畫給予了頁面豐富的視覺體驗(yàn)。我們應(yīng)該盡力避免使用會(huì)觸發(fā)重布局和重繪的屬性,以免失幀。最好提前申明動(dòng)畫,這樣能讓瀏覽器提前對動(dòng)畫進(jìn)行優(yōu)化。由于 GPU 的參與,現(xiàn)在用來做動(dòng)畫的最好屬性是如下幾個(gè):* opacity* translate* rotate* scale,Javascript 優(yōu)化、減少 Layout 和 Paint。希望對大家了解瀏覽器的渲染機(jī)制和日常的動(dòng)畫開發(fā)有所幫助。

性能優(yōu)化是一件不斷持續(xù),不斷深入的事情。我們通過本文中所介紹的改進(jìn)措施對頁面性能實(shí)現(xiàn)了很大的優(yōu)化,達(dá)到了不錯(cuò)的效果。后續(xù)也會(huì)在此基礎(chǔ)之上對還可提高的地方繼續(xù)加深,后續(xù)提供通用的解決方案。

責(zé)任編輯:張燕妮 來源: 攜程技術(shù)
相關(guān)推薦

2023-07-07 14:18:57

攜程實(shí)踐

2022-09-09 15:49:03

攜程火車票組件化管理優(yōu)化

2023-09-15 09:34:54

2023-06-28 14:01:13

攜程實(shí)踐

2023-05-12 09:58:05

編譯優(yōu)化

2023-10-20 09:17:08

攜程實(shí)踐

2023-06-28 10:10:31

攜程技術(shù)

2024-01-30 08:55:24

2011-01-24 15:37:32

火車票

2022-08-17 09:54:57

Java性能優(yōu)化

2011-12-20 14:09:40

2012-01-05 13:14:42

火車票

2016-08-31 13:26:24

PythonPython3工具

2011-01-28 15:48:11

Chrome插件Page Monito火車票

2012-01-13 10:16:39

2018-01-10 22:19:44

2018-12-29 16:24:58

Python12306火車票

2022-07-15 09:20:17

性能優(yōu)化方案

2022-07-08 09:38:27

攜程酒店Flutter技術(shù)跨平臺(tái)整合

2012-11-15 09:40:18

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)