说瀑布流原理其实很简单,原理就是哪列高度和小就将元素放到哪列。那么这就涉及到一个算法了,就是给定一个数组,分成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个数和随意增加,其实现效果如下图
到此,基本上实现了瀑布流的效果,具体精细效果请各位自行添加即可。