JS实现瀑布流效果

先创建好基本的框架,在id为main的div中动态的添加不同尺寸的图片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Pinterest JS</title>
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
    <div id="main">
        <script src="js/index.js"></script>
    </div>
</body>
</html>

如上图定义每个图片元件为一个class为box的div容器,padding-left和padding-top都为10px,内部欠了一个class为image-container的div,padding为10px。内部在放一个img,设宽度为165px。可以先为构思好的整体框架预设样式。

预设css样式

* {
    margin: 0;
    padding: 0;
}

#main {
    position: relative;
}

#main .box {
    padding-left: 10px;
    padding-top: 10px;
    float: left;
}

#main .box .image-container {
    padding: 10px 10px 5px 10px;
    border: 1px solid #CCCCCC;
    border-radius: 2px;
    background-color: white;
    box-shadow: rgba(0,0,0,0.3) 2px 2px 4px;
}

#main .box .image-container img {
    width: 165px;
}

然后使用js动态实现

var boxWidth = 0;//box的宽度
var boxes = null;//所有box的数组
var main = $('main');

createBoxes();//预先创建40个box

window.onload = function () {

    pinterest();//瀑布流布局

    window.onscroll = checkScroll;//监听网页滚动
};

//快捷取id标签的函数
function $(id) {
    return typeof id === 'string' ? document.getElementById(id) : id;
}

//产生box对象的构造函数
function ImageBox(index) {
    var box = document.createElement('div');
    box.className = 'box';
    var imageContainer = document.createElement('div');
    imageContainer.className = 'image-container';
    var image = document.createElement('img');
    box.appendChild(imageContainer);
    imageContainer.appendChild(image);
    image.src = "images/" + index + ".jpg";

    return box;
}

//预先创建40个box
function createBoxes() {
    boxes = [];
    for(var i = 0; i < 40; i++) {
        createABox(i);
    }
}

//创建1个box
function createABox(imageIndex) {
    var box = new ImageBox(imageIndex);
    main.appendChild(box);
    boxes.push(box);

    //获取box的统一宽度
    if(boxWidth == 0)
    {
        boxWidth = box.offsetWidth;
    }
}

//瀑布流算法
//将main的宽度设为浏览器宽度能容纳的图片数乘以图片统一的宽度
//将main设为居中
function pinterest() {
    var boxHeightsInRow = [];
    var countInRow = Math.floor(window.innerWidth / boxWidth);
    main.style.width = countInRow * boxWidth + 'px';
    main.style.margin = '0 auto';
    console.log(window.innerWidth,countInRow,main.style.width);

    //遍历box,先记录第一行的box的高度,放入一个高度数组,并且记录最小高度的那一列的序号
    //遍历到的box如果超过第一行,将box拼接到最小高度那一列的下方,然后更新这一列的高度,(高度=原先的高度 + 新拼接图片的高度)
    //后面的图片按照这个算法找到自己的位置
    for(var i = 0; i < boxes.length; i++) {

        if(i < countInRow) {
            boxHeightsInRow.push(boxes[i].offsetHeight);
        }
        else {
            var minHeight = Math.min.apply(Math.min,boxHeightsInRow);
            var minHeightIndex = getMinHeightIndex(minHeight,boxHeightsInRow);

            boxes[i].style.position = 'absolute';
            boxes[i].style.top = minHeight + 'px';
            boxes[i].style.left = minHeightIndex * boxWidth + 'px';
            boxHeightsInRow[minHeightIndex] += boxes[i].offsetHeight;
        }
    }
}

//检测网页滚动,并且算出什么时候加入一张新的图片。
//当最后一个box出现在屏幕时加入新的图片
//最后一个box的top如果 小于等于 屏高 + 网页滚动后的scrollTop,这个时候视为最后一个box出现在屏幕
function checkScroll() {

    var lastBox = boxes[boxes.length - 1];
    var lastBoxCenterTop = lastBox.offsetTop;
    var windowHeight = document.documentElement.clientHeight;
    var scrollTop = document.body.scrollTop;

    console.log("lastBoxCenterTop:" + lastBoxCenterTop + "windowHeight:" + windowHeight + "scrollTop:" + scrollTop);

    if(lastBoxCenterTop <= windowHeight + scrollTop) {
        createABox(Math.floor(Math.random() * 40));
        pinterest();
    }
}

//计算最小高度那一列的序号
function getMinHeightIndex(h,heights) {

    for(var i in heights) {

        if(heights[i] == h) {
            return i;
        }
    }
    return 0;
}

results matching ""

    No results matching ""