我们浏览网站的时候尤其是图片网站,我们会发现大大小小的图片,紧密的排列在一起,就像瀑布一样看着非常舒服,虽然css可以通过cloums来指定,
像我们这次的图片项目用的就是css实现的,最后布局是用grid布局写的,最后比较懒,就没有改成js实现的瀑布流,因为其比较耗性能而且每次都会重排,用户体验不好,所以更多的还是用js去写,这里就来分享一下吧。
核心js代码
//第一个值是父元素,第二个是子元素,第三个是指定多少列
function waterFall(parentEle, childEle, cols) {
//根据图片的列数来确定父盒子的宽度,父盒子居中
//获取标签,父盒子和所有子盒子
var father = document.getElementById(parentEle)
var allBox = document.getElementsByClassName(childEle)
//获取其中一个的宽度
var boxWidth = allBox[0].offsetWidth
//获取文档的宽度(兼容)
var screen = document.documentElement.clientWidth || document.body.clientWidth
// 父盒子居中,给父盒子设置宽度
father.style.width = cols * boxWidth + 'px'
father.style.margin = '0 auto'
//子盒子定位(从第二行开始)
// 定义变量
var heightArr = [], boxHeight = 0, minBoxHeight = 0, minIndex = 0
//遍历所有的盒子
for (let i = 0; i < allBox.length; i++) {
boxHeight = allBox[i].offsetHeight
//判断是否是第一行
if (i < cols) {
heightArr.push(boxHeight)
} else { //剩余行做定位
//取出数组中最矮盒子的高度
minBoxHeight = heightArr[minBox(heightArr)]
//取出最矮盒子再数组中的索引
minIndex = minBox(heightArr)
//剩余子盒子的定位
allBox[i].style.position = 'absolute'
allBox[i].style.left = minIndex * boxWidth + 'px'
allBox[i].style.top = minBoxHeight + 'px'
/*
更新高度(利用更新这个数组实现动态找最低的
每次循环时会在原本最低的那个盒子的高度基础上加上新添加的盒子的高度)
*/
heightArr[minIndex] += boxHeight
}
}
}
// 获取高度最小的一个值
function minBox(box) {
var j = 0
for (i in box) {
if (box[j] > box[i]){
j = i
}
}
return j
}
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>瀑布流</title>
<style>
* {
padding: 0;
margin: 0;
border: none;
}
img {
width: 200px;
vertical-align: top;
}
#main {
position: relative;
}
.box {
float: left;
padding: 15px 0 0 15px;
}
.pic {
padding: 10px;
border: 1px solid #ccc;
}
.clearFloat::after {
content: "";
display: block;
clear: both;
}
</style>
</head>
<body>
<button onclick="sureFn()">确定</button>
<div id="main" class="clearFloat">
<div class="box">
<div class="pic">
<img src="./img/huidilogo.png" alt="">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./img/613927.jpg" alt="">
</div>
</div>
<div class="box">
<div class="pic">
<div class="" style="display: grid;">
<img src="./img/677283.jpg" alt="">
<span>123</span>
</div>
</div>
</div>
<div class="box">
<div class="pic">
<img src="./img/680381.png" alt="">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./img/911401.jpg" alt="">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./img/huidilogo.png" alt="">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./img/huidilogo.png" alt="">
</div>
</div>
<div class="box">
<div class="pic">
<img src="./img/613927.jpg" alt="">
</div>
</div>
<div class="box">
<div class="pic">
<div class="" style="display: grid;">
<img src="./img/677283.jpg" alt="">
<span>123</span>
</div>
</div>
</div>
</div>
<script>
window.addEventListener("load", function () {
waterFall('main', 'box', 4);
});
//2、加载数据(追加)
function sureFn() {
let str = `
<div class="pic">
<img src="./img/1.png" alt="">
</div>
`
var newBox = document.createElement('div');
newBox.className = 'box';
newBox.innerHTML = str
document.getElementById('main').appendChild(newBox);
//重新进行瀑布流布局
waterFall('main', 'box', 4);
}
}
function waterFall(parentEle, childEle, cols) {
var father = document.getElementById(parentEle);
var allBox = document.getElementsByClassName(childEle);
var boxWidth = allBox[0].offsetWidth;
var screen = document.documentElement.clientWidth || document.body.clientWidth;
father.style.width = cols * boxWidth + 'px';
father.style.margin = '0 auto';
var heightArr = [], boxHeight = 0, minBoxHeight = 0, minIndex = 0;
for (let i = 0; i < allBox.length; i++) {
boxHeight = allBox[i].offsetHeight;
if (i < cols) {
heightArr.push(boxHeight)
} else {
minBoxHeight = heightArr[minBox(heightArr)];
minIndex = minBox(heightArr);
allBox[i].style.position = 'absolute';
allBox[i].style.left = minIndex * boxWidth + 'px';
allBox[i].style.top = minBoxHeight + 'px';
heightArr[minIndex] += boxHeight;
}
}
}
function minBox(box) {
var j = 0;
for (i in box) {
if (box[j] > box[i])
j = i
}
return j;
}
</script>
</body>
</html>
效果图
总结
之后再写项目的话,不能像这次项目那样用最简单的方式去实现瀑布流,要想到用户体验和一些性能的考虑。