在暑期留校期间完成了瀑布流的任务,现在写下这篇博客作为总结以及回顾。
首先来讲下瀑布流的思想:首先将屏幕分成n列,图片有规则的(宽度一致高度随机,除了第一排的图片,其余图片的布局紧接在当前列长度最短的那列,并且在实现霸屏的情况下,如果继续滑动鼠标滑轮,图片数据会继续向下加载,直至不再滑动鼠标滑轮)。
那么现在来看瀑布流的html代码:
<style type="text/css">
#main{
position: relative; /*给整体的瀑布流设置一个大div包住*/
}
.pin{
padding: 15px 0 0 15px;
/*设置每个小块之间的边距,分别上、左各15px,
实际上是为了实现每个块之间的间距*/
float:left; /*设置左浮动 使每个块浮动起来*/
}
.box{
padding: 10px; /*box每个方向上均有10px的内边距*/
border:1px solid #ccc;
box-shadow: 0 0 6px #ccc;
border-radius: 5px;
}
.box img{
width:162px; /*设置图片的宽度一致,高度auto随着
height:auto; 图片原本高度对应变化*/
}
</style>
<body>
<div id="main">
<div class="pin">
<div class="box">
<img src="./images/1.jpg"/>
</div>
</div>
<div class="pin">
<div class="box">
<img src="./images/2.jpg"/>
</div>
</div>
/*以下重复上面一小块*/
</div>
</body>
示例图如下:
从整个布局来看,绿框就是页面显示出来的效果。
然后我们来看,当你现在也布局完成后,你打开网页,会发现大致是如下的效果,
会发现有很多地方空出来,为啥呢?因为图片长度不一致的原因,有的图片占在前面但是长度较长,就会“挡”住后面的图片“上位”。那么现在我们要解决的是怎么让每个图片都根据我们的设定到自己该到的地方,就是让空出来的地方不空出来,也有图片占据。
那我们现在来写一个函数,使得每个图片都到自己相应的位置去:
window.onload=function () {
waterFall();
var arr=['1.jpg','2.jpg','3.jpg','4.jpg','5.jpg',
'6.jpg','7.jpg','8.jpg','9.jpg','10.gif',
'11.jpg','12.jpg','13.jpg','14.jpg','15.jpg',
'16.jpg','17.jpg','18.jpg','19.jpg','20.jpg',
'21.jpg','22.jpg','23.jpg','24.jpg','25.jpg',
'26.jpg','27.jpg','28.jpg','29.jpg','30.jpg',
'31.jpg','32.jpg','33.jpg','34.jpg','35.jpg',
'36.jpg','37.jpg','38.jpg','39.jpg','40.jpg'];
/*利用数组来存储用于瀑布流的数据(图片的src)*/
//当滚动滑动条时触发事件:
window.onscroll=function(){
var oMain=document.getElementById("main");
if(Check){ //Check为检查当前是否满足加载数据的函数,返回值为布尔型
for(var i=0;i<arr.length;i++){
var oBox=document.createElement("div");
oBox.className='box';
oMain.appendChild(oBox);
var oPic=document.createElement("div");
oPic.className='pic';
oBox.appendChild(oPic);
var oImg=document.createElement("img");
oImg.src=arr[i];
oPic.appendChild(oImg);
}
/* 以上执行的步骤是1.创建class为box的div,并将其插入到main后作为子元素;
2.创建class为pic的div,并将其插入到1中创建的box的div中作为子元素
3.向2中创建的pic的div中插入img元素,并为其附上src(来源于先前已经存
储好数据的数组,也可以用json格式)*/
waterFall(); //执行瀑布流的函数(将现有数据(图片)按照我们设置的分布成瀑布流形式)
}
}
}
如下图:
//为第一行之后的数据块设置位置
function waterFall(){
var oMain=document.getElementById("main");
var aBox=getByClass(oMain,'box'); //获取oMain下className为box的所有元素
var oBoxW=aBox[0].offsetWidth;
//获取box的宽度(每个box的宽度一致,所以直接获取第一个便可)
var oScreenW=document.documentElement.clientWidth;
//获取当前屏幕的宽度
var cols=Math.floor(oScreenW/oBoxW); //对列数取整
oMain.style.cssText='width:'+cols*oBoxW+'px;margin:0 auto;'; //让main居中
var arrH=[]; //存储每一列的长度
for(var i=0;i<aBox.length;i++){
if(i<cols){
//当i<列数(即分布第一行时执行以下步骤,将每一列的长度存储进之前定义好的空数组arrH中)
arrH.push(aBox[i].offsetHeight);
}
else{
//在对除第一行之外的其他行的图片做相应处理(即让该图片位于当前页面长度最短的列的后面)
var minH=Math.min.apply(null,arrH);
//将Math.min方法扩展到数组arrH中,获取当前页面中长度最短列的长度minH
var index=GetMinIndex(arrH,minH); //获取长度最短为minH的列的索引(下标)
//对该图片进行样式的设定
aBox[i].style.cssText='position:absolute;';
//让该图片的position:absolute;
//将该图片加到当前页面最短列之后:
//1.设置该图片的left=“长度最短列的的left”
aBox[i].style.left=aBox[index].offsetLeft+'px';
//2.设置该图片的top=“长度最短列的长度”,即设为top
aBox[i].style.top=minH+'px';
arrH[index]+=aBox[i].offsetHeight;
//执行完上述步骤后,最短列的长度改变了,为:之前长度+该图片的长度
}
}
}
如下图:
以下是上述某些小的方法的代码:
//从obj中获取class名称为claName的所有元素,并返回一个数组
function getByClass(obj,claName){
var oArr=obj.getElementsByTagName("*");
var aClass=[];
for(var i=0;i<oArr.length;i++){
if(oArr[i].className==claName){
aClass.push(oArr[i]);
}
}
return aClass;
}
//获取数组中最小值的索引,min为已知
function GetMinIndex(arr,min){
for(var i=0;i<arr.length;i++){
if(arr[i]==min){
return i;
}
}
}
//检查是否满足加载数据块的条件
function Check(){
var oMain=document.getElementById("main");
var aBox=getByClass(oMain,'box');
var oCom=aBox[aBox.length-1].offsetTop;
var oScrollTop=document.body.scrollTop||document.documentElement.scrollTop;
var oScreeH=document.body.clientHeight||document.documentElement.clientHeight;
return (oCom<=oScrollTop+oScreeH)?true:false;
}