图片瀑布流实现

实现思路:图片宽度必定,高度不一样,下一行的第一张图片放在高度最小的图片的下方,以此类推。css

 实现代码:html

html代码:jquery

<!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代码:ajax

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 app

缘由:页面的加载顺序问题,将script添加到body的后面 异步

报错2:HTMLCollection []问题 优化

缘由:在获取container下的全部节点的时候,const tagsAll = parent.getElementsByTagName('*'); 获得的是HTMLCollection,它不是数组,会动态改变。spa

因此采用如下编程方法:

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

 

待完善的:

窗口大小改变的时候,在不用刷新的状况下图片自动更改适应瀑布流

使用ajax请求图片数据

在点击相应的图片的时候,背景变暗,被点击的图片被放大。

异步请求数据的时候,若是未知图片的高度,怎么办?

移动端的优化。