初始数据集中在窗口底部,通过动画移动摆动到正确的位置,同样模拟网络加载数据时,图片也从窗口底部“动画”摆放到正确的位置。

如下图所示,这是初始数据移动的过程。

带有分散效果的瀑布流(jQuery实现)_数据

带有分散效果的瀑布流(jQuery实现)_数据_02

移动结束后,初始数据摆放在正确的位置:

带有分散效果的瀑布流(jQuery实现)_带有分散效果的瀑布流_03

加载数据——数据从窗口底部分散到正确的摆放位置:

带有分散效果的瀑布流(jQuery实现)_数据_04


带有分散效果的瀑布流(jQuery实现)_加载数据_05


exec.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>带有分散效果的瀑布流</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="js/jquery.min.js"></script>
<script src="js/scriptExec1.js"></script>
</head>
<body>
<div id="main">
<div class="box">
<div class="pic"><img src="images/1.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/2.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/3.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/4.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/5.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/6.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/7.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/8.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/9.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/10.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/11.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/12.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/13.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/14.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/15.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/16.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/17.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/18.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/19.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/20.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/21.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/22.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/23.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/24.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/25.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/26.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/27.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/28.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/29.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/30.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/31.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/32.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/33.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/34.jpg" alt=".jpg"></div>
</div>

<div class="box">
<div class="pic"><img src="images/35.jpg" alt=".jpg"></div>
</div>
</div>
</body>
</html>


style.css

* {
margin: 0;
padding: 0;
}

#main {
position: relative;
}

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

.pic {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 0 5px #ccc;
}

.pic img {
width: 165px;
height: auto;
}


scriptExec1.js

/**
* Created by DreamBoy on 2016/2/5.
*/
/* 带有分散效果的瀑布流*/

var ww, wh, boxs;
var hArr = []; //存储每列的高度
$(window).on("load", function() {
ww = $(window).width(); //窗口宽度
wh = $(window).height(); //窗口高度
boxs = $("#main>div");

var boxsArr = jQtoArray(boxs);
initBoxsPos(boxsArr);
waterfall(boxsArr);


var dataInt = {"data" : [
{"src":"1.jpg"},{"src":"7.jpg"},{"src":"3.jpg"},{"src":"4.jpg"}
]};

$(window).on("scroll", function() {

var boxArr = [];
if(checkScrollSlide()) {

$.each(dataInt.data, function(key, value) {
$box = $("<div>").addClass("box");
$pic = $("<div>").addClass("pic").appendTo($box);
$img = $("<img>").attr("src", "images/" + value.src).appendTo($pic);

boxArr.push($box);

$box.appendTo($("#main"));
});

initBoxsPos(boxArr);
waterfall(boxArr);
}
});

/*$(window).on("resize", function() {
boxs = $("#main>div");
var boxsArr = jQtoArray(boxs);

hArr = [];
for(var i = 0; i < boxsArr.length; i++) {
boxsArr[i].removeAttr("style");
boxsArr[i].css("position", "absolute");
}

initBoxsPos(boxsArr);
waterfall(boxsArr);
});*/
});

// 将遍历得到的jQuery对象转为数组存储
function jQtoArray(jq) {
var boxsArr = [];
for(var i = 0; i < jq.length; i++) {
boxsArr[i] = jq.eq(i);
}
return boxsArr;
}

//初始化盒子的位置
function initBoxsPos(newBoxs) {
//设置初始盒子的位置
$.each(newBoxs, function(index) {
setBoxPos(newBoxs[index]);
});
}

// obj —— jQuery对象
function setBoxPos(newBox) {
var margin_left = Math.floor(- newBox.outerWidth() / 2 + ((Math.random() * 10) < 5 ? -1 : 1) * (Math.random() * 200));
var margin_top = Math.floor(- newBox.outerHeight() / 2 + ((Math.random() * 10) < 5 ? -1 : 1) * (Math.random() * 200));

newBox.css({
"position": "absolute",
"top": wh + $(window).scrollTop(),
"left": ww / 2,
"margin-left": margin_left,
"margin-top": margin_top
});
}

//将所有 newBoxs 新盒子“放好”
function waterfall(newBoxs) {
var w = newBoxs[0].outerWidth(); //盒子的宽度
//计算列数
var cols = Math.floor(ww/w);


$.each(newBoxs, function(index) {
var box = newBoxs[index];
var h = box.outerHeight();

if(index < cols && hArr.length < cols) { //hArr.length < cols 条件是为了区分后续的数据加载,表明已经有一行排在第1行了。
hArr[index] = h;

//移动第1行盒子到正确的位置
moveBox(box, index * w, 0);
} else {
var minH = Math.min.apply(null, hArr);
var minHIndex = $.inArray(minH, hArr);

hArr[minHIndex] += box.outerHeight();
moveBox(box, minHIndex * w, minH);
}
});
}

//移动盒子到正确的位置
function moveBox(box, left, top) {
box.animate({
"top": top,
"left": left,
"margin": 0
}, 2000);
}

