专栏首页OECOM解析瀑布流布局实现原理

解析瀑布流布局实现原理

说瀑布流原理其实很简单,原理就是哪列高度和小就将元素放到哪列。那么这就涉及到一个算法了,就是给定一个数组,分成N组,使得这N组的每组和之差最小。

基本算法

下面我们先来说一下这个思路,我们首先应该想到的就是使用递归算法来实现。递归函数的参数应该包含源数组、组数和目标数组(目标数组是一个二维数组)。

function minHeightDifference(arr,groupCount,tarrgetArr){
//doSomething
}

在方法中每次取出源数组的第一个值,然后判断目标数组这个二维数组中哪个数组的和最小,就将该值push到其中,下面我们来看一下简单的实现步骤

if(!Array.prototype.watherFullSum){
    Array.prototype.watherFullSum = function(){
        var temp = 0;
        for(var i=0;i<this.length;i++){
            if(!isNaN(this[i])){
                temp+=this[i];
            }
        }
        return temp;
    }
}

function minHeightDifference(arr,groupCount,tarrgetArr){
    if(arr.length==0){//判断源数组是否为空
        return tarrgetArr
    }
    var groupArr =[];
    if(!tarrgetArr){
        groupArr = Array.apply(null,new Array(groupCount)).map((item)=>0)
        //初始调用无需填写目标数组,创建一个长度为groupCount的全为0的空数组
    }else{
        groupArr = tarrgetArr
    }


    var tempArr =[];
    for(var i=0;i<groupArr.length;i++){
        tempArr[i] = groupArr[i] instanceof Array ? groupArr[i].watherFullSum():0
    }
    //查找最小高度是哪列
    var min = Math.min.apply(null,tempArr);
    var minIndex = tempArr.indexOf(min);
    //如果不是数组的话,则生成一个空数组
    if(!(groupArr[minIndex] instanceof Array)){
        groupArr[minIndex] = [];
    }
    groupArr[minIndex].push(arr[0]);

    return minHeightDifference(arr.slice(1),groupCount,groupArr)
}

上面的代码及注释很清晰,不在额外赘述,调用的时候就很简单了

minHeightDifference([1,2,3,4,2,3,4,5,1,2,3,4,2,3,1,5,2,7],4)

实现瀑布流功能

对于实现瀑布流功能的话,我们只需要构成一个传入的数组即可,数组内容为元素的高度,但是为了方便操作元素位置,我们需要对这个数组进行一下改造

var x = [{dom:obj,height:height}]

改造成上述代码格式,那么上面的算法代码也需要进行相应的修改:

if(!Array.prototype.watherFullSum){
    Array.prototype.watherFullSum = function(){
        var temp = 0;
        for(var i=0;i<this.length;i++){
            if(!isNaN(this[i].height)){
                temp+=this[i].height;
            }
        }
        return temp;
    }
}

function minHeightDifference(arr,groupCount,tarrgetArr){
    if(arr.length==0){
        return tarrgetArr
    }
    var groupArr =[];
    if(!tarrgetArr){
        groupArr = Array.apply(null,new Array(groupCount)).map((item)=>0)
    }else{
        groupArr = tarrgetArr
    }


    var tempArr =[];
    for(var i=0;i<groupArr.length;i++){
    tempArr[i] = groupArr[i] instanceof Array ? groupArr[i].watherFullSum():0
    }
    var tempHeightArr = !isNaN(tempArr[0])?tempArr:tempArr.map(item=>item.height)
    var min = Math.min.apply(null,tempHeightArr);

    var minIndex = tempHeightArr.indexOf(min);
    if(!(groupArr[minIndex] instanceof Array)){
        groupArr[minIndex] = [];
    }
    groupArr[minIndex].push(arr[0]);

    return minHeightDifference(arr.slice(1),groupCount,groupArr)
}

调用就很简单了:

var xms = [];
Array.from(document.querySelectorAll("#test>div")).map(item=>{
    xms.push({'dom':item,'height':item.offsetHeight});
})

var result = minHeightDifference(xms,4);
var x = ''
var maxIndex = Math.max.apply(null,result.map(item=>item.length));
for(var i=0;i<maxIndex;i++){
    result.map((item,key)=>{
        if(item[i]){

        item[i].dom.style.top = item.slice(0,i).watherFullSum();
        item[i].dom.style.left = item[i].dom.offsetWidth*key;
        }
    })
}

我们的html结构是这样的

<html>
<head>
<title>瀑布流</title>
<style>
#test div{
border:1px solid #000;
    display:inline-block;
    position:absolute;
    width:100px;
    box-sizing:border-box;
}
#test{
    width:450px;
    position:relative;
}

</style>
</head>

<body>
<div id="test" >
    <div style="height:83px">1</div>
    <div style="height:103px">2</div>
    <div style="height:84px">3</div>
    <div style="height:56px">4</div>
    <div style="height:78px">5</div>
    <div style="height:93px">6</div>
</div>
</body>
</html>

上面的html结构我省略了一部分,后面的div个数和随意增加,其实现效果如下图

到此,基本上实现了瀑布流的效果,具体精细效果请各位自行添加即可。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 去除inline-block元素间间距

    将代码执行之后我们会发现这个宽度为900的div居然放不下这三个宽度为300的a标签。原因在于他们之间有一个间隔。下面我来说一下如何去除这个水平间距和垂直间距。

    无邪Z
  • JSON.stringify出现 “Converting circular structure to JSON”

    JSON.stringify大家已经不陌生了,是一个将json对象转换为字符串的方法。但是如果你在浏览器控制台中输出 JSON.stringify(window...

    无邪Z
  • css3实现元素圆周运动

    在网页的编写中,好多特效都是通过js来实现,但是还有很多通过css3实现的特效,并且这种方法实现的特效不需要引入外部文件,只需要短短几行代码即可实现,下面这段代...

    无邪Z
  • Spark scala 操作

    黑白格
  • 生成一个指定长度的随机数

    生成随机数在日常工作中的使用率也很高。虽说Python标库自带了生成随机数的功能。但是我想写一个函数,既可以生成数字,又可以生成字符串。而且还可以指定长度,自由...

    TalkPython
  • 【CSS】202-23个CSS垂直居中技巧汇总

    自古以来(是有多?~),网页CSS的垂直居中需求始终没有停过,而其困难度也始终没有让人轻松过,经过了每位开发先烈的研究后,据说CSS的垂直居中技巧已达到近十种之...

    pingan8787
  • 成功最大的捷径是读一流的书

    用户1756920
  • .Net Core in Docker极简入门(下篇)

    上一篇【.Net Core in Docker极简入门(上篇)】讲解了docker的一些基本命令和操作,并成功构建了自己的asp.net core web应用的...

    xhznl
  • 除了腾讯和阿里之外,谁是下一个加入千亿美金俱乐部的公司?

    在中国互联网行业,超过千亿美金市值的公司只有两家:腾讯和阿里。因此,在国内形成了腾讯系和阿里系两大阵营,两家不断的跑马圈地,扩大势力范围。按照资本市场的说法,估...

    光荣与梦想1987
  • OpenGL ---渲染流水线之世界矩阵,相机变换矩阵,透视投影变换矩阵

    https://blog.csdn.net/qq_29523119/article/details/78577246

    用户1148525

扫码关注云+社区

领取腾讯云代金券