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;
}