JS圖片延遲載入
圖片延遲載入也稱 "懶載入",通常應用於圖片比較多的網頁,比如 "美麗說首頁","蘑菇街"等一些導購網站上用的比較多,或者淘寶,京東等電子商務網站上也用的比較多,因為頁面載入時候 假如我們沒有用延遲載入的話 那麼頁面上很多圖片,首先要發n多個請求,效能肯定不怎麼好,而我們用延遲載入技術,頁面開啟時候 只載入第一屏資料,第二屏以上都用延遲載入 滾動的時候進行載入,這樣的話 假如頁面不管他有n屏的話 那麼我們只管載入第一屏的資料,後面不做操作。這樣就可以顯著的提高頁面的載入速度,提升使用者體驗。且更小的併發請求也可以減輕伺服器的壓力,而且如果使用者只瀏覽首屏的話,還可以節省流量(手機客戶端應該用的比較多,減少使用者流量)。
延遲載入的原理是?
我這邊原理是先在img src中放一張佔位符圖片,而真實的圖片地址存放在相對應一個屬性 data-img(字尾img可以自定義)中,這樣的話 那麼頁面載入的時候 只載入src地址 不會對屬性的圖片真正地址載入,滾動時候判斷 待載入的資源相對於瀏覽器頂端的距離 <= 可視區域相對於瀏覽器頂端的距離 如果為true的話 則把相對應的data-img值賦值給src 否則不載入。
先看看JSFiddle的demo效果
如果最外層容器是window的話 那麼請看這個demo demo連結
如果自己定義了最外層容器的話 那麼請看這個demo demo連結
可配置的引數如下:
程式碼簡單的分析下:
1.頁面初始化init時候 只處理一個滾動事件:如下呼叫update方法:
init: function(options){ this.config = $.extend(this.config, options || {}); var self = this, _config = self.config, _cache = self.cache; // 滾動時(或者其他事件) 觸發事件 $(_config.container).unbind(_config.event); $(_config.container).bind(_config.event,function(){ self._update(); }); }
2.update方法先判斷下 容器是否是window還是自定義容器。且對向下滾動及向右滾動進行了一下處理。接著呼叫_eachImg這個方法。程式碼如下:
_update:function(){ var self = this, _config = self.config, _cache = self.cache; if(_config.container === window) { $('img').each(function(index,item){ // 如果圖片隱藏的 那麼不強制載入 if(_config.skip_invisible && !$('img').is(":visible")) { return; } if (self._abovethetop(item) || self._leftofbegin(item)) { // 什麼都不處理 } else if (self._belowthefold(item) && self._belowthefold(item)) { self._eachImg(item); } }) }else { $('img',$(_config.container)).each(function(index,item){ // 如果圖片隱藏的 那麼不強制載入 if(_config.skip_invisible && !$('img').is(":visible")) { return; } if (self._abovethetop(item) || self._leftofbegin(item)) { } else if (self._belowthefold(item) && self._rightoffold(item)) { self._eachImg(item); } }) } },
3.在呼叫eachImg方法之前 先判斷向下滾動或者向右滾動 元素是否在可視區域內 如在 則呼叫eachImg方法 把對應的data-img賦值給src 否則 反之。
HTML程式碼如下:
<img src="images/grey.gif" data-img ="http://m3.img.libdd.com/farm4/d/2014/0111/18/3256C6587D94BDF9E9908908CAB6C5FD_B500_900_500_375.jpeg" width="800" height="600" isload="false"><br/> <img src="images/grey.gif" data-img ="http://m3.img.libdd.com/farm4/d/2014/0111/18/23CC5BDD3730A819E498B703A40DE5CF_B250_400_250_187.jpeg" width="800" height="600" isload="false"><br/> <img src="images/grey.gif" data-img ="http://m3.img.libdd.com/farm4/d/2014/0111/18/33F69B61E6671E4F6623F0D1084C42A8_B250_400_250_187.jpeg" width="800" height="600" isload="false"><br/> <img src="images/grey.gif" data-img ="http://m3.img.libdd.com/farm5/d/2014/0111/18/7B87F0A2209D234D2AB907C62946A7FE_B250_400_250_187.jpeg" width="800" height="600" isload="false"><br/> <img src="images/grey.gif" data-img ="http://m2.img.libdd.com/farm5/d/2014/0111/18/C37405D8DBC8D1BF69A9C894C32FA4DA_B250_400_250_187.jpeg" width="800" height="600" isload="false"><br/> <img src="images/grey.gif" data-img ="http://m1.img.libdd.com/farm5/d/2014/0111/18/1433297A651DA0329E866FD2D2776C7F_B250_400_250_187.jpeg" width="800" height="600" isload="false">
JS所有程式碼如下:
/** * JS圖片延遲載入 * @constructor {DataLazyLoad} * @param {options} 物件傳參 * @time 2014-1-10 */ /* * 延遲載入的原理:滾動時:待載入的資源相對於遊覽器頂端的距離 - threshold <= 可視區域相對於瀏覽器頂端的距離 true 就載入 * 否則的話 不載入 */ function DataLazyLoad(options){ this.config = { container : window, //容器 預設為window threshold : 0, // 離多少畫素渲染圖片 event : 'scroll', // 預設為scroll(滾動) effect : 'fadeIn', // 預設為fadeIn 也可以為fadeIn, slideDown 等 jQuery 自帶的效果 effectspeed : 1000, // 時間 suffix : 'img', // img屬性 預設以data-img 也可以自定義字尾 skip_invisible : true // 如果img標籤為隱藏的 那麼不強制載入 }; this.cache = {}; this.init(options); } DataLazyLoad.prototype = { init: function(options){ this.config = $.extend(this.config, options || {}); var self = this, _config = self.config, _cache = self.cache; // 滾動時(或者其他事件) 觸發事件 $(_config.container).unbind(_config.event); $(_config.container).bind(_config.event,function(){ self._update(); }); }, /* * 載入對應的圖片 */ _eachImg: function(item) { var self = this, _config = self.config, _cache = self.cache; if($(item).attr('isload') == 'false') { var dataImg = $(item).attr('data-'+_config.suffix), src = $(item).attr('src'); $(item).hide(); $(item).attr('src',dataImg); $(item).attr('data-'+_config.suffix,''); $(item)[_config.effect](_config.effectspeed); $(item).attr('isload','true'); } }, _update:function(){ var self = this, _config = self.config, _cache = self.cache; if(_config.container === window) { $('img').each(function(index,item){ // 如果圖片隱藏的 那麼不強制載入 if(_config.skip_invisible && !$('img').is(":visible")) { return; } if (self._abovethetop(item) || self._leftofbegin(item)) { // 什麼都不處理 } else if (self._belowthefold(item) && self._belowthefold(item)) { self._eachImg(item); } }) }else { $('img',$(_config.container)).each(function(index,item){ // 如果圖片隱藏的 那麼不強制載入 if(_config.skip_invisible && !$('img').is(":visible")) { return; } if (self._abovethetop(item) || self._leftofbegin(item)) { } else if (self._belowthefold(item) && self._rightoffold(item)) { self._eachImg(item); } }) } }, /* * 往下滾動時 判斷待載入的元素是否在可視區域內 * @return {Boolean} */ _belowthefold: function(elem){ var self = this, _config = self.config; var fold; if(_config.container === window) { fold = $(window).height() + $(window).scrollTop(); }else { fold = $(_config.container).offset().top + $(_config.container).height(); } return fold >= $(elem).offset().top - _config.threshold; }, /* * 往右滾動時 判斷待載入的元素是否在可視區域內 * @return {Boolean} */ _rightoffold: function(elem){ var self = this, _config = self.config; var fold; if(_config.container === window) { fold = $(window).width() + $(window).scrollLeft(); }else { fold = $(_config.container).offset().left + $(_config.container).width(); } return fold >= $(elem).offset().left - _config.threshold; }, /* * 往上滾動 * @return {Boolean} */ _abovethetop: function(elem){ var self = this, _config = self.config; var fold; if(_config.container === window) { fold = $(window).scrollTop(); }else { fold = $(_config.container).offset().top; } return fold >= $(elem).offset().top + _config.threshold + $(elem).height(); }, /* * 往左滾動 * @return {Boolean} */ _leftofbegin: function(elem) { var self = this, _config = self.config; var fold; if (_config.container === window) { fold = $(window).scrollLeft(); } else { fold = $(_config.container).offset().left; } return fold >= $(elem).offset().left + _config.threshold + $(elem).width(); } }; // 初始化的方式 $(function(){ var datalazy = new DataLazyLoad({ container: '#demo' }); });
初始化方式如下:
// 初始化的方式 $(function(){ var datalazy = new DataLazyLoad({ container: '#demo' }); });
也可以根據自己自動配置。