JS 实现瀑布流

作者: ghwaphon | 来源:发表于2016-09-14 23:18 被阅读2025次

在极客学院下载的 JS 基础视屏中提到了瀑布流效果,花了一下午的时间去学习,到现在终于也算有所理解了,自己也动手实现了这么一个效果,来看一下吧。

demo.gif

我个人感觉这个效果还是比较好看的,下面我们就来看看怎么实现吧。

HTML 代码

其实 HTML 的编码是极其简单的,我们去除重复的部分,来看看核心代码

<div id="container">
    <div class="box">
        <div class="box_img">
            <img src="imgs/1.jpg">
        </div>
    </div>
</div>

其实在 container 内部不止一个 div 标签,这里是为了简单,所以将其他的代码都省略了。 这里为什么要设置双层 div 包含住 img 标签呢,这里是为了在后面的 JS 代码中设置 position 属性,到后面自然而然就明白了。

CSS 代码

* {
    margin: 0px;
    padding: 0px;
}

#container {
    position: relative;
}

.box {
    float: left;
    padding: 15px 0 0 15px;
}

.box .box_img {
    padding: 10px;
    border: 1px solid #cccccc;
    border-radius: 5px;
    box-shadow: 0px 0px 6px #cccccc;
}

.box_img img {
    width: 172px;
    height: auto;
}

* 选择器的使用可以说是遭受非议的,有人认为它的杀伤力太大了,不可以轻易的使用,但是作为初学者的我来说,还是十分喜欢使用其去除外边距和内边距。 这里我们为了好看,也是为图片设置了内边距,边框和阴影属性,值得一提的是为了保持所有的图片具有共同的宽度,我们将其设置为统一的 172px,为什么设置为 172px 呢?我随便设的,你可以自己指定,高度的话我们设置成 auto , 建议不要自己指定,不然你还实现什么瀑布流啊?图片的高度宽度都相同,还有什么瀑布流可言,顺序排列不就可以了吗?

我刚开始看瀑布流教学视屏的时候,是非常开心的,为什么呢?因为 HTML 代码和 CSS 代码真的好少哦。可是看到 JS 代码就不开心了,真的好长。好了,不吐槽了,来看看 JS 代码吧。

JS 代码

由于 JS 代码过长,所以我们逐段来分析,下面来看第一段。

function location(parent, child) {
   1  var vparent = document.getElementById(parent);
   2  var childArray = getChild(vparent, child);
   3  var imgWidth = childArray[0].offsetWidth;
   4  var cols = Math.floor(document.documentElement.clientWidth / imgWidth); // 计算每行能容纳多少列
   5  vparent.style.cssText = "width : " + imgWidth * cols + "px;margin:0 auto;";

   6  var boxHeightArray = [];
   7  for (var i = 0; i < childArray.length; i++) {
   8    if (i < cols) {
   9        boxHeightArray[i] = childArray[i].offsetHeight;
   10    } else {
   11        var minHeight = Math.min.apply(null, boxHeightArray);
   12        var minIndex = getIndex(boxHeightArray, minHeight);

   13        childArray[i].style.position = "absolute";
   14        childArray[i].style.top = minHeight + "px";
   15        childArray[i].style.left = childArray[minIndex].offsetLeft + "px";
   16        boxHeightArray[minIndex] = boxHeightArray[minIndex] + childArray[i].offsetHeight;
        }
    }
}

分析一个函数之前,我们首先要知道这个函数要实现的功能是什么?方法的名称叫做 location , 所以该方法肯定要实现一个定位功能?给谁定位?当然是给图片定位!

  • 第 1 - 3 行 : 获取当前 页面中 有多少张图片要展示并且获取图片的宽度。
  • 第 4 行 : 计算当前一行能容纳多少列,也即一行能容纳多少个图片的展示。
  • 第 5 行 : 将承载图片的父节点(其实这个时候就是 container)设置为指定行,并且居中显示。
  • 第 9 行 :将第一行图片的距离页面顶端的高度记录在一个数组中。
  • 第 10 - 16 行 : 获取到第一行中高度最小的那张图片,将其在数组中的下标获取到,然后将下一行的图片放置到高度最小的图片的下方,更新高度值。其实这很像一个计数功能,当我们知道了一行放置多少图片之后,当我们放满了第一行,将高度值存放在数组中,从第二行开始,寻找数组中最小的那个值,然后将图片放在这一列,更新数组值。

在以上代码中我们用到了 两个自定义的方法,分别是 getChild()getIndex(),很容易理解,这里 只粘贴代码,就不在解释。

function getIndex(boxHeightArray, mingHeight) {
    for (var i = 0; i < boxHeightArray.length; i++) {
        if (boxHeightArray[i] == mingHeight) {
            return i;
        }
    }
}

function getChild(parent, child) {
    var contentArray = [];
    var allcontent = parent.getElementsByTagName("*");
    for (var i = 0; i < allcontent.length; i++) {
        if (allcontent[i].className == child) {
            contentArray.push(allcontent[i]);
        }
    }
    return contentArray;
}

其实,通过上述方法,我们就实现了一个瀑布流效果,但是我们还想实现另一个效果,就是我们可以不断下拉,那么这个功能该怎么实现呢?既然想实现下拉动态加载效果,那么我们至少应该在什么时候开始动态加载吧?下面就来实现这么一个功能。

