標籤:屬性 一個 顯示 多行 計算 設定 ret 一段 logs
最近不是在學習設計模式嗎,然後就看到了代理模式載入圖片的範例,然後自己實現了一下,就發現,自己寫的這貨每次就只能載入一張圖片,而且圖片要放在哪也是個很嚴重的問題
然後就去了 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,添加一個新的setTimoutvar 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源碼學習