2014年12月1日 星期一

[外掛] jQuery 圖片延遲載入﹍Lazy Load 安裝懶人包 (徹底解決圖片 reflow 現象)

[外掛] jQuery 圖片延遲載入﹍Lazy Load 安裝懶人包 (徹底解決圖片 reflow 現象)

Wayne Fu 0 A+
當網頁圖片多的時候,「影響效能的最大因素就是圖片載入」。除了縮減圖片尺寸、壓縮檔案來縮短傳輸時間之外,更好的改善方法是讓圖片能延遲載入,先讓頁面把主要文字內容優先顯示出來──這正是 jQuery 圖片延遲載入外掛「Lazy Load」的作用。

好的,本篇的程式正是為了解決以上所有難題,自動幫文章中的圖片預先設定尺寸、並能執行最佳的 Lazy Load 效果。以下大致先說明原理,想直接安裝懶人包請跳至「二、準備動作」。




<< 請注意!本篇文章含會員限定內容 >>


一、新舊版 Lazy Load 及最佳化原理


1. 版本差異

目前「Lazy Load 官網」提供的 js 版本,要正常運作得將圖片的 HTML 碼改為以下格式:

<img class="lazy" data-original="img/example.jpg" width="640" height="480">
原本 img 應該是 src 屬性的位置,必須改為 "data-original" 這樣的屬性,且須手動設定圖片寬、高值。如果每張圖片都這麼搞,沒幾個人有這樣的耐性吧?

這篇「Lazy Load 最佳安裝方式」使用 Lazy Load 舊版的 js,圖片 img 的 HTML 不需做任何變更即可執行延遲載入,因此舊版的 js 比較適合懶人安裝法,本篇的程式碼依舊沿用這個版本。


2. 自動取得圖片寬高

這部分的原理是,利用 jQuery 的 on() 函數來監控 img 的 load 事件,就能取得圖片的寬高值,再設定到原本的 img 上,來避免 reflow 的發生。


3. Lazy Load 擺放位置

如同「舊版 Lazy Load 教學」的說明,網頁不需要全部圖片都 Lazy Load,最需要使用 Lazy Load 的是文章區塊的圖片。因此最佳的執行位置是「文章區塊結尾處」,而非 </body> 之前的位置。

也因為這一點,要安裝 Lazy Load 得先「找出文章區塊結尾處」這個位置。本篇教學提供 Blogger 的範例,而非 Blogger 平台的使用者,可能需學會操作「Chrome 開發人員工具」這樣的介面,來自行找出文章區塊的位置。



二、安裝準備動作


1. Blogger 平台

安裝過舊版本的話,這部分的動作可不必再做。

在修改範本之前,如果第一次安裝本站工具的讀者,建議先閱讀「備份範本的訣竅」系列文章。

請到後台「範本」→「編輯 HTML」,游標點進範本區塊,搜尋 </head> 這個字串,找到後在此字串的前一行,插入以下程式碼:

<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js'></script>
<script>//<![CDATA[(function($){$.fn.lazyload=function(options){var settings={threshold:0,failurelimit:0,event:"scroll",effect:"show",container:window};if(options){$.extend(settings,options);}
var elements=this;if("scroll"==settings.event){$(settings.container).bind("scroll",function(event){var counter=0;elements.each(function(){if($.abovethetop(this,settings)||$.leftofbegin(this,settings)){}else if(!$.belowthefold(this,settings)&&!$.rightoffold(this,settings)){$(this).trigger("appear");}else{if(counter++>settings.failurelimit){return false;}}});var temp=$.grep(elements,function(element){return!element.loaded;});elements=$(temp);});}
this.each(function(){var self=this;if(undefined==$(self).attr("original")){$(self).attr("original",$(self).attr("src"));}
if("scroll"!=settings.event||undefined==$(self).attr("src")||settings.placeholder==$(self).attr("src")||($.abovethetop(self,settings)||$.leftofbegin(self,settings)||$.belowthefold(self,settings)||$.rightoffold(self,settings))){if(settings.placeholder){$(self).attr("src",settings.placeholder);}else{$(self).removeAttr("src");}
self.loaded=false;}else{self.loaded=true;}
$(self).one("appear",function(){if(!this.loaded){$("").bind("load",function(){$(self).hide().attr("src",$(self).attr("original"))
[settings.effect](settings.effectspeed);self.loaded=true;}).attr("src",$(self).attr("original"));};});if("scroll"!=settings.event){$(self).bind(settings.event,function(event){if(!self.loaded){$(self).trigger("appear");}});}});$(settings.container).trigger(settings.event);return this;};$.belowthefold=function(element,settings){if(settings.container===undefined||settings.container===window){var fold=$(window).height()+$(window).scrollTop();}else{var fold=$(settings.container).offset().top+$(settings.container).height();}
return fold<=$(element).offset().top-settings.threshold;};$.rightoffold=function(element,settings){if(settings.container===undefined||settings.container===window){var fold=$(window).width()+$(window).scrollLeft();}else{var fold=$(settings.container).offset().left+$(settings.container).width();} return fold<=$(element).offset().left-settings.threshold;};$.abovethetop=function(element,settings){if(settings.container===undefined||settings.container===window){var fold=$(window).scrollTop();}else{var fold=$(settings.container).offset().top;} return fold>=$(element).offset().top+settings.threshold+$(element).height();};$.leftofbegin=function(element,settings){if(settings.container===undefined||settings.container===window){var fold=$(window).scrollLeft();}else{var fold=$(settings.container).offset().left;}
return fold>=$(element).offset().left+settings.threshold+$(element).width();};$.extend($.expr[':'],{"below-the-fold":"$.belowthefold(a, {threshold : 0, container: window})","above-the-fold":"!$.belowthefold(a, {threshold : 0, container: window})","right-of-fold":"$.rightoffold(a, {threshold : 0, container: window})","left-of-fold":"!$.rightoffold(a, {threshold : 0, container: window})"});})(jQuery);//]]></script>


