實現圖片的預加載和懶加載


延遲加載也稱為惰性加載,即在長網頁中延遲加載圖像。用戶滾動到它們之前,視口外的圖像不會加載。這與圖像預加載相反,在長網頁上使用延遲加載將使網頁加載更快。在某些情況下,它還可以幫助減少服務器負載。

那么延遲加載有什么好處:
1、提升用戶的體驗,避免出現卡頓現象。
2、有選擇性地請求圖片,減少服務器的壓力和流量,減小瀏覽器的負擔。

 實現方式:
1、首先將頁面上的圖片的 src 屬性設為 loading.gif,而圖片的真實路徑則設置在 data-src 屬性中,頁面滾動的時候計算圖片的位置與滾動的位置,當圖片出現在瀏覽器視口內時,將圖片的 src 屬性設置為 data-src 的值,這樣,就可以實現延遲加載

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>Lazyload 1</title>
    <style>
        img {
        display: block;
        margin-bottom: 50px;
        height: 200px;
    }
    </style>
</head>
<body>
    <img src="images/loading.gif" data-src="images/1.png">
    <img src="images/loading.gif" data-src="images/2.png">
    <img src="images/loading.gif" data-src="images/3.png">
    <img src="images/loading.gif" data-src="images/4.png">
    <img src="images/loading.gif" data-src="images/5.png">
    <img src="images/loading.gif" data-src="images/6.png">
    <img src="images/loading.gif" data-src="images/7.png">
    <img src="images/loading.gif" data-src="images/8.png">
    <img src="images/loading.gif" data-src="images/9.png">
    <img src="images/loading.gif" data-src="images/10.png">
    <img src="images/loading.gif" data-src="images/11.png">
    <img src="images/loading.gif" data-src="images/12.png">
    <script>
        function lazyload() {
        var images = document.getElementsByTagName('img');
        var len    = images.length;
        var n      = 0;      //存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷        
        return function() {
        var seeHeight = document.documentElement.clientHeight;
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        for(var i = n; i < len; i++) {
            if(images[i].offsetTop < seeHeight + scrollTop) {
                if(images[i].getAttribute('src') === 'images/loading.gif') {
                 images[i].src = images[i].getAttribute('data-src');
            }
            n = n + 1;
             }
        }
        }
    }
    var loadImages = lazyload();
    loadImages();          //初始化首頁的頁面圖片
    window.addEventListener('scroll', loadImages, false);
    </script>
</body>
</html>

不斷滑動頁面時,圖片延遲加載。 image 的 offsetTop 與 seeHeight + scrollTop 的大小,當小於時則說明圖片已經出現過在視口中,這時候繼續判斷圖片是否已經替換過,如果沒有替換過,則進行替換。

上面的代碼是沒什么問題,但是性能偏差。如果直接將函數綁定在 scroll 事件上,當頁面滾動時,函數會被高頻觸發,這非常影響瀏覽器的性能。我粗略地估計一下,當簡單地滾動一下頁面,函數至少觸發了十來次,這顯然是十分沒必要的。

2、所以在做事件綁定的時候,可以對 lazyload 函數進行函數節流(throttle)與函數去抖(debounce)處理。

Debounce:一部電梯停在某一個樓層,當有一個人進來后,20秒后自動關門,這20秒的等待期間,又一個人按了電梯進來,這20秒又重新計算,直到電梯關門那一刻才算是響應了事件。
Throttle:好比一台自動的飲料機,按拿鐵按鈕,在出飲料的過程中,不管按多少這個按鈕,都不會連續出飲料,中間按鈕的響應會被忽略,必須要等這一杯的容量全部出完之后,再按拿鐵按鈕才會出下一杯。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lazyload 2</title>
    <style>
    img {
        display: block;
        margin-bottom: 50px;
        height: 200px;
    }
    </style>
