经典阿里面试题:如何实现瀑布流...

479 阅读2分钟

前言

当面试官提出这样一个场景问题:在快手、小红书、淘宝...等大热的app中,有一种布局产品内容的方式,叫做瀑布流布局(它的主要特点是视觉上呈现出参差不齐的多栏布局,其中每个栏目宽度相等,但高度则根据内容(如图片、文章摘要等)自然调整,形成一种不规则而富有动态感的视觉效果),面试官给出的问题是如何具体实现瀑布流布局。。

接下来给出实例

实例是一个html页面,页面内放置有20张高度不一,宽度相同的图片,通过向左浮动的形式放置(float=left).(下图p1)理想的效果为:在第一行的图片摆放完后,下一张图片摆放在高度最小的一列下方,依此类推,摆放完所有的照片。(下图p2)

image.png

                                           p1

image.png

                                           p2

实现思路

先计算出你的屏幕一行能够放下多少张图片(screenWidth/imgWidth),假设为i张,将i张图片的高度记录在一个数组中,在放置第i+1张图片的时候,找到最短高度的一列,通过对父容器的相对位置定位到那一列的下方放置,放置完后更新最短列的高度设置为boxHeightArr[i+1]=boxHeightArr[indexOfMin]+img.Height[i+1]
后面的图片也通过一样的思路通过for循环完成。


js核心代码:(有注释解题思路)

    // --- 思路
    //确定一行能放几张图片
    //1、获取屏幕宽度
    //2.获取图片的宽度
    //操作第n+1张摆放它的位置 放在高度最小的那一列
    //1.获取每一列的高度
    //2.更新这一列的高度
    

function imgLocation(parent,child){
    var cParent=document.getElementById(parent)
    var cChild=cParent.getElementsByClassName(child)
    var screenWidth=window.innerWidth    //获取窗口宽度
    var imgWidth=cChild[0].offsetWidth  //获取图片的宽度
    var num=Math.floor(screenWidth / imgWidth)   //得到一行放多少张图片
    cParent.style.width=`${imgWidth * num}px`        //将容器大小设置为。。。
    var boxHeightArr=[]
    //遍历所有图片
    for(var i=0;i<cChild.length;i++){
        if(i<num){
            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]+=cChild[i].offsetHeight

        }
    }

console.log(boxHeightArr)
}
imgLocation('container','box')
}

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 #eee;
        }
        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>
    
<script src="./base/index.js"></script>
</body>
</html>


最后我们就完成了面试官给出的需求,成功进入阿里....

总结

虽然这是阿里的一道面试题,但这其实并不那么困难。主要就是对算法思路的清晰,不要被那几张图片绕晕,思路主要就是对容器中元素的定位,以及对图片高度算法的处理..

如果小伙伴们能从中学到的话,是cc的荣幸~留个赞再走吧(共勉)