搜尋
首頁web前端H5教程以HTML5建構高效能視差網站的圖文程式碼詳解

        本文介紹了一種時尚的網站設計方法,以及如何由淺入深的透過HTML5和瀏覽器渲染機制來建立高效能的網站。

        文中多處涉及瀏覽器重繪和性能優化的原理,也是《Web滾動性能優化實戰》的拓展和延續,難度上屬於中級進階,請在閱讀前請先看看這篇文章。

        介紹

#        

Old Pulteney Row to the Pole
  •         

    Adidas Snowboarding
  •         

    #BBC News - James Bond: Cars, catchphrases and kisses


以HTML5建構高效能視差網站的圖文程式碼詳解

#        如果你還不了解它們,它們其實就是頁面的視覺結構隨滾動變化的網站。正常情況下,頁面上的元素會按比例縮放、旋轉或移動到滾動的位置。

我們視差效果的示範頁面以HTML5建構高效能視差網站的圖文程式碼詳解

        你喜不喜歡視差網站是一回事,但是我們能確定的是這絕對是一個效能黑洞。原因是當你滾動時,瀏覽器會試圖對新內容出現的地方(根據滾動的方向)進行性能優化,總的來講,在滾動中視覺上越少更新瀏覽器性能越好。對於視差網站來說這很少見,因為在整個頁面上大的視覺元素會多次發生改變,從而導致瀏覽器必須對整個頁面進行重繪(為什麼是性能黑洞,可以參考我的這篇文章《 Web滾動效能優化實戰》)。

        將視差網站歸納為下面的特色是合理的:

        1、  當你往上或向下捲動頁面時,背景元素改變位置、旋轉或縮放。

        2、  頁面內容,例如文字或小圖片,以特別的從上到下的方式捲動。

        我們先前介紹過滾動效能及其最佳化方式,你可以以此來改善應用的反應能力。本文將建立在此基礎上,所以你需要先讀一下上面這篇文章。 ######        所以現在的問題是,如果你正在建立一個視差滾動網站,是必須要進行代價昂貴的重繪,還是有其它方法可以採用來最大限度的提高性能?讓我們來看看可供選擇的方法。 #########        方法1:使用DOM元素和絕對定位#########        這可能是多數人所選擇的方式。頁面裡有許多元素,當滾動事件觸發時,許多視覺上的更新會發生在這些元素上。這裡我展示了一個演示頁面。 ######        如果你開啟了開發者工具時間軸的frame模式,並且上下滾動,你會注意到有代價昂貴的全螢幕繪製操作。如果你滾動多次,你也許可以在一個單獨的幀裡看到多個滾動事件,每一個都會觸發佈局工作。 ###############開發者工具顯示了一幀裡有大量的繪圖作業和多個由事件觸發的版面######        重要的是要牢記,為了達到60fps(與典型的顯示器刷新率60Hz相符),我們必須在差不多16ms內完成所有事情。在這第一個版本中,我們每當得到一個滾動事件,我們就要執行一次視覺更新,但是正如我們在前面的文章-《用requestAnimationFrame實現更簡單動畫》和《Web滾動性能優化實戰》裡討論到的一樣,這與瀏覽器的更新節奏並不一致。所以我們要么錯過幀,要么在一幀裡完成太多的工作。這會讓你的網站很容易看起來不舒服和不自然,導致用戶感覺失望。 ######        讓我們把視覺更新的程式碼從滾動事件中移到###requestAnimationFrame###回呼裡,並且在滾動事件的回呼裡簡單的獲取滾動的值。我們在第二個演示中展示了這個變化。 ###

        如果你重複滾動測試,你可能會注意到有輕微的改善,雖然不多。原因是由滾動觸發的佈局操作代價昂貴,現在我們只在每幀中執行一次佈局操作。

以HTML5建構高效能視差網站的圖文程式碼詳解

