求star

开源不易,喜欢请点个star吧

Ocean Han
642 字
3 分钟
瀑布流布局
2023-03-03

瀑布流布局#

TIP

比较流行的一种布局方案,视觉表现为参差不齐的多栏布局,随着页面滚动条滚动,会不断添加数据块并附加到尾部,瀑布流的主要特性便是错落有致,定宽而不定高的设计让页面区别于传统的矩阵式图片布局模式。

Demo: JS动态添加#

:::tip 思路

记录每一列的高度,子绝父相定位,利用topleft控制位置,每次增加新成员时,找到高度最小的那一列,并将新成员至于其下方,最后更新每一列的高度。

同时也可利用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>
瀑布流布局
https://blog.oceanh.top/posts/frontend/瀑布流布局/
作者
Ocean Han
发布于
2023-03-03
许可协议
CC BY-NC-SA 4.0
最后修改时间
2024-08-10 10:08:49