感觉瀑布流布局还真的是不简单...先说一下我是在慕课网上下载的源代码,读不懂的地方看一遍视频,感觉还是不错的。 首先我们先看看效果吧~
我们先仔细的看一看瀑布流的特点啊,首先有一个父容器,他是居中的,这个父容器包含这n个小容器,小容器里面装着图片。小容器有margin,padding,border,图片是等宽不等高的,中间的缝隙相等,不会出现大块的空白。
首先,我们先看html的代码
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="js/waterfall.js"/></script>
<title></title>
</head>
<body>
<div id="main">
<div class="pin">
<div class="box">
![](./images/1.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/2.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/3.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/4.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/5.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/6.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/7.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/8.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/9.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/10.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/11.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/12.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/13.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/14.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/15.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/16.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/17.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/18.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/19.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/20.jpg)
</div>
</div>
<div class="pin">
<div class="box">
![](./images/21.jpg)
</div>
</div>
</div>
</body>
</html>
其实我们在写代码的时候完全可以不用重复这么多的,我们可以用document.createElement()来创建元素并用obj.appendChild挂载到 #main 中,所以大家不要怕代码多。可是我们发居然在小容器里面还有一个容器,这是为什么呢?现在的布局很丑很简陋,先看看吧。
额额额,好傻。现在我们为他加上一点css。
*{padding: 0;margin:0;}//去除浏览器自带样式
#main{ //父容器
position: relative;//相对定位,这里相对于body
margin:0 auto;//左右居中
}
.pin{
padding: 15px 0 0 15px;//设置上边距,左边距为15px
float:left;//向左浮动
}
.box{
padding: 10px;
border:1px solid #ccc;
box-shadow: 0 0 6px #ccc;//灰色阴影
border-radius: 5px;//圆角
}
.box img{//给小容器里的图片设置固定宽度,高度随意
width:162px;
height:auto;
}
这个时候好看了一些,但是有大片的留白,也知道了为什么小容器pin中还有一层小容器,原来是因为要在border外面在加一层边距,可是为什么不用margin还要在套一层用padding呢? 我们先不管哦、
我们再给他加一点js吧
window.onload=function(){
waterfall('main','pin');
}
function waterfall(parent,pin){
var oParent=document.getElementById(parent);// 父级对象
var aPin=getClassObj(oParent,pin);// 获取存储块框pin的数组aPin
var iPinW=aPin[0].offsetWidth;// 一个块框pin的宽
var num=Math.floor(document.documentElement.clientWidth/iPinW);//每行中能容纳的pin个数【窗口宽度除以一个块框宽度】
oParent.style.cssText='width:'+iPinW*num+'px;ma rgin:0 auto;';//设置父级居中样式:定宽+自动水平外边距
var pinHArr=[];//用于存储 每列中的所有块框相加的高度。
for(var i=0;i<aPin.length;i++){//遍历数组aPin的每个块框元素
var pinH=aPin[i].offsetHeight;
if(i<num){
pinHArr[i]=pinH; //第一行中的num个块框pin 先添加进数组pinHArr
}else{
var minH=Math.min.apply(null,pinHArr);//数组pinHArr中的最小值minH
var minHIndex=getminHIndex(pinHArr,minH);
aPin[i].style.position='absolute';//设置绝对位移
aPin[i].style.top=minH+'px';
aPin[i].style.left=aPin[minHIndex].offsetLeft+'px';
//数组 最小高元素的高 + 添加上的aPin[i]块框高
pinHArr[minHIndex]+=aPin[i].offsetHeight;//更新添加了块框后的列高
}
}
}
//通过父级和子元素的class类 获取该同类子元素的数组
function getClassObj(parent,className){
var obj=parent.getElementsByTagName('*');//获取 父级的所有子集
var pinS=[];//创建一个数组 用于收集子元素
for (var i=0;i<obj.length;i++) {//遍历子元素、判断类别、压入数组
if (obj[i].className==className){
pinS.push(obj[i]);
}
};
return pinS;
}
//获取 pin高度 最小值的索引index
function getminHIndex(arr,minH){
for(var i in arr){
if(arr[i]==minH){
return i;
}
}
}
function checkscrollside(){
var oParent=document.getElementById('main');
var aPin=getClassObj(oParent,'pin');
var lastPinH=aPin[aPin.length-1].offsetTop+Math.floor(aPin[aPin.length-1].offsetHeight/2);//创建【触发添加块框函数waterfall()】的高度:最后一个块框的距离网页顶部+自身高的一半(实现未滚到底就开始加载)
var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//注意解决兼容性
var documentH=document.documentElement.clientHeight;//页面高度
return (lastPinH<scrollTop+documentH)?true:false;
//到达指定高度后 返回true,触发waterfall()函数
}
好啦,我们来看看效果
这个时候我们知道了,为什么要多加一个小容器并且使用padding属性了,因为小容器要使用绝对定位。
最后我们在总结一下使用瀑布流布局的步骤或者说是重点。
HTML部分:
- 创建一个父容器;
- 在父容器内部创建n个小容器 使用同一class,比如pin
- 在每一个小容器里面创建一个div 使用用一个class,比如class
CSS部分:
- 父容器使用绝对布局并居中
- 小容器设置上左的内边距padding并向左浮动
- 小容器里的可以写一些美化的东西:比如padding border box-shadow reduis等
- 给div内部的图片设置固定宽度
JavaScript部分:
- 获取小容器的宽度,用可视区域的宽度/小容器的宽度
- 给小容器一个绝对位置并且赋值。