通过js原生实现瀑布流

瀑布流

什么是瀑布流

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

制作思路

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

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

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

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

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

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

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

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

新的高度的计算公式:

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

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

代码部分

.container {
    width: 90%;
    margin: 0 auto;
    border: 1px solid #eee;
    position: relative;
  }
  
  /* 图片样式 */
.container img {
    position: absolute;
    transition: all 0.5s;
    width: 220px;
  }
  
<!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>

var div = document.querySelector("#container") //获取dom元素
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();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

缔造06

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值