使用js实现瀑布流

效果图如下:
在这里插入图片描述
设计思路:

  1. 封装一个函数,可以接受五个参数分别为容器id(或class)名称、容器中内容项id(或class)名称、容器中内容展示列数、容器中列间隔距离、容器中行间隔距离。当我们下次再有地方需要生成瀑布流的时候,我们就可以直接传入对应的参数就可以了。
  2. 获取每一列的宽度以及图片的集合
  3. 生成一个数组(数组的长度是瀑布流列的长度),用于存放每一列已经放置了图片的总高度,方便后面比较大小,知道哪一列的图片最少,将图片加入到哪一列
  4. 先挨个将图片放入到第一行
  5. 然后比较哪一列的高度值最小,然后将带有定位的图片定位至哪一些列,然后将该列的高度进行增加一个图片的高度。
  6. 在放置下一张图片的时候,重复第五步即可

代码如下:

<!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>Document</title>
    <style>
        * {
    
    
            margin: 0;
            padding: 0;
        }

        .tab-container {
    
    
            position: relative;
        }

        .tab-container .tab-item {
    
    
            position: absolute;
            height: auto;
            border: 1px solid #000;
            background: white;
            break-inside: avoid;
            text-align: center;
        }

        .tab-container .tab-item img {
    
    
            width: 100%;
            height: auto;
        }
    </style>
</head>

<body>
    <div class="tab-container" id="tabContainer">
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/business-people_PAQJGIXNYI.jpg" />
        </div>
        <div class="tab-item">
            <img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />

        </div>
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/coastal-landscape_80QIX6YO2W.jpg" />
        </div>
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/girl-field_RY7NGH96SF.jpg" />
        </div>
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/mushrooms-forest_LUYHIZXNWX.jpg" />
        </div>
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/QX9O1AZUPM.jpg" />
        </div>
        <div class="tab-item">
            <img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
        </div>
        <div class="tab-item">
            <img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />

        </div>
        <div class="tab-item">
            <img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
        </div>
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/QX9O1AZUPM.jpg" />
        </div>
        <div class="tab-item">
            <img src="https://img2.baidu.com/it/u=3856347329,2228203164&fm=253&fmt=auto&app=120&f=JPEG?w=480&h=800" />
        </div>
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/QX9O1AZUPM.jpg" />
        </div>
        <div class="tab-item">
            <img src="https://cdn.stocksnap.io/img-thumbs/280h/dog-sunglasses_ZVCXJVXL75.jpg" />
        </div>
    </div>
    <script>
        window.onload = function () {
    
    
            waterFall('#tabContainer', '.tab-item'); //实现瀑布流
        }

        /**
         * @param { string } wrapIdName 容器id(或class)名称
         * @param { string } contentIdName 容器中内容项id(或class)名称
         * @param { number } column 容器中内容展示列数 默认为4
         * @param { number } columnGap 容器中列间隔距离 默认为20
         * @param { number } rowGap 容器中行间隔距离 默认为20
         */
        function waterFall(wrapIdName, contentIdName, columns = 4, columnGap = 20, rowGap = 20) {
    
    
            // 获得内容可用宽度(去除滚动条宽度)
            const wrapContentWidth = document.querySelector(wrapIdName).offsetWidth - 8;

            // 间隔空白区域
            const whiteArea = (columns - 1) * columnGap;

            // 得到每列宽度(也即每项内容宽度)
            const contentWidth = parseInt((wrapContentWidth - whiteArea) / columns);

            // 得到内容项集合
            const contentList = document.querySelectorAll(contentIdName);

            // 成行内容项高度集合
            const lineConentHeightList = []

            for (let i = 0; i < contentList.length; i++) {
    
    
                // 动态设置内容项宽度
                // 设置完宽度之后高度也会等比例的缩小
                contentList[i].style.width = contentWidth + 'px';

                // 获取内容项高度
                const height = contentList[i].clientHeight;
                if (i < columns) {
    
    
                    // 第一行按序布局
                    contentList[i].style.top = 0;
                    contentList[i].style.left = contentWidth * i + columnGap * i + 'px';

                    // 将行高push到数组
                    lineConentHeightList.push(height)
                    console.log(lineConentHeightList);
                } else {
    
    
                    // 其他行
                    // 获取数组最小的高度 和 对应索引			
                    let minHeight = Math.min(...lineConentHeightList)
                    let index = lineConentHeightList.findIndex(listH => listH === minHeight)

                    contentList[i].style.top = (minHeight + rowGap) + 'px';
                    contentList[i].style.left = (contentWidth + columnGap) * index + 'px';

                    // 修改最小列的高度 最小列的高度 = 当前自己的高度 + 拼接过来的高度 + 行间距
                    lineConentHeightList[index] += height + rowGap
                }
            }
        }

    </script>
</body>

</html>

猜你喜欢

转载自blog.csdn.net/ksjdbdh/article/details/129654794