文档章节

JQuery实现照片瀑布流

postbird
 postbird
发布于 2016/05/04 16:01
字数 2300
阅读 26
收藏 1

JQuery实现照片瀑布流

摘要:总所周知,百度搜图结果下拉会越来越多自动呈现,成为瀑布流。想要打造类似百度图片搜索的瀑布流不是困难的事情,通过javascript也能实现只是实现的比较麻烦,通过jquery实现50+行代码即可。而且相比百度的样式,更加自由化!

废话不多说,先上图:

下图最终的效果图,比较丑,是因为图片我没有经过处理,随便找的图片。

【照片特点】宽度全部相同,高度不相同。
(注:百度图片宽度不同,高度相同—改版之后)

postbird


下面就是实现瀑布流:

一、原理简介

二、文档列表

三、实现过程

四、相关问题


一、原理:

1、从上图可以看出,瀑布流无非是让高度不想同的图片能够按照一定的规律,顺序排列下来。下面给出一示意图,介绍瀑布流原理。

postbird

假设一排网页只能显示四张图片,第一排蓝色四张图片已经显示完成。可以看出,第二排的排列是无顺序的,或者说是某种隐藏的顺序。
什么意思呢?
第二排第一张一定是放在第一排高度最短的那张图片后面的。【请仔细斟酌着句话】
然后依次根据高度进行放置第二排的图片。为什么要这样子防治呢?无非是为了更好地贴合第一排的摆放情况,从而达到无缝对接(这里的无缝是指本实例中,每张图片的外边距都为0),最终形成瀑布流。
请思考,第三排第一张图片应该摆放在那里? A/B/C/D??

而瀑布流的主要思想就是按照这种顺序进行排列。

当然最终的屏幕滚动监听属于高级思想的扩展。


**

二、本实例文档说明

**

  • img文件夹
    • 存放十张图片
  • jquery.js
  • app.js (瀑布流实现js)
  • style.css (图片样式控制)
  • index.html (显示界面)

这里写图片描述

这里写图片描述


**

三、jquery实现瀑布流

首先是**

index.html

**代码说明:

很简单就是放了几个div,然后几张图片:

主要结构为:

  • 图片放在class为content的盒子中,然后父盒子是box,然后外面最大为contianer。
  • 头部也很简单。

    (为方便查看,将图片的div只写了一个,实际上是写了20多个。)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Jquery 瀑布流</title>
    <link rel="stylesheet" href="./style.css">
    <script src="./jquery.js"></script>
    <script src="./app.js"></script>
</head>
<body>
    <div id="container">
        <div class="box">
            <div class="content">
                <img src="./img/1.jpg" alt="1">
            </div>
        </div>
    </div>
</body>

**

style.css

**代码说明:

唯一注意的是:

所有的图片宽度都应该相等,只是高度不等。

