“懶”的妙用——淺析圖片懶載入技術

發表於2017-12-25

1、定義

圖片懶載入是一種網頁優化技術。圖片作為一種網路資源,在被請求時也與普通靜態資源一樣,將佔用網路資源,而一次性將整個頁面的所有圖片載入完,將大大增加頁面的首屏載入時間。為了解決這種問題,通過前後端配合,使圖片僅在瀏覽器當前視窗內出現時才載入該圖片,達到減少首屏圖片請求數的技術就被稱為“圖片懶載入”。

2、傳統的解決方案

我們先來探討一下傳統的圖片懶載入技術是如何實現的。

以京東sale活動頁為例,我們隨便選取一個活動地址,檢視網頁原始碼,我們可以找到形如這種結構的img標籤:

我們試著來分析一下這個img標籤的結構,首先我們在瀏覽器中直接開啟該img標籤的src,即:“//img14.360buyimg.com/cms/g10/M00/13/04/rBEQWFFj4PUIAAAAAAAESxyqJLUAADvdAIHC9oAAARj186.gif”。結果發現這張圖是一張10*10的空白圖片。我們發現img標籤中還有一個偽屬性original,裡面也有一個很像是圖片的連結,我們再在瀏覽器中訪問這個連結:646

 

果然如我們所料,original中存放的才是真實圖片的路徑。

那麼瀏覽器是怎麼載入存放在偽屬性中的真實圖片的呢?

首先後端直出的頁面結構中,img標籤中的src為一張佔點陣圖,真實圖片地址存放在一個偽屬性中,如:data-src中。當頁面滾動時,遍歷當前頁面需要進行懶載入的圖片,判斷圖片是否在可視區域內,如果在的話,則取存放在偽屬性中的真實src替換當前的src。

640

以上是一張簡略的示意圖,外部黑色框代表頁面範圍(即html的範圍),虛線內代表瀏覽器當前視窗區域。在這個場景下,只有第4、5、6張圖片處在當前視窗中,因此它們會使用上述載入策略,使用真實src替換佔點陣圖。而其餘的幾張圖片由於並不在可視區域內,因此並不會被立即載入,只有當滾動事件產生,某張圖片(或圖片的一部分)開始出現在視窗內時,才會真正載入。

3、可優化的一些點:

(1)滾動函式的節流

瀏覽器中的滾動事件是一個觸發非常頻繁的事件,有時候我們主觀體驗只是輕輕撥動了一下滾輪,但實際上觸發了數次甚至數十次的onscroll事件:

641

還記得我們在前文所述的懶載入策略中提到,每次滾動事件都將執行:選擇頁面所有圖片→遍歷→篩選在當前視窗內的圖片→使用真實src替換佔點陣圖。以上過程是一個非常耗時的過程,尤其是在篩選符合條件的圖片的步驟。因此,我們需要對滾動事件進行節流:只有當後一次觸發滾動與前一次觸發滾動的時間間隔大於一定閾值時,才認為這次滾動生效。

通俗地說,就是兩次滾動事件之間必須大於一定的時間。這意味著使用者在快速下滑頁面時,篩選載入策略並不會執行,只有當使用者停下或是逐漸放緩下滑速度時,才會進行篩選載入策略。若用jQuery實現上述節流步驟則如下所示(scroll事件節流閾值150ms,resize事件節流閾值100ms):

642

(2)預載入

顧名思義,預載入就是指預先載入一些未在當前視窗內,但是即將出現的一些圖片。還是拿前文舉的例子進行擴充套件:

643

可以看到,雖然當前視窗中只有3張圖片,但若使用預載入,將提前載入前後各1螢幕內的影像(紅色虛線內),如此一來,當使用者在當前視窗內繼續上滑或下滑時,該屏內的圖片已經提前載入完畢,使用者就不會感知到圖片從白屏到顯像的這種抖動過程,大大提升了使用者體驗。

4、更優的使用者體驗

在國內網站中,知乎官網在圖片懶載入部分做得較為領先,擁有很好的使用者體驗。讓我們先來看一下效果,隨便開啟一個知乎問答頁(在PC環境中開啟):知乎問答頁示例

效果圖:

0

仔細觀察,我們可以看到這樣一種效果:圖片在由白至清晰的過程中有一種模糊漸變的效果,相比於直接替換空白佔點陣圖的方案,這種方式不會給使用者帶來突兀感。

檢視頁面原始碼,我們發現直出的頁面中img標籤是以這種形式存在的:

644

img標籤及其內的資訊作為字串儲存在noscript標籤中,src中為一張低品質圖片,data-original中為真實圖片地址,同時有一個佔位的span元素。當頁面滾動到該noscript標籤對應的位置時,解析出noscript標籤中的img,並替換佔位span元素:

645

此時將先載入低質量的小圖,再載入清晰的高質量原圖:

647

如此一來,使用者將在極短的時間內就能看到圖片的大致輪廓。隨後等真實圖片載入完畢後,再使用CSS控制圖片逐漸變清晰,整個過程順暢自然,一氣呵成。在網速較差的環境下,這種方式也能有很優雅的降級體驗。

5、更加富有腦洞的圖片懶載入策略:

這裡有一篇國外論壇的文章:How to use SVG as a Placeholder, and Other Image Loading Techniques,主題是利用SVG生成各種風格的佔點陣圖。國內也有人對其進行了簡要翻譯:圖片載入時使用 SVG 作為圖片 placehold。

我們在上文中提到的佔點陣圖都是一個空白圖片的形式,而這篇文章中提出了一些非常新穎而前衛的佔點陣圖生成方式:

(1)梯度底色佔點陣圖:

644這種方式是通過後端的處理,將img標籤中的圖片提前做一次解析,處理為一種帶梯度的SVG元素,這種SVG元素所佔體積極小,可以隨頁面一起直出。

換種思路,如果我們不想使用SVG,也可以直接將圖片的主要背景顏色提取出來,使用base64方式直出該圖片。

(2)SVG色塊:

645

我們可以通過一些簡單的SVG元素拼接,描繪出圖片的基本輪廓,並在此基礎上加上一個模糊濾鏡,也可以達到很好的佔點陣圖效果。

(3)二值化剪影:

646

效果圖如上。

推薦看一下原文,作者也分享了一些生成這些SVG佔點陣圖所需要使用的工具庫。

 

相關文章