function check() {
    var parent = document.getElementById("container");
    var child = getChild(parent, "box");

    var lastContentHeight = child[child.length - 1].offsetTop;
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    var pageHeight = document.documentElement.clientHeight || document.body.clientHeight;

    if (lastContentHeight <= scrollTop + pageHeight) {
        return true;
    }
}

lastContentHeight 的值是最后一张图片到页面顶部的距离。 scrollTop 的值是当前正在显示的之前隐藏的部分。什么意思呢?举个例子来说,当我们进入一个网页,这个网页右垂直滚动条,那么刚进去时显示的肯定是网页的一部分,还有一部分处于隐藏状态,那么 scrollTop 的值就是从当前可见页面的底部开始从 0 计数的,往下拉,这个值就会递增。 pageHeight 的值就是当前可见页面的高度。那么最后的 if 条件判断是什么意思呢?这个判断语句的意思就是,当我们下拉到最后一张图片的顶部的时候,开始动态加载图片。好了,下面我们去看看加载图片的逻辑代码。

window.onscroll = function () {
    var imgData = {
        "data": [
            {"src": "1.jpg"},
            {"src": "2.jpg"},
            {"src": "3.jpg"},
            {"src": "4.jpg"},
            {"src": "5.jpg"},
            {"src": "6.jpg"},
            {"src": "7.jpg"},
            {"src": "8.jpg"}]
    };

    if (check()) {
        var parent = document.getElementById("container");
        for (var i = 0; i < imgData.data.length; i++) {

            var box = document.createElement("div");
            box.className = "box";
            parent.appendChild(box);

            var boximg = document.createElement("div");
            boximg.className = "box_img";
            box.appendChild(boximg);

            var img = document.createElement("img");
            img.src = "imgs/" + imgData.data[i].src;
            boximg.appendChild(img);
        }

        location("container", "box");
    }
}

其实这段逻辑代码反而好懂,意思就是当我们的页面滑动了,而且符合我们对动态加载图片的判断,即开始创建节点,和我们在 HTML 代码中创建的结构相同,这样我们才可以复用 CSS代码。在底部别忘了调用 location() 函数,不然的话我们在新加载的图片中是无法看到瀑布流效果的。还有一个值得注意的地方,就是这里我们也看到了我们使用的是 window.scroll ,就意味着,我们必须要能够满足能够滑动的事件,说的再通俗一点,就是初始的图片要高于当前浏览器可见的高度。

好了,瀑布流的效果就介绍到这里,大家中秋快乐。

相关文章

  • js/jQuery实现瀑布流

    html中主要代码: 实现瀑布流的js代码: css实现瀑布流只需要三行代码: 实现下拉刷新的js代码: js/c...

  • JS实现瀑布流

    用js实现瀑布流代码,实现下拉过程中图片的自动加载:效果如下: ![]98]ZI}Y[~1]WE9OFBV}}VA...

  • JS 实现瀑布流

    在极客学院下载的 JS 基础视屏中提到了瀑布流效果,花了一下午的时间去学习,到现在终于也算有所理解了,自己也动手实...

  • Js实现瀑布流

    1.使用原生js实现瀑布流效果,demo地址(https://xukeler.github.io/waterfal...

  • JavaScript实现瀑布流效果

    在极客学院下载的js基础视频中学习到了用js实现瀑布流效果,然后自己总结了两个关键的点,一个是瀑布流效果的实现,另...

  • 瀑布流布局

    1: 实现一个瀑布流布局效果 code 2 : 实现一个新闻瀑布流新闻网站 http://js.jirengu.c...

  • 小程序 瀑布流布局 简单易懂 css 及js 两种方法

    css 自带标签 实现瀑布流 有一定的缺陷 建议使用js...

  • 使用js来实现瀑布流效果

    使用js来实现瀑布流效果 瀑布流的实现方法有很多种,我这次采用的是使用绝对定位的方法来实现。页面中包含一个容器ul...

  • js实现瀑布流效果

    瀑布流的特点:宽度确定,高度不确定;通过定位处理的。 每一行添加在高度最低的下面 绝对定位left:图片的宽度*索...

  • 原生js实现瀑布流

    浏览网页的时候经常会遇到瀑布流布局的网站。也许有些读者不了解瀑布流。瀑布流,又称瀑布流式布局。是比较流行的一种网...

网友评论

  • 5bad1c452ce7:没有浏览器适配吧。打开格式都不一样了
  • kidd_hlt:还好看懂了!!!有收获!
    ghwaphon:@kidd_hlt 很高兴帮助到你
  • 西泽大大:给个链接
    ghwaphon:@西泽大大 https://pan.baidu.com/s/1i45ZUUL
  • 一棵树的时光:没看懂,代码看不全呢
    ghwaphon:@一棵树的时光 中午我会将代码共享到百度云,会给你发送链接地址
    一棵树的时光: @千里追风 谢谢。什么链接呢?
    ghwaphon: @一棵树的时光 你好,你可以给我一个链接,我会在午饭时间将验证代码发送给你

本文标题:JS 实现瀑布流

本文链接:https://www.haomeiwen.com/subject/tmzvettx.html