第一行綠字的 js 檔連結可參考「引用 jQuery 的注意事項」,檢查範本是否已安裝過 jquery,以免重複安裝。


2. 非 Blogger 平台

說明一樣參考第 1 點,程式碼放在範本中 </head> 之前的位置即可。



三、安裝程式碼


1. Blogger 平台

A. 接著在範本中先找到 <b:if cond='data:post.hasJumpLink'> 這個字串,會看到類似下面「繼續閱讀」的程式碼:

<b:if cond='data:post.hasJumpLink'>
<div class='jump-link'>
<a expr:href='data:post.url + "#more"' expr:title='data:post.title'><data:post.jumpText/></a>
</div>
</b:if>


B. 緊接在以上程式碼後面,插入以下程式碼(這裡如安裝過舊版 lazy load,請先刪除舊版程式碼):


以下參數修改請參照以上程式碼行號:

F:預設讓 Lazy Load 抓文章區塊 .post-body 之間的 img 標籤來進行延遲載入,而頁面其他區塊的圖片將沒有 Lazy Load 效果。(如果要設定別的區塊的圖片,那麼 E、F 行的紅色字串得改為該區塊的 class 或 id,且全部程式碼得改放到該區塊的位置之後。)

Y:除了使用藍色字串參數 "fadeIn" 的淡入特效,還可用 "slideDown" 由小圖伸展到大圖的特效,或是使用 "show" 無特效。

2015.1.18 修訂:由於留言回報首頁圖片顯示會不正常,因此 Blogger 平台請將 Y~Z 兩行的內容置換為以下:

effect: "fadeIn"
<b:if cond='data:blog.pageType != "index"'>,
placeholder: "http://3.bp.blogspot.com/-8KXAO6va29c/VLurz0IIz2I/AAAAAAAAK-o/u7sMjZOqFm4/s0/grey.gif"
</b:if>



存檔後開一篇圖片多的文章即可看效果,或是也可參考 DEMO 網頁:



2. 非 Blogger 平台

A. 請先找出文章區塊的 class 或 id,可利用「Chrome 開發人員工具」這樣的介面。

B. 在後台範本中找到這個區塊的結尾處,於下一行插入「1. Blogger 平台」→ B 點的程式碼,並參照程式碼行號:

E~F:紅色字串得改為文章區塊的 class 或 id。

Y:除了使用藍色字串參數 "fadeIn" 的淡入特效,還可用 "slideDown" 由小圖伸展到大圖的特效,或是使用 "show" 無特效。



四、小結


若曾使用舊版 Lazy Load 安裝程式,由於圖片寬、高事先不知道數值,瀏覽器無法為圖片保留位置,畫面在捲動之間會不斷產生 reflow、版面區塊會不斷擠壓變動,增加瀏覽器無謂的運算量。使用了本篇新版的安裝程式後,相信畫面捲動的時候,可以明顯感受到兩者的差異性,為網頁帶來更好的效能。



五、常見 FAQ


日後若有常見問題,會持續補充在此。

Q1: 留言 #2 提到「進入任意一篇文章後再按導覽列上的"首頁"回到首頁,會出現圖片不見的狀況(重新整理後又正常出現)」?

Ans: 如果 Blogger 首頁會出現異常情形的話,請刪除 Y 行最後面的逗點 "," 以及 Z 行的內容即可。(2014.12.18 補充:由於多位使用者出現此情形,已將原程式碼 Y 行最後面的逗點 "," 以及 Z 行的內容去除 )


優化網站效能 相關文章:
0 0
如這篇文章對你有幫助,歡迎「分享」到 FB、「追蹤」粉絲團、「訂閱」最新文章

沒有留言:

張貼留言注意事項:

◎ 勾選「通知我」可收到後續回覆的mail!
◎ 請在相關文章留言,與文章無關的主題可至「Blogger 社團」提問。
◎ 請避免使用 Safari 瀏覽器,否則無法登入 Google 帳號留言(只能匿名留言)!
◎ 提問若無法提供足夠的資訊供判斷,可能會被無視。建議先參考這篇「Blogger 提問技巧及注意事項」。
◎ CSS 相關問題非免費諮詢,建議使用「Chrome 開發人員工具」尋找答案。
◎ 手機版相關問題請參考「Blogger 行動版範本的特質」→「三、行動版範本不一定能執行網頁版工具」;或參考「Blogger 行動版範本修改技巧 」,或本站 Blogger 行動版標籤相關文章。
◎ 非官方範本問題、或貴站為商業網站,請參考「Blogger 免費諮詢 + 付費諮詢
◎ 若是使用官方 RWD 範本,請參考「Blogger 推出全新自適應 RWD 官方範本及佈景主題」→ 不建議對範本進行修改!
◎ 若留言要輸入語法,"<"、">"這兩個符號請用其他符號代替,否則語法會消失!
◎ 為了過濾垃圾留言,所有留言不會即時發佈,請稍待片刻。
◎ 本站「已關閉自刪留言功能」。

TOP