阿里面试——手撕瀑布流布局

发布于:2024-04-25 ⋅ 阅读:(35) ⋅ 点赞:(0)

前言

本前端渣在今天的学习中遇到了一种新的布局方式--瀑布流布局。那么什么是瀑布流布局呢?(一个熊猫图在我脑海中浮现)

image.png

瀑布流布局

当前主流的一些软件当中我们常常可以看见这样的一种布局,该布局可以将大小不一的图片完整的显示在页面上,并且在杂乱的布局中保持着一定的美感。(如下图:)

Screenshot_2024-04-23-23-12-35-519_com.jingdong.a.jpg

image.png

HTML与CSS部分

  1. div#container 作为所有图片的容器
  2. div.box 作为每个图片的容器
  3. div.box-img 包裹 img 标签
  4. img负责显示图片
  5. 多个 div.box 排列图片
  6. 重复上述结构,排列了多行图片
  7. 主容器使用相对定位占据文档流中的位置而其子标签box使用浮动式布局
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #container {
            position: relative;
        }

        .box {
            float: left;
            padding: 5px;
        }

        .box-img {
            width: 150px;
            padding: 5px;
            border: 1px solid #dd9f9f;
        }

        img {
            width: 100%;
        }
    </style>
</head>

<body>
    <div id="container">
        <div class="box">
            <div class="box-img">
                <img src="./img/1.webp" alt="">
            </div>
        </div>
        ......省略了19个box

    </div>
    <script src="index.js"></script>
</body>

</html>

此时的页面:

image.png

JavaScript部分

实现原理:

1.使用一个父容器container包裹子容器box

2.图片容器box-img包裹在容器box中,用来展示

3.通过js获取父容器的DOM结构,再获取其子元素图片容器box

4.将其按照瀑布流的规则使用绝对定位放置

5.获取屏幕大小计算该屏幕最多能放下几张图片,将前n张图片放在第一行

6.使用一个heightArr高度数组,在放置的时候记录每一列图片的高度,后面的图片放置在高度最低的那一列

图解:

image.png

js代码实现:

//获取用户屏幕宽度,决定一行几张图
//操作下一张图,放到上一行最矮的列下
imgLocation('container', 'box');

function imgLocation(parent, content) {
    var cparent = document.getElementById(parent)
    var ccontent = getChildElement(cparent, content) //document.querySelectorAll('#container .box')
    // console.log(ccontent)
    var imgWidth = ccontent[0].offsetWidth
    var num = Math.floor(document.documentElement.clientWidth / imgWidth)
    cparent.style.width = `${imgWidth * num}px`
    //要操作的是哪张,每一列的高度

    var BoxHeightArr = []
    for (var i = 0; i < ccontent.length; i++) {
        if (i < num) {
            //记录第一行
            BoxHeightArr[i] = ccontent[i].offsetHeight
        }
        else {
            //开始操作,找到最矮的高度及列数
            minHeight = Math.min.apply(null, BoxHeightArr)
            var minIndex = BoxHeightArr.indexOf(minHeight);

            //摆放图片位置
            ccontent[i].style.position = "absolute"
            ccontent[i].style.top = minHeight + "px"
            ccontent[i].style.left = ccontent[minIndex].offsetLeft + "px"
            //更新这一列图片高度
            BoxHeightArr[minIndex] = BoxHeightArr[minIndex] + ccontent[i].offsetHeight
        }
    }
    console.log(BoxHeightArr);


}

function getChildElement(parent, child) {
    //获取parent中所有child
    var childArr = []
    var allChild = parent.getElementsByTagName('*')
    //找出所有box
    for (var i = 0; i < allChild.length; i++) {
        if (allChild[i].className == child) {
            childArr.push(allChild[i])
        }
    }
    return childArr
}

最终效果:

image.png

到这瀑布流布局就已经实现了,希望对大家有所帮助。 image.png