開發者工具展示了一幀裡有大量的繪圖作業和多個由事件觸發的佈局

        我們現在在每個畫面中可以處理一個或上百個滾動事件,但最重要的是,我們僅僅儲存最近的一個滾動值,供requestAnimationFrame回調觸發時使用,並執行視覺上的更新。關鍵是我們已經從每次接收到滾動事件時進行視覺更新優化為在瀏覽器給我們的合適時機進行處理。你是不是覺得這相當給力?

        這個方法的主要問題是,無論使用requestAnimationFrame與否,我們基本上都會產生整個頁面的層,在移動這些視覺元素時需要大量且代價昂貴的重繪。通常重繪會是一個阻塞操作(雖然這點將會優化),這意味著瀏覽器不能同時進行其它工作,而我們經常有可能超過瀏覽器16ms的幀的處理時限,這代表會出現性能上卡頓的情況。

        方法2:使用DOM元素和3D轉換

        除了絕對定位之外,另一個我們可以採取的方法是3D轉換(transform)。在這種情況下我們可以看到每個用3D轉換處理的元素都會產生新的圖層。相較之下,在方法1中,如果有任何變更時,我們必須要重繪頁面上一大部分的層。

        這表示使用此方法情況會大為不同:我們可能對應用了3D轉換的任何元素都會有一個層。如果透過更多元素的轉換做到這一點,我們不需要重繪任何層,GPU能夠處理移動元素和合成整個頁面。也許你想知道為什麼用3D轉換取代3D,原因是2D轉換不能保證得到一個新的層,而3D#可以

        這是另一個使用了3D轉換的示範。滾動時你可以看到效能已經大有改觀。

        很多時候人們使用-webkit-transform:translateZ(0)這個技巧,能夠看到有奇妙的性能改善(宇捷註:關於這種方式,其實就是利用3D轉換來開啟瀏覽器硬體加速,屬於一種Hack。 《IncreasingPerformance of HTML and JavaScript on Mobile Devices》)。這個方式現在可以正常運作,但是會帶來一些問題:

        1、  它並不是瀏覽器相容的;

        2、  它強迫瀏覽器為每一個轉換的元素建立新的層。大量的層會帶來其它性能瓶頸,所以需要有節制的使用。

        3、  它在某些Webkit版本的移植上停用。

        所以,你如果採取這種方法需要非常謹慎,這對解決問題來說是一個臨時方案。在完美的情況下我們甚至不會考慮它,而且瀏覽器每天都在改進中,誰知道也許哪天我們就不需要它了。

        方法3:使用固定定位(Fixed Position)的Canvas或WebGL

##        我們最後要考慮的方法就是在頁面上採用固定定位的Canvas,而把轉換的圖像繪製在上面。乍看之下,這可能不是最有效率的解決方案,但它有幾個好處:


  • #        我們不再需要大量合成工作,因為頁面只有一個元素- Canvas;

  •         我們可以高效的透過硬體加速處理一個單獨的bitmap;

  •         Canvas2D API非常適合我們要執行的轉換類型,這意味著開發和維護更容易管理。


        使用Canvas元素為我們提供了一個新的層,但是它只有一層,而在方法2中我們為每一個應用3D轉換的元素都創建了一個新層,所以有額外的工作量來把這些層合成在一起。

        如果你看看這個方法的示範,並且在開發者工具中觀察,你會發現它的表現更加優異。在這個方法裡,我們只需在Canvas上呼叫drawImage API、設定背景圖像,以及每一個要在螢幕上正確位置繪製的色塊。

/**
 * Updates and draws in the underlying visual elements to the canvas.
 */
