1. 程式人生 > >圖片瀑布流實現

圖片瀑布流實現

實現思路:圖片寬度一定,高度不同,下一行的第一張圖片放在高度最小的圖片的下方,以此類推。

 實現程式碼:

html程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>js實現瀑布流效果</title>
    <link href="css/index.css" rel="stylesheet">
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"
></script> </head> <body> <div id="container"> <div class="box"> <div class="pic"> <img src="images/01.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/02.jpg"
> </div> </div> <div class="box"> <div class="pic"> <img src="images/03.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/04.jpg"> </div>
</div> <div class="box"> <div class="pic"> <img src="images/05.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/06.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/01.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/02.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/03.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/04.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/05.jpg"> </div> </div> <div class="box"> <div class="pic"> <img src="images/06.jpg"> </div> </div> </div> <script src="js/index.js"></script> </body> </html>

JavaScript程式碼:

var parent = document.getElementById('container');
function WaterFall() {
    imgLocation('box');
    const data = [{'img':'01.jpg'},{'img':'02.jpg'},{'img':'03.jpg'},
        {'img':'04.jpg'},{'img':'05.jpg'},{'img':'06.jpg'},{'img':'07.jpg'},
        {'img':'08.jpg'},{'img':'09.jpg'},{'img':'10.jpg'},{'img':'11.jpg'},
        {'img':'12.jpg'},{'img':'13.jpg'},{'img':'14.jpg'},{'img':'15.jpg'},
        {'img':'16.jpg'},{'img':'17.jpg'},{'img':'01.jpg'},{'img':'02.jpg'},
        {'img':'03.jpg'},{'img':'04.jpg'},{'img':'05.jpg'},{'img':'06.jpg'},
        {'img':'07.jpg'},{'img':'08.jpg'},{'img':'09.jpg'},{'img':'10.jpg'},
        {'img':'11.jpg'},{'img':'12.jpg'},{'img':'13.jpg'},{'img':'14.jpg'},
    ];
    window.addEventListener('scroll',()=>{
        if (checkLoading('box')){
            //載入新的圖片
            data.map((current)=>{
                const newBox = document.createElement('div');
                newBox.className = 'box';
                parent.appendChild(newBox);
                const newPic = document.createElement('div');
                newPic.className = 'pic';
                newBox.appendChild(newPic);
                const newImg = document.createElement('img');
                newImg.src = 'images/'+current.img;
                newPic.appendChild(newImg);
            });
            imgLocation('box');
        }
    });
}


function checkLoading(child){
    const content = getChilds(child);
    const lastTop = content[content.length - 1].offsetTop;
    const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    const pageTop = document.body.clientHeight || document.documentElement.clientHeight;
    if ((scrollTop + pageTop > lastTop) ||(scrollTop == 0 && lastTop < pageTop)){
        return true;
    }
}


function imgLocation(child){
    const content = getChilds(child);
    const imgWidth = content[0].offsetWidth;
    const num = Math.floor(document.body.clientWidth / imgWidth);
    //讓圖片靈活居中
    parent.style.cssText = 'width:'+ imgWidth * num + 'px;margin:0 auto;';
    //計算圖片的高度
    const heightArr = [];
    [].map.call(content,(current,index)=>{
        if (index < num){
            heightArr.push(current.offsetHeight);
        } else {
            //得到圖片的最小高度
            const minHeight = Math.min(...heightArr);
            //得到最小高度的序列號
            const minIndex = getMinIndex(minHeight,heightArr);
            current.style.position = 'absolute';
            current.style.top = minHeight + 'px';
            current.style.left = content[minIndex].offsetLeft + 'px';
            //更新最小的高度
            heightArr[minIndex] += current.offsetHeight;
        }
    });
}

//將父級元素下的所有符合條件的子元素獲取
function getChilds(child){
    const childArr = [];
    const tagsAll = parent.getElementsByTagName('*');
    [].map.call(tagsAll,(current)=>{
        if (current.className == child){
            childArr.push(current);
        }
    });
    return childArr;
}

function getMinIndex(minHeight,heightArr){
    for (const i in heightArr){
        if (minHeight == heightArr[i]){
            return i;
        }
    }
}

window.addEventListener('load',WaterFall());

 

結果:執行成功。

程式設計的時候出現的報錯:

報錯1:Uncaught TypeError: Cannot read property 'getElementsByTagName' of null

原因:頁面的載入順序問題,將script新增到body的後面

報錯2:HTMLCollection []問題

原因:在獲取container下的所有節點的時候,const tagsAll = parent.getElementsByTagName('*'); 得到的是HTMLCollection,它不是陣列,會動態改變。

所以採用以下程式設計方法:

[].map.call(tagsAll,(current)=>{
        if (current.className == child){
            childArr.push(current);
        }

 

待完善的:

視窗大小改變的時候,在不用重新整理的情況下圖片自動更改適應瀑布流

使用ajax請求圖片資料

在點選相應的圖片的時候,背景變暗,被點選的圖片被放大。

非同步請求資料的時候,如果未知圖片的高度,怎麼辦?

移動端的優化。