原生JS实现瀑布流布局

Posted CaseyWei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生JS实现瀑布流布局相关的知识,希望对你有一定的参考价值。

一.瀑布流之准备工作

     首先声明下, 为了方便演示和联系, 我使用的是本地图片, 如果大家有需要的话可以尝试着写下网络的, 不过本地和远端的大致是相同的. 那么我就来简单介绍下本地的瀑布流效果吧, 我们要先准备好八九张图片, 当然啦, 我们实现的是瀑布流效果, 所以最好是高度不相同的, 这样才可以看出来效果, 对吧, 嘿嘿.

二.代码的准备工作

    我们打开开发工具, 先建个html工程, 在内部写下如下代码, 因为是准备工作, 所以刚开始写的都是一些基础性的东西, 就不一一解释了, 直接上代码:

复制代码

<body>
<div id="container">
    <div class="box">
        <div class="boximg">
            <img src="img/1.jpeg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/2.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/3.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/4.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/5.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/6.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/7.gif">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/8.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/9.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/9.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/9.jpg">
        </div>
    </div>
    <div class="box">
        <div class="boximg">
            <img src="img/9.jpg">
        </div>
    </div>

</div>

</body>

复制代码

    很明显这段代码中也就是几个div标签和几个img标签, 所以是很简单的, 就不多说了, 下面我们来布置css样式.

三.css样式布置

    说句比较实在的话, 对于瀑布流而言, 因为我只是简单的模拟下, 所以css样式的定制, 我并没有特别复杂的定制, 只是简单的把边框和容器(div)大小给定制了下, 还有一些颜色, 话不多说, 直接上代码吧

复制代码

/*使用通配符将内外边距都设置为零, 这样看着好看*/
*{
    margin: 0px;
    padding: 0px;
}
/*将主容器的布局方式设置为相对布局*/
#contianer{
    position: relative;
}

.box{
    padding: 5px;
    float: left;
}
/*将承载图片的容器定制颜色及边框大小和圆角*/
.boximg{
    padding: 5px;
    box-shadow: 0 0 5px #ccc;
    border: 1px solid #cccccc;
    border-radius: 5px;
}
/*定制图片尺寸*/
.boximg img{
    width: 250px;
    height: auto;
}

复制代码

  代码中注释已经解释的很清楚了, 就不再过多的赘述了.

四.重点也是瀑布流的难点(JS的实现)

    大家对于瀑布流都不陌生吧, 它主要是顶宽的, 然后根据高度来进行布局, 也就是说在第一行铺满后, 准备排布第二行的时候, 将第二行的第一种图片放在第一行图片高度最小处, 之后依次类推, 先简单的上些代码, 然后一一作解释了, 正所谓有图有真相, 哈哈!

      这就是在未编写js代码时的效果图, 那么按道理来说下面的图片应该放在第一行第二张图片的位置下面, 应该充分利用空白资源, 那么这要如何来实现呢, 接下来我就附上代码来告诉大家了:

复制代码

window.onload = function(){
    waterFlow("container", "box");
   
}
function waterFlow(parent, chirld){
    var wparent = document.getElementById(parent);//获取父级div, 最外级容器
    var allArr = getAllChirld(wparent,chirld);//获取到所有的class为box的容器div
    var wscreenWidth = document.documentElement.clientWidth;//获取屏幕宽度
    var wchirldWidth = wparent.getElementsByTagName("*");//获取所有的标签
    var num = Math.floor(wscreenWidth/wchirldWidth[0].offsetWidth);//这是一个Math算法, 目的是将小数转变为整数,
    // 从而可以知道每行最多容纳几张图片
    wparent.style.cssText = \'width:\'+wchirldWidth[0].offsetWidth*num+\'px;margin:0 auto\';//固定每行摆放个数 和上下左右边距
    //获得每行的最小高度
    getMinHeightOfCols(allArr, num);
}
function getAllChirld(parent,classname){
    //获取所有的标签
    var wchirld = parent.getElementsByTagName("*");
    //创建数组
    var chirldArr = [];
    //遍历wchirld, 将其中className等于classname(传进来的参数)相同的标签放入数组chirldArr中
    for(var i = 0; i<wchirld.length; i++){
        if(wchirld[i].className==classname){
            //因为是位push所以没放进去一个, 都是在数组的最后一个
            chirldArr.push(wchirld[i]);
        }
    }
    //返回该数组
    return chirldArr;
}
function getMinHeightOfCols(chirdArr, num){
    //创建数组, 用来盛放每一行的高度
    var onlyOneColsArr = [];
    for(var i = 0; i<chirdArr.length; i++){

        if(i<num){
            //num为传进来的参数, 即为每行放图片的张数, 此步骤的目的是为了将第一行每张图片的高度遍历出来存放如新数组
            onlyOneColsArr[i]=chirdArr[i].offsetHeight;
        } else {
            //当大于每行存放的图片个数时进入该方法, Math.min.apply这个方法是为了得到数组中的最小值
            var minHeightOfCols = Math.min.apply(null, onlyOneColsArr);
            //此方法的目的是为了得到最小高度图片的下表, 也就是在每行的第几张, 具体方法见下面
            var minHeightOfindex = getminIndex(onlyOneColsArr, minHeightOfCols);
            //定义布局方式为绝对布局
            chirdArr[i].style.position = "absolute";
            //得到下一行图片应放的高度
            chirdArr[i].style.top = minHeightOfCols + "px";
            //得到下一行图片应放于那个位置
            chirdArr[i].style.left = chirdArr[minHeightOfindex].offsetLeft + "px";
            //将两张图片高度相加得到一个新的高度用来进行下一次的计算
            onlyOneColsArr[minHeightOfindex] += chirdArr[i].offsetHeight;
        }
    }

}
//此方法是为了进行最小高度下标的确定
function getminIndex(onlyOneColsArr, min){
    //遍历传进来的高度数组
        for(var i in onlyOneColsArr){
            //如果高度等于最小高度, 返回i即为该图片下标
            if(onlyOneColsArr[i] == min){
                return i;
            }
        }
}
 

以上是关于原生JS实现瀑布流布局的主要内容,如果未能解决你的问题,请参考以下文章

JS原生方法实现瀑布流布局

关于waterfall 瀑布流布局出现布局错乱的问题

[Web] 简单瀑布流布局实现

css 瀑布流布局问题 高手进

瀑布流布局(jq实现)

瀑布流布局