JavaScript:实现瀑布流

一、前言:

  瀑布流现在是一个非常常用的布局方式了,尤其在购物平台上,例如蘑菇街,淘宝等等。

 

二、流程:

      1、在html文件中写出布局的元素内容;

      2、在css文件中整体对每一个必要的元素进行样式和浮动设置;

      3、在js文件中动态实现布局,每一个滚动时,都要刷新布局。

 

三、思想:

     实现瀑布流,就是每次当前一列的图片显示完全后,接着要显示下一列时,先找出最短的一列,然后将图片填充上,以此类推...

 

四、代码:

 waterFlow.html:

<!DOCTYPE html>
<html lang="zh-en">
<head>
    <meta charset="UTF-8">
    <title>瀑布流效果</title>
    <link rel="stylesheet" href="waterFlow.css">
    <script src="waterFlow.js" type="text/javascript"></script>
</head>
<body>
    <!--父盒子-->
    <div id="main">
         <!--子盒子-->
         <div class="box">
              <div class="pic">
                  <img src="images/0.png">
                  <div>
                      <span>喜欢:666</span>
                      <span>收藏:999</span>
                  </div>
              </div>
         </div>

        <div class="box">
            <div class="pic"><img src="images/1.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/2.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/3.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/4.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/5.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/6.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/7.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/8.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/9.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/10.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/11.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/12.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/13.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/14.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/15.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/16.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/17.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/18.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/19.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/20.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/21.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/22.png" alt=""></div>
        </div>
        <div class="box">
            <div class="pic"><img src="images/23.png" alt=""></div>
        </div>
    </div>
</body>
</html>
View Code

 waterFlow.css:

*{
    padding: 0;
    margin: 0;
}

#main{
    /*定位*/
    position: relative;
}

.box{
   float: left;
   /*内边距*/
   padding: 15px 0 0 15px;
   /*background-color: red;*/
}

.pic{
    border:1px solid #dddddd;
    padding: 10px;
    background-color: white;
    border-radius: 5px;
}

.pic img{
    width: 165px;
}
View Code

 waterFlow.js:

// ===  值比较  类型比较
function $(id) {
    return typeof id === 'string' ? document.getElementById(id) : id
}


// 当窗口加载完毕
window.onload = function () {
     // 瀑布流布局
     WaterFall('main', 'box');
     // 滚动加载盒子
     window.onscroll = function () {
         if(CheckWillLoad()){ // 具备滚动的条件
            // 造数据
            var dataArr = [{'src': '10.png'},{'src': '11.png'},{'src': '13.png'},{'src': '15.png'},{'src': '17.png'},{'src': '19.png'},{'src': '21.png'},{'src': '23.png'}];

            // 遍历
            for(var i=0; i<dataArr.length; i++){
                // 创建子盒子
                var newBox = document.createElement('div');
                newBox.className = 'box';
                $('main').appendChild(newBox);

                var newPic = document.createElement('div');
                newPic.className = 'pic';
                newBox.appendChild(newPic);

                var newImg = document.createElement('img');
                newImg.src = 'images/' + dataArr[i].src;
                newPic.appendChild(newImg);
            }

            // 重新实现瀑布流布局
           WaterFall('main', 'box');
         }
     }
};


// http://blog.sina.com.cn/s/blog_966e43000101bplb.html
// 瀑布流布局
function WaterFall(parent, child) {
    // ------ 父盒子居中
    // 1.1 拿到所有的子盒子
    var allBox = document.getElementsByClassName(child);
    // 1.2 求出其中一个盒子的宽度
    var boxWidth = allBox[0].offsetWidth;
    // 1.3 求出页面的宽度
    var clientWidth = document.body.clientWidth;
    // 1.4 求出列数
    var cols = Math.floor(clientWidth / boxWidth);
    // 1.5 父盒子居中 css赋值都是String类型
    $(parent).style.width = boxWidth * cols + 'px';
    $(parent).style.margin = '0 auto';

    // ------ 子盒子的定位
    // 1.1 定义高度数组
    var heightArr = [];

    // 1.2 遍历所有的盒子
    for(var i=0; i<allBox.length; i++){
        // 1.2.1 取出单个盒子的高度
        var boxHeight = allBox[i].offsetHeight;
        // 1.2.2 判断
        if(i < cols){ // 第一行
           heightArr.push(boxHeight);
        }else{ // 剩余的行
           // 取出数组中最矮的盒子的高度
           var minBoxHeight = Math.min.apply(this, heightArr);
           // 取出数组中最矮的盒子的索引
           var minBoxIndex = GetMinBoxIndex(heightArr, minBoxHeight);
           // 子盒子定位
           allBox[i].style.position = 'absolute';
           allBox[i].style.top = minBoxHeight +'px';
           allBox[i].style.left = boxWidth * minBoxIndex + 'px';

           // 更新数组中最矮盒子的高度
           heightArr[minBoxIndex] += boxHeight;
        }
    }

    // console.log(heightArr, minBoxHeight, minBoxIndex);
}

// 获取最矮盒子的索引
function GetMinBoxIndex(arr, value) {
    for(var i=0; i<arr.length; i++){
        if (arr[i] == value) return i;
    }
}

// 判断是否具备加载条件
function CheckWillLoad() {
    // 1.1 获取最后的一个盒子
    var allBox = document.getElementsByClassName('box');
    var lastBox = allBox[allBox.length - 1];

    // 1.2 求出高度的一半 + 头部偏离的高度
    var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop;

    // 1.3 求出页面的高度  JS存在兼容性问题 ---> 标准模式  混杂模式
    var clientHeight = document.body.clientHeight || document.documentElement.clientHeight;

    // 1.4 求出页面偏离浏览器的高度
    var scrollTopHeight = document.body.scrollTop;

    // 1.5 判断返回
    return lastBoxDis <= clientHeight + scrollTopHeight;
}
View Code

 

五、效果图:

 

源码:https://files.cnblogs.com/files/XYQ-208910/waterFlow.zip

posted @ 2016-09-22 14:12  XYQ全哥  阅读(462)  评论(0编辑  收藏  举报