原生JavaScript实现瀑布流

时间:2021-05-04 10:15:29

效果:

   瀑布流布局

运用知识:

   JavaScript/CSS/HTML

中心思想:

   用原生JS计算每个图片的位置然后进行绝对定位

思路:(绝对定位)

   1、计算页面所能承载图片的列数:页面总宽度除以每个图片盒子的宽度
   2、将第一行的图片高度用数组存放起来
   3、计算每一列高度的最小值,获取其索引号,获取其offsetLeft;那么下一张图片绝对定位的位置Top就是高度的最小值,Left就是所获取的offsetLeft
   4、预先加载n张图片,最好超过浏览器的可视高度,其余图片用JS创建新的节点进行加载;当屏幕滚动时触发加载图片的函数,为了不频繁触发该函数,可以设置一个条件加以限制,此例子中触发条件是最后一张图片的高度露出一半时触发加载函数。

源码

html代码:


<!DOCTYPE>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>js原生方法实现瀑布流布局</title>
<link href="css/css.css" rel="stylesheet" type="text/css"/>
<script src="javascript/waterfall.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<div class="box">
<div class="pic">
<img src="images/1.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/2.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/3.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/4.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/5.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/6.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/7.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/8.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/9.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/10.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/11.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/12.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/13.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/14.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/15.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/16.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/17.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/18.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/19.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/20.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/21.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/22.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/23.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/24.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/25.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/26.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/27.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/28.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/29.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/30.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/21.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/22.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/23.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/24.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/25.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/26.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/27.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/28.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/29.jpg" alt="cute animal"/>
</div>
</div>
<div class="box">
<div class="pic">
<img src="images/30.jpg" alt="cute animal"/>
</div>
</div>
</div>
</body>
</html>


css代码:


*{
margin:0;
padding:0;
}
#container{
position:relative;
margin:0 auto;
}
.box{
padding:15px 0 0 15px;
opacity:0;
float:left;
}
.pic{
padding:10px;
border:1px solid #ccc;
border-radius:5px;
box-shadow:0 0 5px #ccc;
}
.pic img{
width:165px;
height:auto;
}


js代码:


window.onload=function(){
//waterfall(container,box);/*box在main中呈瀑布排列*/
waterfall("container","box");
/*假装这是JSON文件*/
var dataInt={'data':[{'src':'images/1.jpg'},{'src':'images/2.jpg'},{'src':'images/3.jpg'},{'src':'images/4.jpg'}]};
/*当滚动屏幕时执行加载页面函数*/
window.onscroll=function(){
if(checkLastPic()){
var container=document.getElementById("container");
for(var i=0;i<dataInt.data.length;i++){
var newBox=document.createElement("div");
newBox.className="box";
container.appendChild(newBox);
var newPic=document.createElement("div");
newPic.className="pic";
newBox.appendChild(newPic);
var newImg=document.createElement("img");
newImg.src=dataInt.data[i].src;
newPic.appendChild(newImg);
}
waterfall("container","box");
}
}


}
/*main是父盒子,box是每个图片外面的框*/
function waterfall(main,box){
/*计算页面的宽度算出可以摆放几列图片*/
var container=document.getElementById(main);//获取父盒子节点
var screenWidth=document.body.offsetWidth;//获得屏幕尺寸
var boxArr=container.getElementsByClassName(box);//获取每一个box
var boxWidth=boxArr[0].offsetWidth;//盒子宽度
var wfcols=Math.floor(screenWidth/boxWidth);//计算列数
container.style.cssText="width:"+boxWidth*wfcols;/*container设置宽度且在css样式表中margin:0 auto可以实现居中*/
//把每一个盒子的高度存放在数组中
var boxHeightArr=[];//存放所有盒子的高度,实际上是每一列的高度
for(var i=0;i<boxArr.length;i++)
{
if(i<wfcols){//实际上boxHeightArr数组中只有wfcols个高度值
boxHeightArr.push(boxArr[i].offsetHeight);
}
else{
var minHeight=Math.min.apply(null,boxHeightArr);//从数组中得到最小值
var minIndex=getMinIndex(boxHeightArr,minHeight);
boxArr[i].style.position='absolute';
boxArr[i].style.top=minHeight;
boxArr[i].style.left=boxArr[minIndex].offsetLeft+"px";
boxHeightArr[minIndex]+=boxArr[i].offsetHeight;//更新最小高度值
}
boxArr[i].style.opacity=1;
}


}
/*得到数组中最小值的索引号,arr为数组,minH为数组中最小的值*/
function getMinIndex(arr,minH){
for(var i in arr){
if(arr[i]==minH) return i;
}
}
/*检测最后一张图片是否露出来一半*/
function checkLastPic(){
var container=document.getElementById("container");
var boxArr=container.getElementsByClassName("box");
var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//考虑兼容性
var checkHeight=boxArr[boxArr.length-1].offsetTop+Math.floor(boxArr[boxArr.length-1].offsetHeight/2);//最后一个图片的一般高度加上这一列的高度offsetHeight;
var documentHeight=document.documentElement.clientHeight+scrollTop;//被卷起的高度加上用户可见的高度
return (checkHeight<documentHeight)?true:false;

}