瀑布流特点:
1.图片长短不一,但排列整齐有序
2.中心思想:
根据可视区的宽度clientWidth,确定瀑布流的列数,
寻找高度最低的一列,每次循环遍历时,下一张图片应先从最低列下端续上,
每循环一次,每计算一次列数的总高度
每张后续图片采用定位的方式摆放
开篇先说几句:
1.这个瀑布流效果列数不定,适用于pc端.(移动端瀑布流后期奉上)
2.参考了一篇网文,但是看到有网友评论称“使用position定位的瀑布流都不算合格”,
在我仿照着实现瀑布流功能后,发现这位网友的评论确有道理,
因为每当浏览器可视区域宽度(clientWidth)变化时,由于定位的原因,出现了图片错位现象,在刷新浏览器的情况下方可解决.
3.参考文章的作者思路巧妙,值得学习模仿,因此有了此文.(您即将看到的代码已经过极度简化)
4.木有封装,相信您一定能看懂
先看一下瀑布流的效果图:
有长有短,图片的排列按照列数先短后长的顺序进行.
代码如下:
html部分:
<body>
<!-- 为了节约篇幅,我减去了部分class='box'的div元素,可以根据需要自行添加 -->
<div id="container">
<div class="box">
<img src="assets/22.jpg">
</div>
<div class="box">
<img src="one.jpeg">
</div>
<div class="box">
<img src="assets/timg.jpeg">
</div>
<div class="box">
<img src="assets/1.jpg">
</div>
<div class="box">
<img src="assets/22.jpg">
</div>
<div class="box">
<img src="assets/2.jpg">
</div>
<div class="box">
<img src="assets/11.jpg">
</div>
</div>
为了节约篇幅,我的小盒子<div class="box">元素减去了不少,
如果您练习时为了追求明显的效果,可以后续添加n多个这样的小盒子
CSS部分:
无论父盒子还是子盒子,他们的宽高全靠其下一层内容来撑
<style>
*{
margin: 0px;
padding: 0px;
}
/*将主容器的布局方式设置为相对布局,
注意:js部分会为container添加上宽度,
以实现margin:0 auto的样式需求*/
#container{
position: relative;
margin:0 auto;
}
.box{
padding: 5px;
float: left;
}
/*图片尺寸*/
.box img{
width: 250px;
height: auto;
}
</style>
注意:container元素最初没有设置宽度,JS部分会为其计算出宽度,实现居中效果
JS部分:
<script>
window.onload = function(){
// 获取浏览器可视区域宽度
var clientWidth = document.documentElement.clientWidth;
// 获取小盒子的数组
var sons = document.getElementsByClassName('box')
// 总宽度/小盒子的宽度,得出当前可视区可以放入几列图片,即获取列数
var num = Math.floor(clientWidth/sons[0].offsetWidth)
// 获取父盒子
var father = document.getElementById('container')
//计算出父盒子的宽度
father.style.cssText = 'width:' + sons[0].offsetWidth*num + 'px;'
var rowBoxHeight = [];// 创建一个存放每一行高度值的数组
for(var i = 0 ;i<sons.length;i++){
//如果图片数量小于列数
if(i < num){
//两种把所得项放入新数组的方法
// rowBoxHeight.push(sons[i].offsetHeight)//方法1
rowBoxHeight[i] = sons[i].offsetHeight // 方法2 新数组的每个值就是每个box的高度值
} else {
//如果图片数量大于列数,那么先找到每一列中最小高度
// 注意Math.min.apply的用法
var minHeight = Math.min.apply(null,rowBoxHeight)
//找到最低高度的box的索引值
for(let i in rowBoxHeight){
if(rowBoxHeight[i] == minHeight){
var minHeightIndex = i;
}
}
// 即将续上的图片的布局方式是绝对布局
sons[i].style.position = 'absolute';
// top值为为最低高度box的高度
sons[i].style.top = minHeight +'px';
//left值最低高度box的坐标offsetLeft
sons[i].style.left = sons[minHeightIndex].offsetLeft +'px';
//新续上的图片改变了该数列的高度,所以,及时更新数列高度,为下一轮循环高度比较做准备
rowBoxHeight[minHeightIndex] += sons[i].offsetHeight;
}
}
}
</script>
注意点:
1.window.onload保证图片加载完成后,可以获取到正确的offsetHeight;
2.Math.min() 返回一组表达式中最小者,apply使得数组可以使用Math.min方法
Math.max() 返回一组表达式中的最大者
3.两种为数组添加成员的方式
rowBoxHeight.push(sons[i].offsetHeight)
rowBoxHeight[i] = sons[i].offsetHeight
4.新续上的图片改变了该数列的高度,所以,及时更新数列高度,
为下一轮循环高度比较做准备.
列的高度 = 列的最低高度 + 新续的图片高度
rowBoxHeight[minHeightIndex] += sons[i].offsetHeight;