搞定阿里面试官:用js实现瀑布流
前端学习之路
当我们在刷小红书或者逛淘宝的时候,你会发现小红书越刷越上瘾,淘宝越逛越想逛;这是为什么呢?难道这些软件有什么魔力吗?到底是什么致使我们越看越上头,其实它正是运用了一种瀑布流的页面布局方式紧紧地抓住了我们的好奇心,页面的内容就犹如飞流直下的瀑布一般,左右两边不对称的格式恰好能够在刷的过程中一直让新内容能够出现在我们的视野之中,吸引着我们的注意。
瀑布流
在现代网页设计中,瀑布流布局(Waterfall Flow)已经成为一种常见的展示方式,尤其在图片墙、产品展示等场景中被广泛应用。它的特点是将内容按照一定规则依次排列,形成类似瀑布流般的视觉效果。在瀑布流布局中,每个内容块的高度可以不同,但宽度通常是相同的,这样可以使得页面看起来更加整洁和美观。瀑布流布局常用于图片墙、产品展示等场景,能够有效利用页面空间,提升用户体验。
在面试的时候,大部分面试官也常常会对瀑布流进行提问;接下来,我将会给大家展示瀑布流的实现方法,请跟随我的步伐一起用js搞定阿里面试官!
HTML、CSS
在实现瀑布流样式之前我们的页面是这样的:
根据上图我们可以快速地编写出它的HTML框架:
<!DOCTYPE html>
<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;
}
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>
由于需要设置的css样式比较少,就直接添加在了HTML代码文件中;页面布局以向左浮动为主。
js
实现瀑布流,主要是通过js代码达到这种布局效果;用编程思维可以分为两大步:1.确定第一行能放几张 n 张图;2.操作第 n+1 张图,摆放它的位置并放在高度最小的那一列。
再进行细分:
// 确定第一行能放几张 n 张图
// 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); // floor向下取整
// 设置父容器宽度为每行图片总宽度
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'; // 设置图片的top值为最小高度
cChild[i].style.left = cChild[minIndex].offsetLeft + 'px'; // 设置图片的left值为对应列的left值
// 更新对应列的高度
boxHeightArr[minIndex] = boxHeightArr[minIndex] + cChild[i].offsetHeight;
}
}
}
以上代码中,获取父容器和子容器后返回的是一个数组,所以调用的时候要用下标cChild[0]
;在盒子模型中,它的内置方法offsetWidth
可以获取当前容器的宽度,同理,offsetLeft
则能得到当前容器的左边距;Math.floor()
方法是数学库中的一个向下取整的方法,即小数部分直接舍去,取整数位;Math.min(...boxHeightArr)
中的...
是对boxHeightArr
数组进行拆分解耦;以上即是实现瀑布流布局的具体思路及代码。
学会了吗?快去动手实现一个吧。
转载自:https://juejin.cn/post/7369838480984031282