/* 第二排第一张图片应该放在第一排中高度最小的图片的下方. */
*{ padding:0; margin:0; }/*消除所有的边距*/
.box{ position:relative; float:left; }/*所有盒子左浮动*/
.content{ padding:10px; border:1px solid #ccc; box-shadow: 0 0 5px #ccc; border-radius:5px; }/*盒子基本样式,即图片的基本状态*/
.content img{ width:190px; height:auto; }/* 所有的图片需要等宽度!!! */

**

app.js

**代码说明:

第一部分:实现第二排第一张图片放在第一排高度最小的图片的下方.

通过函数 imgLocation() 实现

基本思想:

  • 操作DOM来获取盒子的宽度,随便一个DOM IMG就能做到
  • 通过img宽度和window窗口宽度来计算一排能放几张图片
  • 将第一排的图片的高度存在数组boxArr[ ]中,为了后面的高度比较
  • 放置第二排时,首先考虑第一排盒子的高度,从数组中获取最小高度,然后图片的位置确定。
  • 图片位置确定的方式很简单:

$(value).css({
‘position’:’absolute’,
‘top’:minBoxHeight,
‘left’:box.eq(minBoxIndex).position().left
});

        //通过上述代码就能做到,其中value为返回的迭代对象,通过操作css定位来固定位置。

- 最后很重要的一步:添加图片后,该列上的图片高度实际上是变化了,因为高度要加上刚放上去的图片的高度,因此需要进行高度的计算后,重新放在数组中,否则就会出现第二排开始,所有图片都叠在一起了。

【详细解释,见代码!!!】

function imgLocation(){
    var box=$('.box');
    var boxWidth=box.eq(0).width();
        /* 通过qu(0)来获取第一个盒子的宽度 宽度都相同,因此获取那个box的宽度都可以。 */
    var num=Math.floor($(window).width()/boxWidth);
        /* 计算一排能放几个图片 num 取整数。 */
    var boxArr=[]; //存储盒子的高度
    box.each(function(index,value){
        /* index:确定从哪个图片开始 value:确定当前是哪个对象 */
        // console.log(index+" "+value);
        var boxHeight = box.eq(index).height();
            /* 获取每个盒子的高度 其中第一排直接放在数组中。 */
        if(index<num){
            boxArr[index] = boxHeight;
        }else{
            var minBoxHeight=Math.min.apply(null,boxArr);
            var minBoxIndex=$.inArray(minBoxHeight,boxArr);
            /* 当放置第二排时,需要考虑第一排的高度 获取最小盒子的高度 从数组中获取最小盒子的位置,从而为了放置下一排的盒子。 */
             $(value).css({
                 'position':'absolute',
                 'top':minBoxHeight,
                 'left':box.eq(minBoxIndex).position().left
             });
             /* 获取图片的对象,然后对图像进行操作。 实际上操作的是box,位置的放置通过CSS来控制。 */
             boxArr[minBoxIndex]+=box.eq(index).height();
             /* 当第二排的第一张图片添加完后,重新计算高度,否则所有的图片都叠在 第一排的最低的图片下面。 */
        }
    });
}

通过上述函数,就能够灵活的操作图片的位置摆放,但是有一个很重要的问题没有解决:

我们的图片是不确定数量的,需要通过浏览器滚动监听来实现相关的图片加载,而这一步又应该怎么实现呢?

其实这个也不难。

首先需要了解一个函数:

scrollside()

函数的主要作用为:

判断是否需要加载图片,通过监听浏览器窗口高度来实现
具体为:
1、先获取最后一张图片的高度,也就是我们之前固定的能够铺满整个浏览器的一次页面的图片中的最高高度。
2、获取屏幕高度,再获取滚动的高度(滚动距离顶端的高度)。
3、当前文档高度+滚动高度 如果大于当前图片的最高高度时就进行图片的加载!!

代码如下:

function scrollside(){
    var box=$('.box');
    var lastboxHeight = box.last().get(0).offsetTop+Math.floor(box.last().height()/2);
        /* 获取最后一个盒子的高度也就是最高的盒子的高度。 */
    var documentHeight=$(document).width();
        //获取当前屏幕的高度
    var scrollHeight=$(window).scrollTop();
        //获取窗口的滚动高度 滚动到距顶端的位置
        // console.log(scrollHeight+" "+documentHeight);
    return (lastboxHeight<scrollHeight+documentHeight)?true:false;
    /* 当前文档的高度+滚动的高度大于最高的图片的高度的时候,进行图片的加载。 */
}

那么问题又来了:

该怎样去应用这两个函数呢??

基本思想:

1、首先在文档加载完之后进行第一次图片的排放,这次的排放目的是为了铺满一次浏览器页面。

2、var dataTmg={“data”:[{“src”:”1.jpg”},{“src”:”4.jpg”},{“src”:”2.jpg”},{“src”:”3.jpg”}]};

通过json数据【该数据理论上应该从服务器返回来,这个数据是作为鼠标滚动时,图片加载的备用加载源】

3、通过window.onscroll来监听屏幕的滚动,然后进行之前 scrollside函数的确认是否进行图片的瀑布加载。

4、进行图片的加载之后,在进行图片的“序列化排列”。

代码如下:

$(document).ready(function(){
    $(window).on("load",function(){
        imgLocation();
        var dataTmg={"data":[{"src":"1.jpg"},{"src":"4.jpg"},{"src":"2.jpg"},{"src":"3.jpg"}]};
            //json数据存放图片的地址,用于扩充图片时候使用。
         window.onscroll=function(){
        /* 通过屏幕的滚动来加载图片 */
            if(scrollside()){
                $.each(dataTmg.data,function(index,value){
                    //循环进行json数据的读取和函数的调用
                    var box=$("<div>").addClass('box').appendTo($('#container'));
                    //添加一个box到container下面
                    var content = $('<div>').addClass('content').appendTo(box);
                    // console.log('./img/'+$(value).attr('src'));
                    $('<img>').attr('src','./img/'+$(value).attr('src')).appendTo(content);
                        //添加如片到内容
                    imgLocation();
                        //创建出图片后,需要重新添加图片。
                });
            }
         }
     });
});

通过上面的操作,我们可以很轻松的就实现了瀑布流,但是依旧存在几个比较容易出错的地方.

四、常见错误

1、图片叠加到一张图片上去.

原因是没有在下一排的图片排列上去时进行高度的重新计算

2、屏幕滚动无效果

原因是屏幕滚动监听部分高度获取和计算有问题。请注意滚动高度是如何计算的。


五、重要补充

实际上瀑布流的中心流程是:

先把图片全部都放在网页上,然后对网页上的图片数量和高度进行重新计算,重新排列,进而形成瀑布流模式。

实际上不是预先判断好往哪里放,然后再放。

这个很重要。


代码托管在:
http://git.oschina.net/postbird/IMGWaterfallFlow【见附件】

有任何指教请直接留言,谢谢、

By postbird.2016-1-10

© 著作权归作者所有

postbird

postbird

粉丝 6
博文 32
码字总数 17950
作品 8
上海
后端工程师
私信 提问
30个创意出色的非常实用的jquery框架插件-(视觉大背景,瀑布流效果)

jQuery是在网页设计师和开发者最近的热门话题之一。人们使用它的广泛范围从个人博客到企业网站,目前流行的视觉大背景滚动效果,瀑布流图片阴影效果,图片缩放,动态标签复制,html5音频播放...

易达
2012/08/04
645
0
超酷的响应式dribbble设计作品瀑布流布局效果

日期:2013-2-21 来源:GBin1.com 在线演示 相信做设计的朋友肯定都知道dribbble.com,它是一个非常棒的设计师分享作品的网站,全世界数以万计的设计高手和行家都在这个网站上分享自己的作品...

gbin1
2013/02/27
9
0
15 个最佳的 jQuery 表格插件

现如今,网站开发设计的需求会要求自动适应所有移动设备,即响应式网站: 在开发网站时必须考虑对平板设备融合 fluid(流)和自适应性特点。 大多数网站设计要靠margins, guides, rows and c...

oschina
2013/11/29
17K
30
jQuery响应式瀑布流布局插件 - Grid-A-Licious

最近瀑布流布局比较流行,那么今天就给大家介绍一个这样的 jQuery 插件 - Grid-A-Licious。 Grid-A-Licious 是一个简单易用的 jQuery 插件,可用于创建响应式瀑布流布局,针对不同设备可自动...

justjavac
2013/11/27
1K
6
scrollLoad_MingGe 2.52 更新,滚动加载插件

2.52升级内容:加入container容器操作,这个功能在2.52的时候忘记了,修复各种事件机制,以及各种优化修复等 MingGe.scrollLoad2.52插件运行速度非常快, demo.html演试采用的大量图片以瀑布...

明哥先生
2016/01/11
1K
5

没有更多内容

加载失败,请刷新页面

加载更多

uni app 零基础小白到项目实战

$emit 子组件传给父组件$ref 父组件操作子组件 公用模板 uni-app全局变量的几种实现方法 const websiteUrl = 'http'const now = Date.now || function() { return new Date().getTime......

达达前端小酒馆
16分钟前
4
0
Tomcat是如何实现异步Servlet的

前言 通过我之前的Tomcat系列文章,相信看我博客的同学对Tomcat应该有一个比较清晰的了解了,在前几篇博客我们讨论了Tomcat在SpringBoot框架中是如何启动的,讨论了Tomcat的内部组件是如何设...

木木匠
40分钟前
14
0
mysql中间件分享(Mysql-prxoy,Atlas,DBProxy,Amoeba,cobar,TDDL)

hello 各位小伙伴大家好,我是小栈君,这期我们分享关于mysql中间件的研究,也就是数据层的读写分离和负载均衡,希望能够在实际的应用中能够帮助到各位小伙伴。 下期我们将继续分享go语言的系...

IT干货栈
今天
10
0
OSChina 周一乱弹 —— 人生,还真是到处是意外

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @这次装个文艺青年吧 :#今日歌曲推荐# 分享lil peep的单曲《High School》 《High School》- lil peep 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
611
10
Spring使用ThreadPoolTaskExecutor自定义线程池及实现异步调用

多线程一直是工作或面试过程中的高频知识点,今天给大家分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。 一、ThreadPoolTaskExecutor 本文采用 Executors 的工厂...

CREATE_17
今天
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部