1. 程式人生 > >圖片懶加載庫echo.js源碼學習

圖片懶加載庫echo.js源碼學習

流行 cal 特性 document 視圖 背景 != 之前 attribute

最近不是在學習設計模式嗎,然後就看到了代理模式加載圖片的樣例,然後自己實現了一下,就發現,自己寫的這貨每次就只能加載一張圖片,而且圖片要放在哪也是個很嚴重的問題

然後就去了 gayhub 找了找了找流行的圖片懶加載庫,這一找,就找到了一個echo.j是,打開一看,源碼只有100多行吧,震驚。。,看完源碼,哎,木有上代理模式呀

仔細學習了下源碼:覺得這種做法比較適合圖片位置確定場景的吧,比如文章啊,一篇文章老長了,裏面有蠻多圖片散落在不同的地方,這樣就比較合適,有可能有很多圖片讀者都不會翻到哪裏,加載下來就浪費了

關鍵點:

1.如何判斷元素距離出現在視野裏的長度還有多少?以常見鼠標往下滾動,圖片在下面為例

          技術分享

靈魂畫手哈哈,,,;H1是視窗的高度,window.innerHeight可以獲得,H2就是提供給使用者設置的offsetBottom

然後祭出一個大招!element.getBoundingClientRect(),就能得到元素相對於視窗的四個距離

            技術分享

var H=Element.getboundingclientrect().top;
var flag=H-(H1+H2);//當flag值小於0就代表可以開始加載圖片了

  那麽,看看源碼裏面是怎麽寫的:

var offset = {//四個值由用戶傳入決定,默認為0
      t: ,
      b:,
      l: ,
      r:
};
var   view = {  //計算鄰界的距離
      l: 0 - offset.l,
      t: 0 - offset.t,
      b: (root.innerHeight || document.documentElement.clientHeight) + offset.b,
      r: (root.innerWidth || document.documentElement.clientWidth) + offset.r
};
 var isHidden = function (element) {
    return (element.offsetParent === null);  //element.offsetParent 表示父元素,如果為null證明沒有在添加到DOM裏面,或者position值為fixed
  };
  
  var inView = function (element, view) {  //判斷是否在視圖中調用這個函數判斷
    if (isHidden(element)) {  //判斷是否在界面上
      return false;
    }

    var box = element.getBoundingClientRect();  //計算四邊的距離是否滿足條件
    return (box.right >= view.l && box.bottom >= view.t && box.left <= view.r && box.top <= view.b);
  };

  

2.已經有了是否加載的判斷函數,那麽如何做到圖片的懶加載?

先加載loadding小菊花圖片,當滿足懶加載的條件時候,切換img的src屬性,

對於img元素的設置有兩個比較重要的值一個是src,一個是data-echo ,(還有一個是背景圖片,不太重要,忽略他)兩個,src設置小菊花的地址,data-echo真實的地址;

那麽所有頁面元素都這樣設置後,會有什麽影響?

當所有圖片都用設置src為同一值,也就是用同一張菊花圖,加載完之後就可以通用了

img這個元素的特性就是,當設置了src屬性,他會去先加載這張圖圖片,如果在js裏面馬上改變了img的src屬性,他會同事再進行一次網絡請求去加載你js設置的src地址的圖片

但是 會先將html裏面設置的src圖片加載完,顯示,你什麽時候加載完第二個圖片什麽時候替換,如果你在第二張圖片加載的時候又改變了src的值,,,那也是一樣的,什麽加載完什麽時候顯示,沒加載完的情況下顯示原來的

源代碼:

  if (inView(elem, view)) {//是否滿足加載條件

        if (unload) {//如果設置超出了不加載,保存小菊花地址在data-echo-placeholder屬性
          elem.setAttribute(‘data-echo-placeholder‘, elem.src);
        }

        if (elem.getAttribute(‘data-echo-background‘) !== null) {//img的背景圖片
          elem.style.backgroundImage = ‘url(‘ + elem.getAttribute(‘data-echo-
background‘) + ‘)‘;
        }
        //當ele的src不等於data-echo的值,也就是真蒸的圖片地址,改變圖片的src
        else if (elem.src !== (src = elem.getAttribute(‘data-echo‘))) {
          elem.src = src;
        }

        if (!unload) { //如果沒有設置超出不加載,在這裏就可以清除這些屬性了
          elem.removeAttribute(‘data-echo‘);
          elem.removeAttribute(‘data-echo-background‘);
        }

        callback(elem, ‘load‘);
      }
      else if (unload && !!(src = elem.getAttribute(‘data-echo-placeholder‘))) {
     //處理超出不加載圖片的情況,把原來保存的小菊花圖賦給elem的src
    //因為小菊花是最開始就加載好了的,所以圖片切換回小菊花,不再加載之前設置的真實圖片
        if (elem.getAttribute(‘data-echo-background‘) !== null) {
          elem.style.backgroundImage = ‘url(‘ + src + ‘)‘;
        }
        else {
          elem.src = src;
        }

        elem.removeAttribute(‘data-echo-placeholder‘); 
        callback(elem, ‘unload‘);
      }
    }
    if (!length) {
      echo.detach();//移除事件監聽
    }

  

3,scroll函數節流

函數節流,兩種方式:

1:在滾動的時候不會觸發,滾動停下來才會隔一段時間觸發

2:每隔一段事件都觸發

//第一種方式,每次滾動過程中一直觸發,每次都會新清除上一次的setTimout,添加一個新的setTimout
var poll;
function throttle(){ 
 clearTimeout(poll);
 poll=setTimeout(function(){
    echo.render();
 },delay||250) 
}

  

  

var poll;
function throttle(){ if(poll){ //存在setTimout,不清除,直接返回 return ; } clearTimout(poll); poll=setTimeout(function(){ echo.render(); poll=null; //允許再次添加定時器 },delay||250) }

  

圖片懶加載庫echo.js源碼學習