通过js原生实现瀑布流(在校大学生小白初学(笔记形式记录自己多为个人理解))

292 阅读2分钟

瀑布流

什么是瀑布流

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。

制作思路

首先第一步,此瀑布流为定宽

既然定宽,那么一共显示几列,我们也就能够计算出来。如下图所示:

列数出来之后,我们拿一个数组来保存一行的高度。什么意思?看下图:

我们按照 4 列来算,一开始一张图片都没有放,每一列的高度都为 0,所以数组里面是 4 个 0

接下来放入第一张图片,找数组里面最小的,目前都是 0,就放在第一列,放完之后需要更新数组里面的最小值

然后依此类推,找数组最小的,会找到第二个 0,往第二列放入图片,更新数组,找到第三个 0,往第三列放入图片,更新数组...

目前第一行满了,该放在第二行了,但是放在第二行的第几列呢?

实际上和上面的算法是一样的,找数组的最小值即可,哪个最小就放在哪一列,放完之后更新数组

新的高度的计算公式:

这一列新的高度 = 这一列高度(数组里面存储的有) + 间隙 + 新的图片高度

然而这只是计算了 top 值,还有 left 值我们需要计算。每张图片的 left 值只和该图片所在的列有关。

js部分


var imgWidth = 220

function creatImg() {

//创建img元素

for (var i = 0; i <= 40; i++) {

var src = `../img/${i}.jpg`//循环拿到照片

var img = document.createElement('img')//创建img元素

img.src = src;//设置图片的src地址

img.style.width = imgWidth; //设置图宽度

//在div里面添加图片

div.appendChild(img)

//排列每一张图片

img.onload = setPositions;

}

}

//获取最大最小值

function getMin(arr) {

var min = Math.min(...arr)

return min

}

function getMax(arr) {

var max = Math.max(...arr)

return max

}

//排列!!!重点在这

function setPositions() {

var containerWidth = div.clientWidth; //获取容器宽度

var columns = Math.floor(containerWidth / imgWidth) //列数 容器宽度除照片的宽度,然后向下取整,得到最多装下多少列图片,剩下的部分作为间隙宽度

var spaceNumber = columns + 1 //间隙数量=列数+1

var leftSpac = containerWidth - columns * imgWidth //间隙总宽度等于容器宽度-(列数*照片宽度)

var space = leftSpac / spaceNumber //每个间隙的空间=总宽度/间隙数

//创建数组保留每一列的高度

var arr = new Array(columns)

arr.fill(0)//给数组填充0

for (var i = 0; i < div.children.length; i++) {

var img = div.children[i];

var min = getMin(arr) //获取最小的那个一个

img.style.top = min + "px"; //开始排列,每张图片都排列到高度最小的那个一列,就是要改变当前列的高度

var index = arr.indexOf(min) // 首先找到这个最小数对应的列数

//新高度 新的高度 = 图片的高度 + 间隙的高度

arr[index] += img.height + space;

//整个top完成,还需要确定间隙的值

//结合上图看

//间隙值和列数有关,index+1保证设置的是距离左边的值以index为0解释

//第一列*平均间隙宽度+0(第一列在数组种为0)*照片宽度

//以第二列为例 2*平均宽度+1*照片宽度 第二列的位置在第一列距离左边的间隙+照片长度+第二列距离第一列的间隙

var left = (index + 1) * space + index * imgWidth;

img.style.left = left + "px";

}

// 因为图片是绝对定位,脱离了标准流,所以无法撑开盒子的高度,所以利用最高的一列撑开盒子

var max=getMax(arr)

div.style.height=max+"px";

}

//函数防抖

var timeId=null;//计时器id

function change(){

window.onresize=function(){

//该函数会在窗口大小改变时重新对图片进行排列

//至此简单的瀑布流已经完成接下来进行防抖

if(timeId){//如果计时器存在则清除掉重新记录新的

clearTimeout(timeId)

}

timeId=setTimeout(setPositions,50)

}

}

function main() {

//加入图片初始化操作

creatImg()

//绑定事件

change()

}

main();

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>

<link rel="stylesheet" href="../css/1.css">

</head>

<body>

<div id="container" class="container">

</div>

<script src="../js/1.js"></script>

</body>

</html>

css部分

.container {

width: 90%;

margin: 0 auto;

border: 1px solid #eee;

position: relative;

}

/* 图片样式 */

.container img {

position: absolute;

transition: all 0.5s;

width: 220px;

}

image.png ps:个人理解,初学小白,大佬多指教