JS的瀑布流布局

1. 了解瀑布流的实现原理

瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式。视觉表现为参差不齐的多栏布局,最早采用此布局的是网站是 Pinterest,后逐渐在国内流行。
 大部分以图像为主且等宽不等高,可以有效的降低界面复杂度,节省空间,对于触屏的设备来说,它的交互方式更符合视觉观感;但不利于seo的优化有时会有额外的复杂度。
 所有盒子当中有一个父盒子和许多子盒子,由子盒子相对于父盒子进行定位,子盒子通过left和top对页面进行位置定位。第一行盒子随机排列,第二行根据第一行盒子的长度从低到高进行紧凑排列,第三行根据第二行高度…………。
 
 ![定位图例]()
 
 将盒子的高度统一放到一个数组,在数组中找到最矮的高度取出索引再加上盒子的边框,就是第二行第一个盒子的top,第一个盒子的left由最矮盒子的前几个盒子宽度之和再加上边框便可以对盒子进行定位,以此类推。

2. 搭建静态界面

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>瀑布流</title>
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
<!--父盒子-->
<div id="main">
    <!--子盒子-->
        <div class="box">
            <div class="pic">
                <img src="images/0.jpg" alt="">
                <div>第一次瀑布流</div>
                <div>用js实现</div>
            </div>
        </div>
    <div class="box">
        <div class="pic">
            <img src="images/2.jpg" alt="">
        </div>
    </div>
    <div class="box">
        <div class="pic">
            <img src="images/3.jpg" alt="">
        </div>
    </div>
    …………
</div>

index.css

*{
    padding: 0;
    margin: 0;
}

/*父盒子*/
#main{
    position: relative;

}
#main .box{
    /*background-color: red;*/
    /*浮动*/
    float: left;
    padding: 15px 0 0 15px;
}
#main .pic{
    border: 1px solid #dddddd;
    padding: 10px;
    background-color: white;
    border-radius: 5px;
}

.pic img{
    width: 165px;
}
    <script src="js/index.js"></script>
</body>
</html>

3. JS实现父标签居中

居中位置的宽度为当前页面有效宽度除以盒子的宽度。
![	offset系列函数图示]()

4.JS实现瀑布流布局

取出页面当中所有的盒子,拿到他们的个数和宽度,窗口的宽度再除以个数就能够算出一个窗口最多能显示的列数(会随着窗口的拉长和变宽进行变化)。

//实现瀑布流布局
	function   WaterFall(parent,child){
	//父标签居中
	//1.1拿到所有的子盒子
	var allBox = document.getElementsByClassName(child);
	//alert('allBox');
	//1.2求出其中一个盒子的宽度 
	var boxWidth = allBox[0].offsetWidth;
	//console.log(boxWidth);
	//1.3获取窗口的宽度
	var cilentWidth = document.body.clientWidth;
	//1.4求出目前的列数 
	var cols = Math.floor.(clientWidth/boxWidth);
	//1.5父标签居中 
	$(parent).style.width = boxWidth * cols + 'px';
	$(parent).style.margin = '0 auto';
	
}

瀑布流需要一行当中最矮的子盒子居中,于是先便利所有的子盒子,取出每一个盒子的高度,找到最矮的盒子在数组中的索引。

//1.2.3从高度数组取出最矮盒子高度
    var minBoxHeight = Math.min.apply(null,heightArr);
   //1.2.4取出最矮盒子在数组中的索引
    var minBoxIndex = getMinBoxIndex(heightArr,minBoxHeight);
   //1.2.6 更新高度数组中最矮高度
    heightArr[minBoxIndex] +=boxHeight;

    function getMinBoxIndex(arr,val) {
            for(var i in arr){
                if(arr[i]===val) return i;
        }
        
    }

5. JS实现瀑布流和滚动设置

需要判断是否具有滚动加载的条件:

1.拿到最后一个盒子

var allBox = document.getElementsByClassName('box');
   var lastBox = allBox[allBox.length -1];

2.求出它的高度以及头部偏离页面的位置

var lastBoxDis = lastBox.offsetHeight * 0.5 +lastBox.offsetTop;

3.求出页面的高度

var clientHeight = document.body.clientHeight || document.documentElement.clientHeight;

4.求出页面偏离浏览器的高度

var scrollTopHeight = document.body.scrollTop || document.documentElement.scrollTop;

5.判断返回

return lastBoxDis <= clientHeight + scrollTopHeight;

当页面的高度与偏离浏览器的高度之和大于或等于最后一盒盒子的一半高度以及头部的偏离位置时进行滚动加载。

6. JS实现瀑布流的添加盒子

具有滚动加载的条件时,创建一个字典来存放本地图片数据或者图片超链接利用for循环进行重复加载for循环里的新盒子和图像标签。
var data = {'imgData':[{'src':'10.jpg'},{'src':'12.jpg'},{'src':'30.jpg'},{'src':'31.jpg'},{'src':'32.jpg'},{'src':'33.jpg'},{'src':'34.jpg'}]};
            // 循环加载重复数据
            for(var i=0; i<data.imgData.length; i++){
                // 取出单个数据对象
                var item = data.imgData[i];

                // 创建新的盒子放到父盒子中
                var newBox = document.createElement('div');
                newBox.className = 'box';
                //1.5添加到父盒子中
                $('main').appendChild(newBox);
                //1.6里面的盒子
                var newPic = document.createElement('div');
                newPic.className = 'pic';
                newBox.appendChild(newPic);
                //1.7图像标签
                var newImg = document.createElement('img');
                newImg.src = 'images/' + item.src;
                newPic.appendChild(newImg);
            }

创建完之后需要进行重新的布局和排列。

WaterFall('main','box');

瀑布流常用于电商平台、各种购物app中,所以需要能够同时兼容多种不同尺寸设备,初学第一使用js来做一个比较完整的网页,如有不足,请多多指教。