js圖片加載效果(延遲加載+瀑布流加載)

主要作了兩種圖片加載的效果
一種是遇到頁面圖片比較多的時候,帶讀條效果的加載提示(爲了驗證正確加載,設置了1秒鐘的加載間隔時間)
另一種是根據滑塊的位置進行圖片的預加載,在用戶不察覺的狀況下,實現瀑布流的加載效果css

一 延遲加載

主要思路:html

  1. HTML的img標籤中,將正確的地址存在data-src屬性中,給全部圖片設置一個轉圈圈的loading圖片做爲backgroundjquery

  2. js中,依次讀取每個img,將data-src中的地址替換到src中,去掉backgroundc++

  3. 每成功加載一張圖片,進度條的百分比進行相應的變化。json

  4. 若是加載不成功,就提示圖片加載錯誤。瀏覽器


HTML結構很簡單,就是一個div.picList包裹了全部img,而後加上一個簡單的進度條div#loadBarapp

<body>
    <div class="picList">
        <img class="lazy" data-src="pic/compressed/picList1.jg">
        <img class="lazy" data-src="pic/compressed/picList2.jpg">
        <img class="lazy" data-src="pic/compressed/picList3.jpg">
        <img class="lazy" data-src="pic/compressed/picList4.jpg">
        <img class="lazy" data-src="pic/compressed/picList5.jpg">
        <img class="lazy" data-src="pic/compressed/picList6.jpg">
        <img class="lazy" data-src="pic/compressed/picList7.jpg">
        <img class="lazy" data-src="pic/compressed/picList8.jpg">
        <img class="lazy" data-src="pic/compressed/picList9.jpg">
        <img class="lazy" data-src="pic/compressed/picList10.jpg">
    </div>

    <div id="loadBar">
        <div id="loadBarMask"></div>
    </div>
</body>

css(使用的scss,編譯時會自動加上各類兼容前綴)ide

.picList{
    img{
        width: 100px;
        height: 100px;
        position: relative;

        /*加載失敗時顯示灰底文字*/
        &:after{
            content: "( ⊙ o ⊙ )加載失敗";
            font-size: 6px;
            font-family: FontAwesome;
            color: rgb(100, 100, 100);
            display: flex;
            justify-content: center;
            align-items: center;
            position: absolute;
            top: 0;
            left: 0;
            width: 100px;
            height: 100px;
            background-color: #ddd;
        }
    }
}

.lazy{
    background: url(../pic/loading.gif) center no-repeat;
    border: 1px solid black;
}

#loadBar{
    width: 200px;
    height: 15px;
    background: linear-gradient(90deg,#187103,#81b50b,#187103);
    border: 10px solid white;

    position: absolute;
    top: 150px;
    left: 50%;
    margin-left: -100px;

    #loadBarMask{
        width: 70%;//這個數值顯示沒有加載成功的圖片
        height: 100%;
        background-color: beige;
        position: absolute;
        right: 0;
    }
}

css裏面須要注意的地方有兩個:flex

  • 一個是把圖片加載錯誤時顯示的灰底文字放在了img的after僞類中,當圖片加載失敗,又去掉了background的gif圖片以後,就會顯示這個部分的內容及樣式。動畫

  • 一個是進度條的樣式。寫得很簡單,主要是一層帶漸變的綠色和一層白色疊在一塊兒。綠色表示已加載,白色表示未加載。顯示的時候,直接控制白色那層的寬度便可。

js部分(直接執行loadPicPerSecond()便可)

var lazyPic = $('img.lazy');
var loadBarMask = $('#loadBarMask');
var picList = $('.picList');

var activePic = 0;
var totalPic = lazyPic.length;

/*每秒加載一張圖片*/

function loadPicPerSecond(){

    lazyPic.each(function(index){

        var self = $(this);

        //console.log(self[0].complete);
        /*img標籤已經事先寫在html中,因此此時的complete狀態所有都是true*/

        setTimeout(function(){

            src[index] = self.attr('data-src');
            self.attr('src',src[index]);
            self.removeClass('lazy');

            //圖片得到正確src地址以後,能夠執行下面的onload操做
            self[0].onload = function(){

                //加載讀條loadBar動畫
                countPic();
            }

            //圖片得到的src地址不正確時,執行下面的onerror操做
            self[0].onerror = function(){
                /*this.style.background = 'url(pic/compressed/picList18.jpg) center no-repeat';*/
                countPic();
            }

        },1000*index);

    })

}

/*根據onload的執行狀況來計算當前的圖片加載進度.每onload一次,activePic就增長1*/

