JS实现瀑布流页面布局

  • JS实现瀑布流页面布局已关闭评论
  • 195 次浏览
  • A+
所属分类:Web前端
摘要

每列的宽度相等而高度不等,且第二行的第一个容器需要放在第一行高度最小的容器下面,依次类推放置。


个人对瀑布流布局理解:

每列的宽度相等而高度不等,且第二行的第一个容器需要放在第一行高度最小的容器下面,依次类推放置。

附上代码:

代码仅实现了瀑布流的布局方式和 resize 监听,如果大家有需要,可以自己拓展下:实现监听滚动事件,页面滚动加载图片的功能。

代码中写了详细注释,可以直接使用。

<!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>瀑布流布局JS实现</title>     </head>     <body>         <style>             * {                 margin: 0;                 padding: 0;             }             body {                 width: 100vw;                 height: 100vh;             }             .container {                 width: 100vw;                 height: 100vh;                 overflow: scroll;                 position: relative;                 background-color: lightgray;             }             .item {                 width: 200px;                 height: auto;                 box-sizing: border-box;                 background: #fff;                 border: 1px solid #000;                 border-radius: 15px;                 text-align: center;                 font-size: 40px;                 font-weight: bold;                 position: absolute;                 top: 0;                 left: 0;             }             .item1,             .item8 {                 height: 300px;             }             .item2,             .item6 {                 height: 150px;             }             .item3,             .item9 {                 height: 120px;             }             .item4,             .item10 {                 height: 270px;             }             .item5,             .item7 {                 height: 350px;             }         </style>         <div class="container">             <div class="item item1">1</div>             <div class="item item2">2</div>             <div class="item item3">3</div>             <div class="item item4">4</div>             <div class="item item5">5</div>             <div class="item item6">6</div>             <div class="item item7">7</div>             <div class="item item8">8</div>             <div class="item item9">9</div>             <div class="item item10">10</div>         </div>         <script>             function waterFullLayout() {                 console.log("start");                 // 获取页面宽度                 let pageWidth =                     document.getElementsByClassName("container")[0].clientWidth;                 // 获取图片固定的宽度                 let itemWidth = document.getElementsByClassName("item")[0].offsetWidth;                 // 设置图片之间间距                 let gap = 10;                 // 获取一行最多可以展示几张图片                 let nums = Math.floor(pageWidth / (itemWidth + gap));                 // 瀑布流实现原则:                 // 所有图片元素绝对定位,从第二行开始,依次从第一行图片元素高度最小的下方填充,这里注意,不是从左至右填充,即优先填补空位,填补一个后,再填补下一个较大的空位                 // 定义第一行图片的所有高度的数组,之后每张图片下方填充图片后,会更新数组对应位置下的最小高度                 let heightList = [];                 let itemArr = document.getElementsByClassName("item");                 let imgLen = itemArr.length;                 for (let i = 0; i < imgLen; i++) {                     // 如果 当前图片元素索引小于一行最多可以展示的图片个数,说明是第一行,top 已在css中默认设置为0,需要统一设置 left 值,top值如果加gap,则还需设置gap值                     if (i < nums) {                         // 将第一行的图片元素的高度放入 heightList 数组                         heightList.push(itemArr[i].offsetHeight + gap);                         itemArr[i].style.top = gap + "px";                         itemArr[i].style.left = (itemWidth + gap) * i + "px";                     } else {                         // 否则从第二行开始,要根据第一行图片元素的高度,设置top和left                         // 先假设 heightList[0] 为最小高度                         let minItem = {                             minHeight: heightList[0],                             minIndex: 0,                         };                         for (let j = 0; j < heightList.length; j++) {                             if (heightList[j] < minItem["minHeight"]) {                                 minItem["minHeight"] = heightList[j];                                 minItem["minIndex"] = j;                             }                         }                         itemArr[i].style.top = minItem["minHeight"] + gap + "px";                         itemArr[i].style.left =                             (itemWidth + gap) * minItem["minIndex"] + "px";                         // 关键步骤,更新 heightList 中对应位置下整列图片的高度,以便在下次循环时根据heightList 重新寻找最小高度                         heightList[minItem["minIndex"]] =                             parseFloat(itemArr[i].style.top) +                             parseFloat(itemArr[i].offsetHeight);                     }                 }             }             // 防抖             function debounce(fn, delay) {                 let timer = null;                 return function () {                     if (timer) {                         clearTimeout(timer);                     }                     timer = setTimeout(() => {                         fn.apply(this, arguments);                     }, delay);                 };             }             window.onload = function () {                 // 为了保证页面宽度可以正常获取,onload 之后再执行                 waterFullLayout();             };             // 页面宽度变化要重新布局             window.onresize = debounce(waterFullLayout, 100);         </script>     </body> </html>

 实现后效果如下:

JS实现瀑布流页面布局

 

 

 

参考链接:

https://blog.csdn.net/qq_43432158/article/details/121903435

https://www.bilibili.com/video/BV19K4y1K71i?p=3&spm_id_from=pageDriver&vd_source=194f8fed26c3607cae375c20d6e308f0