[前端]圖片預加載方法


  目錄

  1. 使用jQuery圖片預加載(延遲加載)插件Lazy Load
  2. 使用JS實現圖片預加載
  3. 使用CSS實現圖片預加載
  4. 使用Ajax實現圖片預加載

1. 使用jQuery圖片預加載(延遲加載)插件Lazy Load

Lazy Load也叫惰性加載,延遲加載,顧名思義,就是在圖片未到達可視區域時,不加載圖片,我們常常在很多的優秀網站上看到類似的例子,例如迅雷、土豆、優酷等,由於一個網頁的圖片非常多,一次性加載增加服務器壓力,而且用戶未必會拉到底部,浪費用戶流量,Lazy Load采用按需加載,更快的加載速度從而達到優化網頁的目的。

使用方法:

  • 加載jQuery, 並在html代碼的底部包含進來

    <script src="jquery.js" type="text/javascript"></script>
    <script src="jquery.lazyload.js" type="text/javascript"></script>
  • 設置圖片的占位符為data-original, 給圖片一個特別的標簽, 像這樣設置圖片

    <img class="lazy" data-original="img/example.jpg" width="640" height="480">
    $(function(){ 
        $("img.lazy").lazyload(); 
    });

    注意:你必須給圖片設置一個height和width,或者在CSS中定義,否則可能會影響到圖片的顯示。

  • 插件選項

    圖片預先加載距離:threshold,通過設置這個值,在圖片未出現在可視區域的頂部距離這個值時加載。默認為0,下面為設置threshold為200表示在圖片距離可視區域還有200像素時加載。
    $("img.lazy").lazyload({
        threshold :200
    });

    事件綁定加載的方式:event,你可以使用jQuery的事件,例如“click”、“mouseover”,或者你也可以自定義事件,默認等待用戶滾動,圖片出現在可視區域。下面是使用click:

    $("img.lazy").lazyload({event:"click"});
    

    顯示效果:effect,默認使用show(),你可以使用fadeIn(逐漸出現)方式,代碼如下:

    $("img.lazy").lazyload({
        effect :"fadeIn"
    });
    

    對於禁用javascript的瀏覽器則要加上noscript內容:

    <img class="lazy" data-original="img/example.jpg" width="640" heigh="480">
    <noscript><img src="img/example.jpg" alt="jQuery圖片預加載(延遲加載)插件Lazy Load" width="640" heigh="480"></noscript>

    圖片限定在某個容器內:container,你可以通過限定某個容器內容的圖片才會生效,代碼如下:

    #container {
        height:600px;
        overflow: scroll;
    }
    $("img.lazy").lazyload({
         container: $("#container")
    });  

  原文鏈接: jQuery圖片預加載(延遲加載)插件Lazy Load

2. JS實現圖片預加載

  在瀏覽器渲染圖片的時候, 它獲得圖片的一片區域的時候, 就已經為這張圖片預留了一片空白的區域來填充圖片, 這就是預加載獲得圖片尺寸最原始的使用方法.

  有時候會加載一些在當前頁面沒有用到的圖片,是為了提前加載到緩存里,這樣后面的頁面就可以直接從緩存讀取了。

  加載大圖的時候,我們可以先顯示模糊的縮略圖,等到大圖加載完了,再把縮略圖替換掉,這樣填補了圖片加載期間的空白時間。

  image也有onload和onerror事件,分別是加載完后和加載失敗時執行。

  Image對象是專門用於處理圖片加載的,就相當於內存中的img標簽。

  圖片預加載案例:鼠標移入一張圖片時,換成另一張圖片,移出時換回原來的圖片。正常做法是,鼠標移入的時候,改變圖片的src,但這時就要去加載圖片了,會等待一段時間,這樣體驗不好。預加載的做法是,在頁面加載完,鼠標移入之前就通過Image對象把圖片加載進緩存了,這樣鼠標移入的時候直接從緩存里讀取了,速度很快。

  • 圖片預加載:

        if(document.images){
            var img = new Image();
            img.src = "img/example.jpg";
        }

 

  • 封裝成一個預加載圖片的函數

        //實現圖片的預加載
        function preloadImg(srcArr){
            if(srcArr instanceof Array){
                for(var i=0; i<srcArr.length; i++){
                    var oImg = new Image();
                    oImg.src = srcArr[i];
                }
            }
        }
    
        //預加載圖片
        preloadImg(['image/example.jpg']);  //參數是一個url數組  
  • 使用一個回調函數來獲得圖片的屬性

        function getPreloadImgAttr(url,callback){
            var oImg = new Image(); //創建一個Image對象,實現圖片的預加載
            oImg.src = url;      // 看下一節,其實應當先進行onload的綁定,再賦值給src
            if(oImg.complete){
                //如果圖片已經存在於瀏覽器緩存,直接調用回調函數
                callback.call(oImg);
                return; //直接返回,不再處理onload事件
            }
            oImg.onload = function(){
                //圖片下載完畢時異步調用callback函數
                callback.call(oImg);    
            };
        }
        getPreloadImgAttr('image/example.jpg',function(){
            console.log(this.width, this.height);
        });  
  • 關於預加載圖片的改進

    網上看到一篇博客關於圖片的預加載,你所不知道的, 其中指出以上通用的方法存在一些問題:
    • 創建了一個臨時匿名函數來作為圖片的onload事件處理函數,形成了閉包。

      相信大家都看到過ie下的內存泄漏模式的文章,其中有一個模式就是循環引用,而閉包就有保存外部運行環境的能力(依賴於作用域鏈的實現),所以img.onload這個函數內部又保存了對img的引用,這樣就形成了循環引用,導致內存泄漏。(這種模式的內存泄漏只存在低版本的ie6中,打過補丁的ie6以及高版本的ie都解決了循環引用導致的內存泄漏問題)。

    • 只考慮了靜態圖片的加載,忽略了gif等動態圖片,這些動態圖片可能會多次觸發onload。
    •   改進方法:
      function loadImage(url, callback) {     
          var img = new Image(); //創建一個Image對象,實現圖片的預下載     
          img.onload = function(){
              img.onload = null;
              callback(img);
          }
          img.src = url; 
      }
      

        這樣內存泄漏,動態圖片的加載問題都得到了解決,而且也以統一的方式,實現了callback的調用。
      關於這個方法, 有個疑問是緩存的問題, 在原文里也給出了一些解釋

      經過對多個瀏覽器版本的測試,發現ie、opera下,當圖片加載過一次以后,如果再有對該圖片的請求時,由於瀏覽器已經緩存住這張圖
      片了,不會再發起一次新的請求,而是直接從緩存中加載過來。對於 firefox和safari,它們試圖使這兩種加載方式對用戶透明,同樣
      會引起圖片的onload事件,而ie和opera則忽略了這種同一性,不會引起圖片的onload事件,因此上邊的代碼在它們里邊不能得以實
      現效果。

      但整體來講,仍然應該先進行onload事件的綁定, 再賦值src

  參考:[前端] 圖片預加載及獲取屬性  關於圖片的預加載,你所不知道的

