手把手教你搞定阿里面试题:如何实现瀑布流布局

174 阅读2分钟

什么是瀑布流布局?

瀑布流布局,又称瀑布流式布局或Masonry Layouts,是一种流行的网页设计布局方式,其特点在于视觉上的参差不齐和多栏布局。下面是淘宝和小红书中应用了瀑布流的部分截图。

dda78e789fd5de3e7733a4cad119f84.jpg9f2295bedc41021d5ffeae368323a78.jpg

瀑布流布局之所以受到各大互联网公司的喜爱,就源于它的核心机制的强大,核心机制在于,当用户向下滚动页面时,新的内容块会动态加载并填充到当前视图的最底部,使得页面可以无限延伸,提供了流畅的滚动体验和持续的内容发现过程。接下来实现瀑布流布局。

瀑布流原理

页面容器内的多个高度不固定的div之间按照一定的间隔参差不齐的无序浮动,鼠标滚动时不断在容器内的尾部加载数据,且自动加载到空缺位置,不断循环。

代码实现

一. 前端代码实现(HTML+CSS)
1、首先准备好图片下载到img包内,定义一个container容器来装所有图片,在container容器中用box容器装box-img容器,再用box-img容器装入每张图片

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="./index.js"></script>
  //图片容器格式
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    #container{
      position: relative;
    }
    .box{
      float: left;
      padding: 5px;
    }
    .box-img{
      width: 150px;
      padding: 5px;
      border: 1px solid #aaa;
    }
    img{
      width: 100%;
    }
  </style>
</head>
<body>
//图片容器
  <div id="container">
    <div class="box">
      <div class="box-img">
        <img src="./img/1.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/2.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/3.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/4.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/5.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/6.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/7.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/8.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/9.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/10.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/1.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/2.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/3.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/4.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/5.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/6.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/7.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/8.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/9.webp" alt="">
      </div>
    </div>
    <div class="box">
      <div class="box-img">
        <img src="./img/10.webp" alt="">
      </div>
    </div>
  </div>

  
</body>
</html>

二. js代码实现

//首先调用window.onload=function(){}当页面加载完成时,会被触发这个函数完成接下来的执行任务
window.onload = function() {

    imgLocation('container','box')
    //定义函数imgLocation(parent,child) {}
    function imgLocation(parent,child) {
        //利用getElementById(parent)方法来获取父容器container
        var cParent = document.getElementById(parent)
        利用getElementsByClassName(child)方法来获取装载图片的容器box并返回到一个数组当中去
        var cChild = cParent.getElementsByClassName(child)
        var screenWidth = window.innerWidth
        //cChild[0].offsetWidth获取图片的宽度
        var imgWidth = cChild[0].offsetWidth
        var num = Math.floor(screenWidth / imgWidth)  //放得下几张图片向下取整
        //为父容器container设置宽度,即为imgWidth*num
        cParent.style.width = `${imgWidth*num}px`

        //首先定义一个空数组boxHeightArr用来存放列高,利用for循环来遍历存放box的数组,
        //若摆放数小于num,则摆放在第一行,
        //并利用boxHeightArr.push(cChild[i].offsetHeight)将高传入到数组中去,
        //利用indexOf() 返回第一行行高最小的图片的数组下标,
        //将第num+1张图摆放在第二行高最小图同一列。
        
        var boxHeightArr = []
        for (var i = 0; i < cChild.length; i++) {
            if (i < num) {  //第一行的n张图
                boxHeightArr.push(cChild[i].offsetHeight)
            }else {
                //找数组最小值
                var minHeight = Math.min(...boxHeightArr)
                var minIndex = boxHeightArr.indexOf(minHeight)
                //摆放图片
                cChild[i].style.position = 'absolute'
                cChild[i].style.top = minHeight + 'px'
                cChild[i].style.left = cChild[minIndex].offsetLeft + 'px'
                //更新这一列的高度
                boxHeightArr[minIndex] = boxHeightArr[minIndex] + cChild[i].offsetHeight
            } 
        }
    }
}

运行结果展示

image.png 以上就是实现过程,如有错误,还请大佬指正!!