function countPic(){

    activePic++;

    var leftPic = totalPic - activePic;
    var percentPic = Math.ceil(leftPic/totalPic*100);//沒有加載的圖片百分比,和loadBarMask的寬度佔比配合

    console.log("已加載"+(100-percentPic)+"%");

    loadBarMask.css("width",percentPic+"%");

    if(percentPic==0){
        $('#loadBar').hide();
    }
}

二 瀑布流加載

主要思路:

  1. 監聽窗口滾動狀況,當已經加載的圖片的最後一張快要進入窗口的時候,開始加載下面的圖片。

  2. 假設全部的圖片地址已經存在一個json數據中,每次讀取10張圖片地址,加載它們以後,插入到現有的瀑布流末尾。

  3. 如此往復,直到加載完全部圖片。


HTML和前面部分相同,只是把src寫成正常地址便可。
css徹底同樣。

js部分

var lazyPic = $('img.lazy');
var loadBarMask = $('#loadBarMask');
var picList = $('.picList');

var scrollTop,
    clientHeight,
    scrollHeight;

var threshold = 200; //最後一張圖片距離窗口200px的時候開始加載圖片

var src = [];

var activePic = 0;
var totalPic = lazyPic.length;

//待加載的圖片數據
var dirtSrc = "pic/compressed/picList";
var picData = {imgSrc:[
    dirtSrc + "20.jpg",
    dirtSrc + "21.jpg",
    dirtSrc + "22.jpg",
    dirtSrc + "23.jpg",
    dirtSrc + "24.jpg",
    dirtSrc + "25.jpg",
    dirtSrc + "26.jpg",
    dirtSrc + "27.jpg",
    dirtSrc + "28.jpg",
    dirtSrc + "29.jpg",
    dirtSrc + "30.jpg",
    dirtSrc + "31.jpg",
    dirtSrc + "32.jpg",
    dirtSrc + "33.jpg",
    dirtSrc + "34.jpg",
    dirtSrc + "35.jpg",
    dirtSrc + "36.jpg",
    dirtSrc + "37.jpg",
    dirtSrc + "38.jpg",
    dirtSrc + "39.jpg",
    dirtSrc + "40.jpg",
    dirtSrc + "41.jpg",
    dirtSrc + "42.jpg",
    dirtSrc + "43.jpg",
    dirtSrc + "44.jpg",
    dirtSrc + "45.jpg",
    dirtSrc + "46.jpg",
    dirtSrc + "47.jpg",
    dirtSrc + "48.jpg",
    dirtSrc + "49.jpg",
]};

//加載次數計數器
var scrollIndex = 0;

$(function(){

    /*監聽窗口滾動狀況*/
    $(window).on('scroll',function(){

        scrollTop = $(window).scrollTop();//$(window).scrollTop()==document.body.scrollTop
        clientHeight = $(window).height();
        scrollHeight = picList.last().height();//picList.last()[0].clientHeight

        /*目標與窗口的距離達到閾值時開始加載*/
        if(scrollHeight-clientHeight-scrollTop < threshold){
            scrollPic(10);
        }
    })
})

/*根據滾動程度加載圖片,每次加載perAmount張*/

function scrollPic(perAmount = 10){

    var totalAmount = perAmount * (scrollIndex+1);

     //考慮到最後一次加載的時候,剩餘的圖片數量有可能達不到限定的每次加載的數量,這時候須要更改totalAmount的值
    if(totalAmount>picData.imgSrc.length){
        totalAmount = picData.imgSrc.length;
    }
    for(scrollIndex;scrollIndex<totalAmount;scrollIndex++){
        var oimg = new Image();
        oimg.src = picData.imgSrc[scrollIndex];
        picList.append(oimg);
    }

}

比較捉急的就是scrollTop、height那幾個值的取值對象,老是記不清楚,因此按照js和jquery都寫上了,之後能夠直接用。將數值關係搞定以後,只要知足條件就觸發加載便可。

三 後記·兼容性問題

拿到IE8之下運行時,發現img.onload後面的function打死都不執行,IE8智障到不能完成 img.onload = function(){}這麼初級的代碼麼?
去查了資料以後,發現IE8雖然白癡,但還算沒有智障到無藥可救。
onload是能夠調用的,可是要放在src的賦值以前。

簡單來講,就是要先告訴瀏覽器圖片加載完要怎麼處理,再讓它去加載圖片。避免由於加載緩衝區的速度太快,在沒有告訴它加載完要怎麼辦時,它已經加載完了。而其它瀏覽器則是從緩衝區讀取到圖片時就執行onload。

相關文章
相關標籤/搜索