瀑布流
瀑布流式布局是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。最早采用此布局的网站是Pinterest,逐渐在国内流行开来。国内大多数清新站基本为这类风格。
优点:
- 降低了界面复杂度,节省了空间
- 对于触屏设备更加友好,通过向上滑动浏览
- 使用户专注于浏览,去掉繁琐的操作,体验更好
原理
瀑布流的元素为等宽元素(不等高),其以列排布,无限加载下去。这其中就涉及一个问题:如何使得每列高度差不多相等。
一个简单的算法是贪心算法:
- 各列高度初始化为 0
- 寻找各列之中所有元素高度之和的最小者
- 将新的元素添加到该列上
- 该列高度加上新元素的高度
- 如果还有未添加元素,跳转至第
2.
步
实现
一个完整的实现如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.item {
position: absolute;
width: 250px;
margin: 5px;
transition: all 1s;
}
.water-fall {
position: relative;
}
.type1 {
background-color: Cyan;
height: 250px;
}
.type2 {
background-color: Coral;
height: 450px;
}
.type3 {
background-color: Indigo;
height: 350px;
}
</style>
</head>
<body>
<div class="water-fall">
<div class="item type1">1</div>
<div class="item type2">2</div>
<div class="item type3">3</div>
<div class="item type2">4</div>
<div class="item type3">5</div>
<div class="item type1">6</div>
<div class="item type2">7</div>
<div class="item type3">8</div>
<div class="item type2">9</div>
<div class="item type3">10</div>
<div class="item type1">11</div>
<div class="item type3">12</div>
<div class="item type1">13</div>
<div class="item type3">14</div>
<div class="item type1">15</div>
<div class="item type2">16</div>
<div class="item type1">17</div>
<div class="item type2">18</div>
</div>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script>
function findMinIndex(arr) {
var minIndex = 0;
for (var i = 0; i < arr.length; i++) {
if (arr[i] < arr[minIndex])
minIndex = i;
}
return minIndex;
}
function waterFall() {
var itemWidth = $(".item").outerWidth(true)
var containerWidth = $(".water-fall").width()
var colNum = Math.floor(containerWidth / itemWidth);
var heights = [];
for (var i = 0; i < colNum; i++) {
heights.push(0)
}
$(".item").each(function () {
var col = findMinIndex(heights);
var ele = $(this)
ele.css({
top: heights[col] + "px",
left: col * itemWidth + "px"
});
heights[col] += ele.outerHeight(true);
})
}
waterFall();
$(window).on("resize", function () {
waterFall()
})
</script>
</body>
</html>
点击这里预览,请改变浏览器宽度,看看效果
优化
思考:
- 无限加载怎么实现?
- 瀑布流有没有必要配合上图片懒加载?
- 瀑布流元素用 img ,而 img 没有加载的时候瀑布流项的高度无法确定,我们该怎么办?
- 如何获取数据,动态渲染出瀑布流?
提示:
- 我们可以绑定 scroll 事件,在瀑布流底部添加一个加载更多的 div,当 div 被用户看到的时候,加载更多内容。或者直接计算文档高度和用户滚动高度只差,小于某个值即加载更多。
- 没必要,为什么?
- 响应 img 标签的 load 事件,具体该怎么做那?
- 跨域获取数据,前端动态渲染