在 Kayo 的上一篇文章轻图床的新前端与瀑布流布局曾经简略介绍过瀑布流布局,所谓的瀑布流效果就正如轻图床首页效果那样,多个内容相近的栏目紧密排列,尽量使到栏目间的间隙最小(即流体布局),并且随着页面滚动条向下滚动,新的数据会追加至当前页面的尾部直到所有数据加载完毕(滚动触发的 Ajax 翻页)。本文将会介绍如何实现瀑布流布局中的 Ajax 翻页,至于如何实现栏目间的紧密排列,本文将会简略介绍但不在重要的讨论范围。

2013/12/23 更新

轻图床已经全新改版,去掉原有的瀑布流布局,需要参考原有的瀑布流布局效果可以浏览这个另外制作的 Demo(只保留瀑布流翻页和第一张图片的链接,其他的功能入口已经去掉)。

一.实现原理

实现瀑布流布局主要分为两个部分,一是实现流体布局,这里我们采用绝对定位的方式实现,而是滚动触发的 Ajax 分页,这里采用 jQuery 的 Ajax 实现。

第一部分将会采用 Masonry jQuery plugin 。Masonry jQuery plugin 是一款实现流体布局的 jQuery 插件,下文将以轻图床的首页 HTML 为例,给出一个 Masonry 流体布局的实例。第二部分使用 jQuery 的 scroll() 事件触发 Ajax ,触发后使用 jQuery 的 ajax() 方法异步加载新内容,下文将给出完整实例。

二.Masonry 实现的流体布局

假设网站中的 HTML 如下

1
2
3
4
5
6
7
8
9
10
11
<div id="content">
    <!-- 包含所有图片的容器 -->
    <div id="thumbs">
        <!-- 各个图片的容器 -->
        <div class="imgbox"></div>
        <div class="imgbox"></div>
        <div class="imgbox"></div>
        <div class="imgbox"></div>
        <div class="imgbox"></div>
    </div>
</div>

Masonry 采用绝对定位进行流体布局,因此还需添加如下的一段 css

1
2
#thumbs {position: relative; width: 895px; padding: 10px; }
.imgbox {position: absolute; }

则可以在 js 中添加以下一段 jQuery 代码实现流体布局(需先在 head 中添加 jQuery 的库与 Masonry 的插件库, Kayo 测试 jQuery 库为 1.6.2 的版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
$(function() {
    // #thumbs 为包含所有图片的容器
    var $container = $('#thumbs');
    // 使用 imagesLoaded() 修复该插件在 chrome 下的问题
    $container.imagesLoaded(function(){
      $container.masonry({
        // 每一列数据的宽度,若所有栏目块的宽度相同,可以不填这段
        columnWidth: 279,
        // .imgbox 为各个图片的容器
        itemSelector : '.imgbox'
      });
    });
});

这样便实现了网页内容的流体布局,不过这仅仅是第一页的流体布局,下面详细介绍如何获取新一页的内容,最后在文末给出完整的瀑布流布局实例。

三.Ajax 分页实现瀑布流

1.通过 Ajax 的方式获取下一页的内容

我们需要网页中具有如下 HTML 结构的导航, next_link 为下一页的 url。

1
2
3
<div id="page_nav">
    <a href="next_link">下一页</a>
</div>

相应的 css

1
#page_nav {clear: both; text-align: center; }

以下这段代码为通过 Ajax 的方式获取下一页的内容,并追加到当前内容的末尾。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
nextHref = $("#next_page a").attr("href");
// 给浏览器窗口绑定 scroll 事件
$(window).bind("scroll",function(){
    // 判断窗口的滚动条是否接近页面底部
    if( $(document).scrollTop() + $(window).height() > $(document).height() - 10 ) {
        // 判断下一页链接是否为空
        if( nextHref != undefined ) {
            // Ajax 翻页
            $.ajax( {
                url: $("#page_nav a").attr("href"),
                type: "POST",
                success: function(data) {
                    result = $(data).find("#thumbs .imgbox");
                    nextHref = $(data).find("#page_nav a").attr("href");
                    $("#page_nav a").attr("href", nextHref);
                    $("#thumbs").append(result);
                }
            });
        } else {
            $("#page_nav").remove();
        }
    }
});

2.对追加的内容进行流体布局

熟悉 jQuery 的童鞋应该会了解 js 对于通过 Ajax 方式插入到页面中的元素并不起作用,但在这里并不需要作出如使用 live() 等处理,因为 Masonry 已经在内部作出类似的处理并且默认起效,因此只需在 Ajax 成功执行后的回调函数中调用 masonry() 方法即可。

1
2
3
4
$newElems = $result;
$newElems.imagesLoaded(function(){
    $container.masonry( 'appended', $newElems, true );
});

3.对 Ajax 翻页过程作出修饰

在上面的过程中已经有完整的瀑布流布局,但是翻页过程中并没有任何提示,而且直接插入多张图片可能会影响用户体验,因此需要对翻页过程作出一些修饰,下面给出完整代码。

这里需要增加一个如下的元素,用于提示正在加载新内容或提示已到了最后一页。

1
2
3
<div id="page_loading">
    <span>给力加载中……</span>
</div>

相应的 css

1
#page_loading {display: none; background: #111111; opacity: 0.7; height: 60px; width: 220pxpadding: 10px; position: absolute; bottom: -50px; left: 330px; }

下面是完整的 Ajax 翻页代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
nextHref = $("#next_page a").attr("href");
// 给浏览器窗口绑定 scroll 事件
$(window).bind("scroll",function(){
    // 判断窗口的滚动条是否接近页面底部
    if( $(document).scrollTop() + $(window).height() > $(document).height() - 10 ) {
        // 判断下一页链接是否为空
        if( nextHref != undefined ) {
            // 显示正在加载模块
            $("#page_loading").show("slow");
            // Ajax 翻页
            $.ajax( {
                url: $("#page_nav a").attr("href"),
                type: "POST",
                success: function(data) {
                    result = $(data).find("#thumbs .imgbox");
                    nextHref = $(data).find("#page_nav a").attr("href");
                    $("#page_nav a").attr("href", nextHref);
                    $("#thumbs").append(result);
                    // 把新的内容设置为透明
                    $newElems = result.css({ opacity: 0 });
                    $newElems.imagesLoaded(function(){
                        $container.masonry( 'appended', $newElems, true );
                        // 渐显新的内容
                        $newElems.animate({ opacity: 1 });
                        // 隐藏正在加载模块
                        $("#page_loading").hide("slow");                            
                    });
 
                }
            });
        } else {
            $("#page_loading span").text("木有了噢,最后一页了!");
            $("#page_loading").show("fast");
            setTimeout("$('#page_loading').hide()",1000);
            setTimeout("$('#page_loading').remove()",1100);
        }
    }
});

四.备注

本文给出一种完整的瀑布流布局实现方案,其中重点讲述的 Ajax 翻页以一个较为普遍的实例介绍,该代码可以通用于各种站点的 Ajax 翻页,并不局限于瀑布流布局,并且文中主要讲述布局中的 js 部分,关于后台的实现并没有详述。另外该 Ajax 翻页的代码实例并不是轻图床中的代码,因为轻图床中还有切换为手动导航的功能,因此其功能代码比较复杂,有兴趣可以查看轻图床的 js 源码。