function updateElements () {

  var relativeY = lastScrollY / h;

  // Fill the canvas up
  context.fillStyle = "#1e2124";
  context.fillRect(0, 0, canvas.width, canvas.height);

  // Draw the background
  context.drawImage(bg, 0, pos(0, -3600, relativeY, 0));

  // Draw each of the blobs in turn
  context.drawImage(blob1, 484, pos(254, -4400, relativeY, 0));
  context.drawImage(blob2, 84, pos(954, -5400, relativeY, 0));
  context.drawImage(blob3, 584, pos(1054, -3900, relativeY, 0));
  context.drawImage(blob4, 44, pos(1400, -6900, relativeY, 0));
  context.drawImage(blob5, -40, pos(1730, -5900, relativeY, 0));
  context.drawImage(blob6, 325, pos(2860, -7900, relativeY, 0));
  context.drawImage(blob7, 725, pos(2550, -4900, relativeY, 0));
  context.drawImage(blob8, 570, pos(2300, -3700, relativeY, 0));
  context.drawImage(blob9, 640, pos(3700, -9000, relativeY, 0));

  // Allow another rAF call to be scheduled
  ticking = false;
}

/**
 * Calculates a relative disposition given the page’s scroll
 * range normalized from 0 to 1
 * @param {number} base The starting value.
 * @param {number} range The amount of pixels it can move.
 * @param {number} relY The normalized scroll value.
 * @param {number} offset A base normalized value from which to start the scroll behavior.
 * @returns {number} The updated position value.
 */
function pos(base, range, relY, offset) {
  return base + limit(0, 1, relY - offset) * range;
}

/**
 * Clamps a number to a range.
 * @param {number} min The minimum value.
 * @param {number} max The maximum value.
 * @param {number} value The value to limit.
 * @returns {number} The clamped value.
 */
function limit(min, max, value) {
  return Math.max(min, Math.min(max, value));
}

        這個做法真的在處理大圖片(或者它很容易寫到一個Canvas上的元素)或者大塊的文本時肯定根據挑戰性。但是在你的網站上,它可能被證明會是最合適的解決方案。如果你不得不在Canvas上處理文本,你也許要使用fillText API,但是它有訪問成本(你剛剛把文本轉換為bitmap!)而且你需要處理文本換行以及其它問題。你需要盡量避免這麼做。

        討論了這麼多,我們沒有理由假設視差的工作就一定要用Canvas元素。如果瀏覽器支持,我們可以使用WebGL。這裡面的關鍵是WebGL是所有API到顯示卡最直接的方式,並且在你的網站效果很複雜的情況下效能是最有可能達到60fps的。

        你最直接的反應可能是覺得採用WebGL矯枉過正,或者它並沒有獲得廣泛支持,但是如果你如果使用了類似於Three.js的庫,你可以隨時回退為使用Canvas元素,同時你的程式碼能以一致和友善的方式進行抽象。我們需要做的只是用Modernizr來偵測對應API的支援:


// check for WebGL support, otherwise switch to canvas
if (Modernizr.webgl) {
  renderer = new THREE.WebGLRenderer();
} else if (Modernizr.canvas) {
  renderer = new THREE.CanvasRenderer();
}


        然後使用Three.js的API,而不是自己處理上下文。這裡有一個支援兩種渲染方式的示範。

        這個方法的最後一個問題是,如果你不特別愛好在頁面上添加額外的元素,你可以總是在Firefox和Webkit瀏覽器裡使用canvas作為背景元素。很明顯,這並不是普遍適用的,所以你應該對此持謹慎態度。

         逐步退化

        開發者預設使用絕對定位元素而非其它方法的主要原因可能單純且簡單是瀏覽器支援的問題。這種方式在某種程度上是錯誤的,因為對於老舊的瀏覽器來說,只能提供非常貧乏的渲染體驗。即便在現代瀏覽器中,使用絕對定位也不一定能帶來好的效能。

        較好的方案是避免在舊的瀏覽器上嘗試視差效果,並且只確保在最好的瀏覽器上能以正確的API呈現網站效果。當然,如果你使用了Three.js,你應該能夠很容易根據所需的支援在渲染器之間進行切換。

        結論