//判断是否可以加载数据
function checkScrollSlide() {
var lastBox = $("#main>div").last();
var lastBoxH = lastBox.offset().top + Math.floor(lastBox.outerHeight() / 2);

var scrollTop = $(window).scrollTop();
var dh = $(window).height();
return lastBoxH < scrollTop + dh;
}



下面还有另外一种 “带分散效果的瀑布流”,上面提到的“分散”是同时“分散”摆放到正确的位置,下面则是一张一张摆放到正确的位置。

带有分散效果的瀑布流(jQuery实现)_数据_06

加载数据时也类似同样的效果。


scriptExec2.js

/**
* Created by DreamBoy on 2016/2/5.
*/
/* 带有分散效果的瀑布流*/

var ww, wh, boxs;
var hArr = []; //存储每列的高度
$(window).on("load", function() {
ww = $(window).width(); //窗口宽度
wh = $(window).height(); //窗口高度
boxs = $("#main>div");


var boxsArr = jQtoArray(boxs);
initBoxsPos(boxsArr);

hArr[0] = boxsArr[0].outerHeight();
waterfall(boxsArr);


var dataInt = {"data" : [
{"src":"1.jpg"},{"src":"7.jpg"},{"src":"3.jpg"},{"src":"4.jpg"}
]};


// 存在问题:加载数据后,数据块不是按我们设想的方式摆放,即数据块没有按最低高度的列优先加入的方式,但是不影响结果的摆放(至少看起来“正常”)
// 原因可能是因为 动画 + 动态加入数据DOM树渲染的原因。
$(window).on("scroll", function() {
var boxArr = [];
if(checkScrollSlide()) {

$.each(dataInt.data, function(key, value) {
$box = $("<div>").addClass("box");
$pic = $("<div>").addClass("pic").appendTo($box);
$img = $("<img>").attr("src", "images/" + value.src).appendTo($pic);

boxArr.push($box);

$box.appendTo($("#main"));
});

initBoxsPos(boxArr);
waterfall(boxArr);
}
});

/*$(window).on("resize", function() {
boxs = $("#main>div");
var boxsArr = jQtoArray(boxs);

hArr = [];
for(var i = 0; i < boxsArr.length; i++) {
boxsArr[i].removeAttr("style");
boxsArr[i].css("position", "absolute");
}

initBoxsPos(boxsArr);
waterfall(boxsArr);
});*/
});

// 将遍历得到的jQuery对象转为数组存储
function jQtoArray(jq) {
var boxsArr = [];
for(var i = 0; i < jq.length; i++) {
boxsArr[i] = jq.eq(i);
}
return boxsArr;
}

//初始化盒子的位置
function initBoxsPos(newBoxs) {
//设置初始盒子的位置
$.each(newBoxs, function(index) {
setBoxPos(newBoxs[index]);
});
}

// obj —— jQuery对象
function setBoxPos(newBox) {
var margin_left = Math.floor(- newBox.outerWidth() / 2 + ((Math.random() * 10) < 5 ? -1 : 1) * (Math.random() * 200));
var margin_top = Math.floor(- newBox.outerHeight() / 2 + ((Math.random() * 10) < 5 ? -1 : 1) * (Math.random() * 200));

newBox.css({
"position": "absolute",
"top": wh + $(window).scrollTop(),
"left": ww / 2,
"margin-left": margin_left,
"margin-top": margin_top
});
}

var w, cols;
//将所有 newBoxs 新盒子“放好”
function waterfall(newBoxs) {
w = newBoxs[0].outerWidth(); //盒子的宽度
//计算列数
cols = Math.floor(ww/w);

if(hArr.length == 1) {
moveBox(newBoxs, 0, 0, 0);
} else {
var box = newBoxs[0];
var minH = Math.min.apply(null, hArr);
var minHIndex = $.inArray(minH, hArr);
hArr[minHIndex] += box.outerHeight();

moveBox(newBoxs, 0, minHIndex * w, minH);
}
}

//移动盒子到正确的位置
function moveBox(newBoxs, index, left, top) {
if(index < newBoxs.length) {

newBoxs[index].animate({
"top": top,
"left": left,
"margin": 0
}, 200, function() {

index = index + 1;
if(index >= newBoxs.length) {
return;
}

// 求下一个盒子的正确位置
var box = newBoxs[index];
var h = box.outerHeight();
if(index < cols && hArr.length < cols) { //hArr.length < cols 条件是为了区分后续的数据加载,表明已经有一行排在第1行了。
hArr[index] = h;

//移动第1行盒子到正确的位置
moveBox(newBoxs, index, index * w, 0);
} else {
var minH = Math.min.apply(null, hArr);
var minHIndex = $.inArray(minH, hArr);

hArr[minHIndex] += h;
moveBox(newBoxs, index, minHIndex * w, minH);
}
});
}
}

//判断是否可以加载数据
function checkScrollSlide() {
var lastBox = $("#main>div").last();
var lastBoxH = lastBox.offset().top + Math.floor(lastBox.outerHeight() / 2);

var scrollTop = $(window).scrollTop();
var dh = $(window).height();
return lastBoxH < scrollTop + dh;
}