阿里面试官:如何实现瀑布流

247 阅读3分钟

瀑布流是什么

我们这时候便可以望文生义了,瀑布流即像瀑布一般 散落而有序,每一段水流都没有很规则整齐地排列宣泄而下,但又有一个宽度和走势,而形成一种错落美。因此,在我们各大社交媒体平台也有瀑布流的应用。

4920b5f5da81225ded0971c08771849b.png

那么我们如何能实现呢?

现在我们要在页面上放置二十张大小不一的图片,如果按照常规的布局摆放是这样的,我们可以看到在简单的浮动下,会留有很大的间隙,不忍直视。

image.png

而如果你利用瀑布流来show的话,是这样的

image.png

要实现瀑布流有很多方法如 计算列数计算缩放CSS3 column 属性……每一种方法各有利弊,所以当你觉得这个行,那么他就好用。

今天我们来尝试用绝对定位来实现瀑布流。

首先呢 我们需要在页面放置所需图片,完成一个简单的布局

<!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 #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>
</body>
</html>

然后我们就要思考如何来实现了

确定第一行能放多少(n)张图
  • 由于每一个用户的屏幕大小不一,我们需要确定用户的屏幕宽度、图片容器的宽度以及一行可以容纳的图片数量 这里我们可以通过DOM结构来获取我们需要的属性

// 获取容器元素 
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`

我们知道了一行能放多少张图片了,那么第二行呢,接下来就要操作第n+1张图放在哪里了,按照我们的思路,我们会将其放在上一行中高度最小的那一张图片的下面,然后我们对于高度进行更新,对吧,但我们并不知道从第几章开始要换行了,所以我们可以利用循环来放置图片并进行更新。

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] = boxHeightArr[minIndex] + cChild[i].offsetHeight }

what can I say 你已经成功了

路漫漫其修远兮 这不过是一个基础的瀑布流布局 我们还可以进行更多的优化以适应用户的需求 而我们也将在不断地优化中生长。