642 字
3 分钟
瀑布流布局
瀑布流布局
TIP比较流行的一种布局方案,视觉表现为参差不齐的多栏布局,随着页面滚动条滚动,会不断添加数据块并附加到尾部,瀑布流的主要特性便是错落有致,定宽而不定高的设计让页面区别于传统的矩阵式图片布局模式。
Demo: JS动态添加
:::tip 思路
记录每一列的高度,子绝父相定位,利用top
和left
控制位置,每次增加新成员时,找到高度最小的那一列,并将新成员至于其下方,最后更新每一列的高度。
同时也可利用flex
弹性布局或Css3新增的column-*
多列布局来实现,不过仅限于一次性加载展示,不需要动态添加的场景。
:::
<!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>
#container {
position: relative;
}
.item {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
const column = 3;
let counter = 0;
const columnHeight = Array(column).fill(0);
const container = document.getElementById('container');
const colorList = ["#EAA78C", "#F9CD82", "#9ADEAD", "#9CB6E9", "#E49D9B", "#97D7D7", "#ABA0CA", "#9F8BEC", "#ACA4D5", "#6495ED", "#7BCDA5", "#76B4EF", "#E1C38F", "#F6C46A", "#B19ED1", "#F09B98", "#87CECB", "#D1A495", "#89D196", "#FE9E9F", "#93BAFF", "#D999F9", "#81C784", "#FFCA62", "#FFA477"];
// 生成随机数
function random(min = 0, max = 1) {
return min + ~~((max - min) * Math.random());
}
// 查找高度最小的列
function findMinColumn(arr) {
let min = arr[0];
let index = 0;
arr.forEach((v, i) => {
if (v < min) {
min = v;
index = i;
}
});
return [index, min];
}
function appendImg() {
const gap = 3; // 间隔
for (let i = 0; i < 12; ++i) { // 每次加载12个元素
const unit = {
height: random(100, 500), // 随机一个高度
width: 300, // 定宽
color: colorList[random(0, colorList.length - 1)] // 随机颜色
}
const [minIndex, min] = findMinColumn(columnHeight); // 获取高度最小列及下标
const d = document.createElement('div');
d.className = 'item';
d.style.background = unit.color;
d.style.height = `${unit.height}px`;
d.style.width = `${unit.width}px`;
d.style.top = `${min + gap}px`; // 上偏移
d.style.left = `${(300 + gap) * minIndex}px`; // 设置左偏移
d.innerText = `${++counter}#${unit.width}x${unit.height}`; // 设置文字
columnHeight[minIndex] += (unit.height + gap); // 添加后更新列的长度
container.appendChild(d); // 添加节点
}
}
// 初始化
function init() {
appendImg(); // 初始加载
// 是否有某列高度大于屏幕高度
let endLoad = columnHeight.some(v => v > window.innerHeight);
if (!endLoad) init(); // 如果没有,就递归调用继续加载
}
(function () {
init(); // 打开页面自动加载
})()
// 处理浏览器触底事件
window.onscroll = function () {
let marginBottom = 0;
if (document.documentElement.scrollTop) {
let scrollHeight = document.documentElement.scrollHeight;
let scrollTop = document.documentElement.scrollTop + document.body.scrollTop;
let clientHeight = document.documentElement.clientHeight;
marginBottom = scrollHeight - scrollTop - clientHeight;
} else {
let scrollHeight = document.body.scrollHeight;
let scrollTop = document.body.scrollTop;
let clientHeight = document.body.clientHeight;
marginBottom = scrollHeight - scrollTop - clientHeight;
}
if (marginBottom <= 0) appendImg();
}
</script>
</body>
</html>