#        我們評估了幾種方式來處理大量重繪的區域,從絕對定位的元素到使用固定定位的Canvas。當然你要採用的實現方式,取決於你要達到的目標和具體設計,但是知道有多種選擇是一件好事情。在本文的例子中,我們設法從相對卡頓、低於30fps優化到了平滑、60fps的效果。

 

以上是以HTML5建構高效能視差網站的圖文程式碼詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
H5:網絡內容和設計的未來H5:網絡內容和設計的未來May 01, 2025 am 12:12 AM

H5(HTML5)將通過新元素和API提升網頁內容和設計。 1)H5增強了語義化標記和多媒體支持。 2)它引入了Canvas和SVG,豐富了網頁設計。 3)H5的工作原理是通過新標籤和API擴展HTML功能。 4)基本用法包括使用創建圖形,高級用法涉及WebStorageAPI。 5)開發者需注意瀏覽器兼容性和性能優化。

H5:網絡開發的新功能和功能H5:網絡開發的新功能和功能Apr 29, 2025 am 12:07 AM

H5帶來了多項新功能和能力,極大提升了網頁的互動性和開發效率。 1.語義化標籤如、增強了SEO。 2.多媒體支持通過和標籤簡化了音視頻播放。 3.Canvas繪圖提供了動態圖形繪製工具。 4.本地存儲通過localStorage和sessionStorage簡化了數據存儲。 5.地理位置API便於開發基於位置的服務。

H5:HTML5的關鍵改進H5:HTML5的關鍵改進Apr 28, 2025 am 12:26 AM

HTML5帶來了五個關鍵改進:1.語義化標籤提升了代碼清晰度和SEO效果;2.多媒體支持簡化了視頻和音頻嵌入;3.表單增強簡化了驗證;4.離線與本地存儲提高了用戶體驗;5.畫布與圖形功能增強了網頁的可視化效果。

HTML5:標準及其對Web開發的影響HTML5:標準及其對Web開發的影響Apr 27, 2025 am 12:12 AM

HTML5的核心特性包括語義化標籤、多媒體支持、離線存儲與本地存儲、表單增強。 1.語義化標籤如、等,提升代碼可讀性和SEO效果。 2.和標籤簡化多媒體嵌入。 3.離線存儲和本地存儲如ApplicationCache和LocalStorage,支持無網絡運行和數據存儲。 4.表單增強引入新輸入類型和驗證屬性,簡化處理和驗證。

H5代碼示例:實際應用和教程H5代碼示例:實際應用和教程Apr 25, 2025 am 12:10 AM

H5提供了多種新特性和功能,極大地增強了前端開發的能力。 1.多媒體支持:通過和元素嵌入媒體,無需插件。 2.畫布(Canvas):使用元素動態渲染2D圖形和動畫。 3.本地存儲:通過localStorage和sessionStorage實現數據持久化存儲,提升用戶體驗。

H5和HTML5之間的連接:相似性和差異H5和HTML5之間的連接:相似性和差異Apr 24, 2025 am 12:01 AM

H5和HTML5是不同的概念:HTML5是HTML的一個版本,包含新元素和API;H5是基於HTML5的移動應用開發框架。 HTML5通過瀏覽器解析和渲染代碼,H5應用則需要容器運行並通過JavaScript與原生代碼交互。

H5代碼的基礎:密鑰元素及其目的H5代碼的基礎:密鑰元素及其目的Apr 23, 2025 am 12:09 AM

HTML5的關鍵元素包括、、、、、等,用於構建現代網頁。 1.定義頭部內容,2.用於導航鏈接,3.表示獨立文章內容,4.組織頁面內容,5.展示側邊欄內容,6.定義頁腳,這些元素增強了網頁的結構和功能性。

HTML5和H5:了解常見用法HTML5和H5:了解常見用法Apr 22, 2025 am 12:01 AM

HTML5和H5沒有區別,H5是HTML5的簡稱。 1.HTML5是HTML的第五個版本,增強了網頁的多媒體和交互功能。 2.H5常用於指代基於HTML5的移動網頁或應用,適用於各種移動設備。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器