打开小红书,我们可以看到图片是以一种看起来不规律的方式排列,如下:
这种排列方式就是瀑布流式,像瀑布流一样流下,我们看瀑布是不是会感觉很舒服,且视线会跟随水流而下,没错,这样设计的目的是为了使刷东西的人能够不停的往下翻,不停的想知道下面的图片和内容,令人上瘾。 好了,介绍完后,我们就来简单实现这种页面。
首先写html文件里的内容,设计好框架
<div id="container">
<div class="box">
<div class="box-img">
<img src="./img/1.webp" alt="">
</div>
</div>
...20个box,放图片
</div>
container里放20个box,每个box放图片。
其次写css样式:
<style>
*{
margin: 0;
padding: 0;
}
#container{
position: relative;
}
.box{
float: left;
padding: 5px;
}
.box-img{
width: 150px;
padding: 5px;
border: 1px solid #2eec48;
}
img{
width: 100%;
}
</style>
-
*{}设计所有内边距外边距为0(因为初始都会有点内边距和外边距,需要消除) -
#container{}定位position: relative;为box提供父类定位。 -
.box{}设置向左浮动,外边距5px。因为div是块级元素,会单独占用一行,要想图片挨个放一行,测需要
float: left;要想图片之间要有间隙,显得更为美观而不那么拥挤,则设置盒子外边距padding: 5px;。 -
.box-img{}设置盒子大小,外边距以及盒子的边。调整盒子大小,并设置外边距,将盒子的边设置成绿色,宽度为1px,实线。 -
img{}设置图片大小为盒子大小。
最后写js部分:
js是最关键的部分,这就要考验大家的思维和算法
第一行的图片很好排列,无非就是获取用户屏幕宽度,再获取每张图片大小,然后计算出每行可以放几张图片,再获取参考物的坐标放置放下一张的图片。
第n行图片怎么放呢?思路是这样的 获取每一列图片的高度,然后选取最小高度的图片的那一列,获取这列图片的最后一张图片的坐标位置,将图片放到这张图片的下面,最后更新这一列图片的高度,往复循环直到所有图片获取完。
代码:
// 获取到用户屏幕的宽度,决定了一行能放下几图
// 操作下一张图,放到上一行最矮的裂了下面
imgLocation('container', 'box')
function imgLocation(parent, content) {
// 有多少张图
var cparent = document.getElementById(parent)
var ccontent = getChildElement(cparent, content) // document.querySelectorAll('#container .box')
// 每一个box的宽度
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 { // 要操作的
var 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
}
瀑布流是大厂面试经常考的知识点,只要多加理解,多写代码,就可以很轻松回答类似问题,加油!