大厂面试官:如何实现瀑布流? 带你从“-1”开始,码出瀑布。
在我们浏览个个app时,会经常看见像这样类似的瀑布效果的图片布局方式,我们应该如何用js来实现呢?今天我们来谈谈同样是大厂面试官会谈到的话题--如何实现瀑布流
一、什么是瀑布流布局
1、像这样参差不齐的多栏布局,大多数的内容都是图片,并且图片的长度,宽度各不同,每张图片都紧密相连的充满屏幕,我们形象的称为瀑布流
2、优点:
- 减缓用户的视觉疲劳
- 增加页面的有效使用率
3、缺点:
- 页面加载负担变大
- 代码实现逻辑稍加复杂
二、具体代码实现
1、“伪代码的构想”--编程思路
当我们还没设置任何的样式,仅仅将图片放在页面中时,效果是这样的
(1)横向铺满 (2)纵向铺满
简单的两个代码思路就解决了瀑布流的实现。
2、代码的实现
给图片容器加上一些css属性,用float实现了让图片纵向铺满。
*{
margin: 0;
padding: 0;
}
#container{
position: relative;
}
.box{
float: left;
border: 1px solid #aaa;
}
.box-img{
width: 188px;
padding: 5px;
}
img{
width: 100%;
}
</style>
1、横向铺满
我们可以看到,当图片铺满第一行后,后面的图片似乎变得乱了起来。
这是因为float:left属性,将图片容器脱离文本流,当第一行放不下时,它会按照放下的最后一个元素的高度往前浮动,这时候前面已经放入的图片有更高的花,就会被挡住,展现出上图的布局效果。
这时候,我们就要解决第二步,将图片容器纵向铺满
2、如何解决纵向铺满呢?
“伪代码”--编程思路: 判断能第一列能放n张图片: 1、获取屏幕的宽度 2、获取图片的宽度,计算能放多少张图片
处理第n+1张之后的布局方法: 1、找第一列高度最低的图片 2、放置第n+1张后,更新该处图片的高度
3、具体代码
1、html代码
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
*{
margin: 0;
padding: 0;
}
#container{
position: relative;
}
.box{
float: left;
border: 1px solid #aaa;
}
.box-img{
width: 188px;
padding: 5px;
}
img{
width: 100%;
}
</style>
<body>
<div id="container">
<div class="box">
<div class="box-img">
<img src="./1.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./2.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./3.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./4.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./5.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./6.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./7.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./8.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./9.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./10.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./1.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./2.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./3.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./4.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./5.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./6.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./7.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./8.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./9.webp" alt="">
</div>
</div>
<div class="box">
<div class="box-img">
<img src="./10.webp" alt="">
</div>
</div>
</div>
<script src="./index.js"></script>
</body>
</html>
2、JS代码
imgLocation('container', 'box')
function imgLocation(parent, child) {
var cParent = document.getElementById(parent)
var cChild = cParent.getElementsByClassName(child)
var screenWidth = window.innerWidth
cChild.onload = function(){
var imgWidth = cChild[0].offsetWidth
var num = Math.floor(screenWidth / imgWidth)
cParent.style.width = `${imgWidth * num}px`
// 操作第 num+1 张
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] = boxHeightArr[minIndex] + cChild[i].offsetHeight
}
}
}
}
3、最后瀑布效果
三、总结
拿到目标需求样式时,首要的并不是代码的实现,而是编程思路-“伪代码”的设计,这一步往往可以让你在接下来的代码编写中,达到事半功倍的效果。
转载自:https://juejin.cn/post/7369534132080656422