3. 用CSS實現圖片的預加載

  這個概念就是寫一個CSS樣式設置一批背景圖片,然后將其隱藏,這樣你就看不到那些圖片了。那些背景圖片就是你想預載的圖片。

#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }  
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }  
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }

  這里為了隱藏這些圖片, 使用了位置設置為極大的負值的方法. 還可以直接設置 { width: 0; height: 0; display: none};

  該方法雖然高效,但仍有改進余地。使用該法加載的圖片會同頁面的其他內容一起加載,增加了頁面的整體加載時間。為了解決這個問題,我們增加了一些JavaScript代碼,來推遲預加載的時間,直到頁面加載完畢。代碼如下:

// better image preloading @ <a href="http://perishablepress.com/press/2009/12/28/3-ways-preload-images-css-javascript-ajax/">http://perishablepress.com/press/2009/12/28/3-ways-preload-images-css-javascript-ajax/</a>  
function preloader() {  
    if (document.getElementById) {  
        document.getElementById("preload-01").style.background = "url(http://domain.tld/image-01.png) no-repeat -9999px -9999px";  
        document.getElementById("preload-02").style.background = "url(http://domain.tld/image-02.png) no-repeat -9999px -9999px";  
        document.getElementById("preload-03").style.background = "url(http://domain.tld/image-03.png) no-repeat -9999px -9999px";  
    }  
}  
function addLoadEvent(func) {  
    var oldonload = window.onload;  
    if (typeof window.onload != 'function') {  
        window.onload = func;  
    } else {  
        window.onload = function() {  
            if (oldonload) {  
                oldonload();  
            }  
            func();  
        }  
    }  
}  
addLoadEvent(preloader);

  在該腳本的第一部分,我們獲取使用類選擇器的元素,並為其設置了background屬性,以預加載不同的圖片。

  該腳本的第二部分,我們使用addLoadEvent()函數來延遲preloader()函數的加載時間,直到頁面加載完畢。

  如果JavaScript無法在用戶的瀏覽器中正常運行,會發生什么?很簡單,圖片不會被預加載,當頁面調用圖片時,正常顯示即可。

  參考: 純CSS圖片預加載  Javascript圖片預加載詳解

4. 使用Ajax實現預加載

  該方法利用DOM,不僅僅預加載圖片,還會預加載CSS、JavaScript等相關的東西。使用Ajax,比直接使用JavaScript,優越之處在於JavaScript和CSS的加載不會影響到當前頁面。該方法簡潔、高效。

window.onload = function() {  
    setTimeout(function() {  
        // XHR to request a JS and a CSS  
        var xhr = new XMLHttpRequest();  
        xhr.open('GET', 'http://domain.tld/preload.js');  
        xhr.send('');  
        xhr = new XMLHttpRequest();  
        xhr.open('GET', 'http://domain.tld/preload.css');  
        xhr.send('');  
        // preload image  
        new Image().src = "http://domain.tld/preload.png";  
    }, 1000);  
};  

  上面代碼預加載了“preload.js”、“preload.css”和“preload.png”。1000毫秒的超時是為了防止腳本掛起,而導致正常頁面出現功能問題。

  與之相比, 如果用js的話, 要實現以上加載過程則會應用到頁面上. 實現如下

window.onload = function() {  
  
    setTimeout(function() {  
  
        // reference to <head>  
        var head = document.getElementsByTagName('head')[0];  
  
        // a new CSS  
        var css = document.createElement('link');  
        css.type = "text/css";  
        css.rel  = "stylesheet";  
        css.href = "http://domain.tld/preload.css";  
  
        // a new JS  
        var js  = document.createElement("script");  
        js.type = "text/javascript";  
        js.src  = "http://domain.tld/preload.js";  
  
        // preload JS and CSS  
        head.appendChild(css);  
        head.appendChild(js);  
  
        // preload image  
        new Image().src = "http://domain.tld/preload.png";  
  
    }, 1000);  
  
};

 

  這里,我們通過DOM創建三個元素來實現三個文件的預加載。正如上面提到的那樣,使用Ajax,加載文件不會應用到加載頁面上。從這點上看,Ajax方法優越於JavaScript。

  參考: Javascript圖片預加載詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM