/**
* 实现瀑布流布局
*/
function waterFull(parent, child) {
// 1. 父盒子居中
// 1.1 获取所有的盒子
var allBox = $(parent).getElementsByClassName(child);
// 1.2 获取子盒子的宽度
var boxWidth = allBox[0].offsetWidth;
// 1.3 获取屏幕的宽度
var screenW = document.documentElement.clientWidth;
// 1.4 求出列数
var cols = parseInt(screenW / boxWidth);
var xyMargin = 16;
// 2. 子盒子的定位
// 2.1 定义高度数组
var heightArr = [], boxHeight = 0, minBoxHeight = 0, minBoxIndex = 0;
// 2.2 遍历子盒子
for (var i = 0; i < allBox.length; i++) {
// 2.2.1 求出每一个子盒子的高度
boxHeight = allBox[i].offsetHeight + xyMargin;
// 2.2.2 取出第一行盒子的高度放入高度数组
if (i < cols) { // 第一行
heightArr.push(boxHeight);
allBox[i].style.position = "absolute";
allBox[i].style.left = i * (boxWidth + xyMargin)+ 'px';
allBox[i].style.top = xyMargin + 'px';
} else { // 剩余行
// 1. 取出最矮的盒子高度
minBoxHeight = _.min(heightArr);
// 2. 求出最矮盒子对应的索引
minBoxIndex = getMinBoxIndex(heightArr, minBoxHeight);
// 3. 子盒子定位
allBox[i].style.position = "absolute";
allBox[i].style.left = minBoxIndex * (boxWidth + xyMargin)+ 'px';
allBox[i].style.top = minBoxHeight + xyMargin + 'px';
// 4. 更新数组中的高度
heightArr[minBoxIndex] += boxHeight;
}
}
// 5. 更新父盒子的高度
var parentHeight = allBox[allBox.length - 1].offsetTop + allBox[allBox.length - 1].offsetHeight;
$(parent).style.height = parentHeight;
}
/**
* 获取数组中最矮盒子高度的索引
* @param arr
* @param val
* @returns {number}
*/
function getMinBoxIndex(arr, val) {
for(var i=0; i<arr.length; i++){
if(arr[i] === val){
return i;
}
}
}
function $(id) {
return typeof id === "string" ? document.getElementById(id) : null;
}
/**
* 判断是否具备加载图片的条件,如果满足,自动填充
*/
function checkWillLoadImage() {
// 1. 获取最后一个盒子
var allBox = document.getElementsByClassName("box");
var lastBox = allBox[allBox.length - 1];
// 2. 求出最后一个盒子自身高度的一半 + offsetTop
var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop;
// 3. 求出屏幕的高度
var screenW = document.body.clientHeight || document.documentElement.clientHeight;
// 4. 求出页面偏离浏览器的高度
var scrollTop = scroll().top;
return lastBoxDis <= screenW + scrollTop;
}
知识点
- 瀑布流大概思想
① 每一个图片盒子的宽度是固定的,根据当前页面宽度,求出一行能有几列,进而求出最外层div的宽度进行设置并居中.
② 子盒子定位思想
Ⅰ. 第一行顺次排列,用一个数组存储他们的高度
Ⅱ. 第二行的第一张接在第一行最矮的一张下面,并将二者的高度和存入数组
Ⅲ.排好第一行后,将剩余所有图片按照Ⅱ进行排列
③ 便利所有数据,重复瀑布流 - 子绝父相并不是父盒子一定要是相对定位,只要不是static即可
- 当页面缩放的时候,重新进行瀑布流定位,并且将第一行的style定位清除掉
- 节流
① 当添加监听事件的时候,如果请求非常频繁。比如滚动,可以利用定时器进行节流。
② 设置一个定时器,每隔固定的事件进行进行一次操作。
运行效果
代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div id="main">
<div class="box"><div class="pic"><img src="images/img02.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img03.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img04.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img05.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img06.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img07.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img08.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img09.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img10.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img11.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img12.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img13.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img14.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img15.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img16.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img17.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img18.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img19.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img20.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img21.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img22.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img23.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img24.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img25.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img26.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img27.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img28.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img29.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img30.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img31.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img32.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img33.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img34.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img35.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img36.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img37.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img38.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img39.jpg" alt=""></div></div>
<div class="box"><div class="pic"><img src="images/img40.jpg" alt=""></div></div>
</div>
<script src="js/UnderScore.js"></script>
<script src="./js/MyTools.js"></script>
<script src="js/index.js"></script>
</body>
</html>
index.css
*{
margin: 0;
padding: 0;
border: none;
}
img{
vertical-align: top;
}
html,body{
width: 100%;
height: 100%;
}
/*子绝父相*/
*{
margin: 0;
padding: 0;
border: none;
}
img{
vertical-align: top;
}
html,body{
width: 100%;
height: 100%;
}
/*子绝父相*/
#main{
position: relative;
}
.box{
float: left;
padding: 15px 0 0 15px;
}
.pic{
padding: 10px;
border: 1px solid #cccccc;
border-radius: 10px;
}
.box img{
width: 165px;
}
index.js
window.addEventListener('load', function (ev) {
var timer = null,timer1= null;
// 1. 实现瀑布流布局
waterFull('main', 'box');
// 2. 加载数据
window.addEventListener('scroll',function (ev1) {
clearInterval(timer1);
timer1 = setInterval(function () {
if (checkWillLoadNewBox()){ // 结果为真
// 2.1 假数据
var dataArr = [
{"src":"img02.jpg"},
{"src":"img03.jpg"},
{"src":"img05.jpg"},
{"src":"img04.jpg"},
{"src":"img15.jpg"},
{"src":"img06.jpg"},
{"src":"img08.jpg"},
{"src":"img29.jpg"},
{"src":"img30.jpg"},
{"src":"img12.jpg"}
];
// 2.2 遍历数据
for (var i = 0; i < dataArr.length; i++) {
var newBox = document.createElement('div');
newBox.className = 'box';
myTool.$('main').appendChild(newBox);
var newPic = document.createElement('div');
newPic.className = 'pic';
newBox.appendChild(newPic);
var newImg = document.createElement('Img');
newImg.src = 'images/'+dataArr[i].src;
newPic.appendChild(newImg);
}
// 2.3 重新进行瀑布流布局
waterFull('main', 'box');
}
},200);
});
// 3. 页面尺寸发生改变重新布局
window.addEventListener('resize',function (ev1) {
clearInterval(timer);
timer = setInterval(function () {
waterFull('main', 'box');
}, 200);
})
});
/**
* 实现瀑布流布局
* @param {string}parent 父盒子id
* @param {string}child 子盒子class
*/
function waterFull(parent, child) {
// 1. 父盒子居中
// 1.1 获取标签
var allBox = myTool.$(parent).getElementsByClassName(child);
// 1.2 获取其中一个子盒子的宽度
var boxWidth = allBox[0].offsetWidth;
// 1.3 获取文档的宽度
var screenW = document.documentElement.clientWidth || document.body.clientWidth;
// 1.4 求出列数
var cols = parseInt(screenW / boxWidth);
// 1.5 让父盒子剧中
myTool.$(parent).style.width = cols * boxWidth + 'px';
myTool.$(parent).style.margin = '0 auto';
// 2. 子盒子定位
// 2.1 定义变量
var heightArr = [], boxHeight = 0, minBoxHeight = 0, minBoxIndex = 0;
// 2.2 遍历所有盒子
for (var i = 0; i < allBox.length; i++) {
boxHeight = allBox[i].offsetHeight;
// 2.3 判断
if (i < cols) { // 第一行
heightArr.push(boxHeight);
allBox[i].style='';
} else { // 剩余行
// 2.4 取出数组中最矮盒子的高度
minBoxHeight = _.min(heightArr);
// 2.5 取出最矮盒子在数组中的索引
minBoxIndex = getMinBoxIndex(heightArr, minBoxHeight);
// 2.6 剩余子盒子定位
allBox[i].style.position = 'absolute';
allBox[i].style.left = minBoxIndex * boxWidth + 'px';
allBox[i].style.top = minBoxHeight + 'px';
// 2.7 更新高度
heightArr[minBoxIndex] += boxHeight;
}
}
}
function getMinBoxIndex(arr, val) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === val) {
return i;
}
}
}
/**郇凯
* 判断页面高度+页面划出高度 与 最后一张图片高度一半+距页面上方距离 的大小
* 如果大于,图片出现
* @returns {boolean} 返回为真为假
*/
function checkWillLoadNewBox(){
// 1 获取最后的盒子
var allBox = myTool.$('main').getElementsByClassName('box');
var lastBox = allBox[allBox.length - 1];
// 2 求最后盒子高度的一半
var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop;
// 3. 求出页面高度
var screenH = document.documentElement.clientHeight || document.body.clientHeight;
// 4. 求出页面滚出浏览器高度
var scrollTopH = myTool.scroll().top;
// 5. 返回结果
return lastBoxDis <= screenH + scrollTopH;
}