今天突然想起在极客学院看到过一个视频学习, 是关于JS瀑布流的教程。于是在闲暇之余,便点进去看了,结果只能看完第一个教程,剩下两个需要付费。好奇的心已经被勾起,所以不肯罢休的我只能找度娘了。
于是找到了一位coder的代码,学习了一下,然后自己再跟着思路自己搞了一个出来。
这是那位coder的文章地址:http://www.cnblogs.com/slowsoul/archive/2013/02/10/2909746.html
前台页面:
<body>
<div id="container"> <!-- 图片最外层DIV -->
<div class="box">
<div class="box_img"> <!-- 包裹着图片的DIV -->
<img src="images/1.jpg" alt="" />
</div>
</div>
<div class="box">
<div class="box_img">
<img src="images/2.jpg" alt="" />
</div>
</div>
<div class="box">
<div class="box_img">
<img src="images/3.jpg" alt="" />
</div>
</div>
</div>
</body>
CSS:
#container
{
position:relative;
}
.box{
padding:5px;
float:left; /*让图片浮动*/
}
.box_img{
padding:5px;
border:1px solid #ccc;
box-shadow: 0 0 5px #ccc;
border-radius:5px;
position: relative;;
}
.box_img img{
width:150px; /*设定图片宽度为150px,高度则让其自动适应 */
height:auto;
}
JS:
重要的部份来了,在学习过程当中,我在看完极客学院的第一个视频后,并没有得到思路,视频只是介绍了设置图片的样式和获取图片的过程,然后在找到其他coder的代码,仔细读过之后,才知道,重要的过程是:
(1)在重新排列图片的时候,第一行图片,正常摆放。从第二行开始,需要统计当前每一列已摆放的高度,然后算出当前累计高计最小的那一列,将下一张待排列的图片放到该列上。
(2)如图所示,那么比如第一列当前累计高度最小,那么下一张等排列的图片A就会被放到第一列上去。变成下面这样:
(3)如此循环,直至把所有的图片都摆放完就OK了。
(4)那么问题来了,如果当窗口大小发生变化时,又如何处理?答案是再重复(1)~(3)的过程就行了,只不过需要重新计算一行当中可以摆放多少张图片。
代码如下:
window.onload = function(){
imgLocation('container','box'); /* 加载时进行调用 */
}
window.onresize = function(){
imgLocation('container','box'); /* 当窗口大小发生变化时需要重新排列图片 */
}
/*************************************
summary:排列图片
input:
parent - 图片容器
content - 获取的子元素ID
**************************************/
function imgLocation(parent,content){
var cparent = document.getElementById(parent);
var ccontent = getChildElement( cparent, content ); //将parent下的多个content全部取出
var imgWidth = ccontent[0].offsetWidth; //元素宽度,即图片的指定宽度
var colsNum = Math.floor( document.documentElement.clientWidth / imgWidth ); //一行能放的个数 = 文档宽度 / 单个图片宽度
cparent.style.cssText = "width:" + (imgWidth)*colsNum + "px; margin: 0 auto;"; //设置容器样式和宽度,使图片容器能够跟随窗口大小变化排列
setColumnAllHeight(ccontent, colsNum); //进行计算和设置
}
/***********************************************
summary:获取parent下指定的content子元素
input:
parent - 父对象
content - 指定的className字符串
output:
返回parent下的所有指定content子元素数组
************************************************/
function getChildElement(parent,content){
var contentArr = [];
var allContent = parent.getElementsByTagName('*'); //获取所有子元素
for( var i=0; i<allContent.length; i++){
if( allContent[i].className == content ){ //进行筛选
contentArr.push(allContent[i]);
}
}
return contentArr;
}
/*****************************************
summary:获取每列中所有图片相加的高度
input:
elementArr - 元素数组
rowSize - 一行放置的元素个数
output: 返回计算出每列图片总高度的数组
*****************************************/
function setColumnAllHeight(elementArr,rowSize){
clearStyle(elementArr); //清除样式,这个可能是我的样式问题
var colTotal = []; //用于统计累计高度的数组
for( var i=0; i<elementArr.length && i< rowSize; i++ ) //初始化,因为每行只能放rowSize个,先把第一个的高度进行初始化数组
{
colTotal[i] = elementArr[i].offsetHeight;
}
for( var i=rowSize; i<elementArr.length; i++ ){
var minHIndex = getMinHeightIndex(colTotal); //获取当前在累计高度数组中最小值的索引
elementArr[i].style.position = 'absolute'; //将其摆放到该列上
elementArr[i].style.top = colTotal[minHIndex] + 'px'; //图片的top值就等于累计高度数组中最小值
elementArr[i].style.left = elementArr[minHIndex].offsetLeft + 'px'; //距离网页左边的距离等于该列的左边距离
colTotal[minHIndex] += elementArr[i].offsetHeight; //然后更新累计高度数组
}
}
/*************************
summary:清除样式
*************************/
function clearStyle( arr ){
for( var i=0; i<arr.length; i++ ){
arr[i].style.cssText = '';
}
}
/*******************************
summary:获取数组中最小值的索引
input:
arr - 数组
*******************************/
function getMinHeightIndex( arr ){
var index = -1;
var minH = Number.MAX_VALUE;
for( var i in arr ){
if( arr[i] < minH ){
minH = arr[i];
var index = i;
}
}
return index;
}
完成后,运行截图如下:
总结:
其实瀑布流也没有想象中那么难,很多好的设计都是人想出来的,只要有想法,敢于实践,必定成功!我的这个demo多多少少还是有一些小问题,后面可以改进下,希望对大家有所帮助!