天天看點

[轉]javascript 懶加載技術(lazyload)簡單實作

1.前言

2.lazyload在什麼場合中應用比較合适?

   涉及到圖檔,falsh資源 , iframe, 網頁編輯器(類似FCK)等占用較大帶寬,且這些子產品暫且不在浏覽器可視區内,是以可以使用lazyload在适當的時候加載該類資源.避免網頁打開時加載過多資源,讓使用者等待太久.

3.如何實作lazyload?

   lazyload的難點在如何在适當的時候加載使用者需要的資源(這裡使用者需要的資源指該資源呈現在浏覽器可視區域)。是以我們需要知道幾點資訊來确定目标是否已呈現在客戶區,其中包括:

     1.可視區域相對于浏覽器頂端位置

     2.待加載資源相對于浏覽器頂端位置.

   在得到以上兩點資料後,通過如下函數,便可得出某對象是否在浏覽器可視區域了.

    //傳回浏覽器的可視區域位置

    function getClient(){

       var l,t,w,h;

       l  =  document.documentElement.scrollLeft || document.body.scrollLeft;

       t  =  document.documentElement.scrollTop || document.body.scrollTop;

       w =   document.documentElement.clientWidth;

       h =   document.documentElement.clientHeight;

       return {'left':l,'top':t,'width':w,'height':h} ;

    }

    //傳回待加載資源位置

    function getSubClient(p){

       var l = 0,t = 0,w,h;

       w = p.offsetWidth ;

       h = p.offsetHeight;

       while(p.offsetParent){

        l += p.offsetLeft ;

        t += p.offsetTop ;

        p = p.offsetParent;

     }

     return {'left':l,'top':t,'width':w,'height':h } ;

  }

    其中 函數 getClient()傳回浏覽器客戶區區域資訊,getSubClient()傳回目标子產品區域資訊。此時确定目标子產品是否出現在客戶區實際上是确定如上兩個矩形是否相交.

    //判斷兩個矩形是否相交,傳回一個布爾值

    function intens(rec1,rec2){

       var lc1,lc2,tc1,tc2,w1,h1;

       lc1 = rec1.left + rec1.width / 2;

       lc2 = rec2.left + rec2.width / 2;

       tc1 = rec1.top + rec1.height / 2 ;

       tc2 = rec2.top + rec2.height / 2 ;

       w1 = (rec1.width + rec2.width) / 2 ;

       h1 = (rec1.height + rec2.height) / 2;

       return Math.abs(lc1 - lc2) < w1 && Math.abs(tc1 - tc2) < h1 ;

    現在基本上可以實作延時加載了,接下來,我們在 window.onscroll 事件中編寫一些代碼監控目标區域是否呈現在客戶區.

     <div style = "width:100px; height:3000px"></div>

   <div id  = "d1" style = "width:50px; height:50px; background:red;position:absolute; top:1000px">

   </div>

    var d1 = document.getElementById("d1");

    window.onscroll = function(){

       var prec1 = getClient(); 

       var prec2 =  getSubClient(d1);

        if(intens(prec1,prec2)){

          alert("true")

        }

    }

   我們隻需要在彈出視窗的地方加載我們需要的資源.

   這裡值得注意的是:目标對象呈現在客戶區域時,會随着滾動而不斷的彈出視窗.是以我們需要在彈出第一個視窗後取消對該區域的監測,這裡用一個數組來收集需要監測的對象,同時将監測的邏輯抽出來。同時需要注意 onscroll事件和onresize事件都會改變遊覽器可視區域資訊,是以在該類事件觸發後需要重新計算,這裡用autocheck()函數實作.(迅雷首頁的lazyload沒有在onresize事件中重新計算目标對象是否在浏覽器可視區域,是以如果先将浏覽器視窗縮小到一定尺寸後滾動到需要加載圖檔的區域後點選最大化,圖檔加載不出來,呵呵,以後需要注意了).

   增加元素:<div id  = "d2" style = "width:50px; height:50px; background:blue;position:absolute; top:2500px">

    //比較某個子區域是否呈現在浏覽器區域

    function jiance(arr,prec1,callback){

      var prec2;

      for(var i = arr.length - 1 ; i >= 0 ;i--){

        if(arr[i]){

         prec2 =  getSubClient(arr[i]);

         if(intens(prec1,prec2)){

            callback(arr[i]);

            //加載資源後,删除監測

            delete arr[i];

           }

        }

      }

    //檢測目标對象是否出現在客戶區

    function autocheck(){

       var prec1 = getClient(); 

       jiance(arr,prec1,function(obj){

      //加載資源...

        alert(obj.innerHTML)

       })

    //子區域一   

    //子區域二

    var d2 = document.getElementById("d2");

   //需要按需加載區域集合

    var arr = [d1,d2];

     //重新計算

       autocheck();

    window.onresize = function(){

     //重新計算

   現在我們隻需要在彈窗的地方加載我們需要的資源了.源碼就不貼出來了.如果需要的朋友,或着存在疑問的地方,可以聯系我.

本文轉自王磊的部落格部落格園部落格,原文連結:http://www.cnblogs.com/vipstone/archive/2011/01/17/1937055.html,如需轉載請自行聯系原作者

繼續閱讀