</head>
<body>
    <img src="images/loading.gif" data-src="images/1.png">
    <img src="images/loading.gif" data-src="images/2.png">
    <img src="images/loading.gif" data-src="images/3.png">
    <img src="images/loading.gif" data-src="images/4.png">
    <img src="images/loading.gif" data-src="images/5.png">
    <img src="images/loading.gif" data-src="images/6.png">
    <img src="images/loading.gif" data-src="images/7.png">
    <img src="images/loading.gif" data-src="images/8.png">
    <img src="images/loading.gif" data-src="images/9.png">
    <img src="images/loading.gif" data-src="images/10.png">
    <img src="images/loading.gif" data-src="images/11.png">
    <img src="images/loading.gif" data-src="images/12.png">
    <script>
    function throttle(fn, delay, atleast) {
        var timeout = null,
        startTime = new Date();
        return function() {
        var curTime = new Date();
        clearTimeout(timeout);
        if(curTime - startTime >= atleast) {
            fn();
            startTime = curTime;
        }else {
            timeout = setTimeout(fn, delay);
        }
        }
    }
    function lazyload() {
        var images = document.getElementsByTagName('img');
        var len    = images.length;
        var n      = 0;      //存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷        
        return function() {
        var seeHeight = document.documentElement.clientHeight;
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        for(var i = n; i < len; i++) {
            if(images[i].offsetTop < seeHeight + scrollTop) {
                if(images[i].getAttribute('src') === 'images/loading.gif') {
                 images[i].src = images[i].getAttribute('data-src');
                }
            n = n + 1;
             }
        }
        }
    }
    var loadImages = lazyload();
    loadImages();          //初始化首頁的頁面圖片
    window.addEventListener('scroll', throttle(loadImages, 500, 1000), false);
    </script>
</body>
</html>
View Code

設置了 500ms 的延遲,和 1000ms 的間隔,當超過 1000ms 未觸發該函數,則立即執行該函數,不然則延遲 500ms 執行該函數。

 

預加載圖片是提高用戶體驗的一個很好方法。圖片預先加載到瀏覽器中,訪問者便可順利地在你的網站上沖浪,並享受到極快的加載速度。這對圖片畫廊及圖片占據很大比例的網站來說十分有利,它保證了圖片快速、無縫地發布,也可幫助用戶在瀏覽你網站內容時獲得更好的用戶體驗。

1、用CSS和JavaScript實現預加載

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

將這三個ID選擇器應用到(X)HTML元素中,我們便可通過CSS的background屬性將圖片預加載到屏幕外的背景上。只要這些圖片的路徑保持不變,當它們在Web頁面的其他地方被調用時,瀏覽器就會在渲染過程中使用預加載(緩存)的圖片。簡單、高效,不需要任何JavaScript。
該方法雖然高效,但仍有改進余地。使用該法加載的圖片會同頁面的其他內容一起加載,增加了頁面的整體加載時間。為了解決這個問題,我們增加了一些JavaScript代碼,來推遲預加載的時間,直到頁面加載完畢。代碼如下:

function preloader() {
    if (document.getElementById) {
        document.getElementById("preload-01").style.background = "url() no-repeat -9999px -9999px";
        document.getElementById("preload-02").style.background = "url() no-repeat -9999px -9999px";
        document.getElementById("preload-03").style.background = "url() no-repeat -9999px -9999px";
    }
}
function addLoadEvent(func) {
    var oldonload = window.onload;   //獲得window.onload的內容
    if (typeof window.onload != 'function') { //判斷windown.onload是否為函數。如果不是函數,則執行自己的函數,如果是函數,則先執行已經賦值的函數,再執行自己的函數
        window.onload = func;
    } else {
        window.onload = function() {
            if (oldonload) {
                oldonload();
            }
            func();
        }
    }
}
addLoadEvent(preloader);

2、純JavaScript實現,與Css實現相比,會減少時間

function preloader() {
    if (document.images) {
        var img1 = new Image();
        var img2 = new Image();
        var img3 = new Image();
        img1.src = ";;
        img2.src = ";;
        img3.src = ";;
    }
}
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);
 

3、使用Ajax實現預加載

上面所給出的方法似乎不夠酷,那現在來看一個使用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', ';);
        xhr.send('');
        xhr = new XMLHttpRequest();
        xhr.open('GET', ';);
        xhr.send('');
        // preload image
        new Image().src = ";;
    }, 1000);
};
 

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

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 = ";;
 
        // a new JS
        var js  = document.createElement("script");
        js.type = "text/javascript";
        js.src  = ";;
 
        // preload JS and CSS
        head.appendChild(css);
        head.appendChild(js);
 
        // preload image
        new Image().src = ";;
 
    }, 1000);
 
};
 

 


免責聲明!

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



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