JavaScriptWeb前端之路

瀑布流布局

2017-03-24  本文已影响36人  蛋黄肉

感觉瀑布流布局还真的是不简单...先说一下我是在慕课网上下载的源代码,读不懂的地方看一遍视频,感觉还是不错的。 首先我们先看看效果吧~


我们先仔细的看一看瀑布流的特点啊,首先有一个父容器,他是居中的,这个父容器包含这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 中,所以大家不要怕代码多。可是我们发居然在小容器里面还有一个容器,这是为什么呢?现在的布局很丑很简陋,先看看吧。

裸体HTML.png

额额额,好傻。现在我们为他加上一点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;
    }
带css的效果.png

这个时候好看了一些,但是有大片的留白,也知道了为什么小容器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()函数
}

好啦,我们来看看效果

完整.png

这个时候我们知道了,为什么要多加一个小容器并且使用padding属性了,因为小容器要使用绝对定位。

最后我们在总结一下使用瀑布流布局的步骤或者说是重点。

HTML部分:

CSS部分:

JavaScript部分:

上一篇 下一篇

猜你喜欢

热点阅读