初始数据集中在窗口底部,通过动画移动摆动到正确的位置,同样模拟网络加载数据时,图片也从窗口底部“动画”摆放到正确的位置。
如下图所示,这是初始数据移动的过程。
移动结束后,初始数据摆放在正确的位置:
加载数据——数据从窗口底部分散到正确的摆放位置:
exec.html
带有分散效果的瀑布流
* {
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;
}
/**
* 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 = $("").addClass("box");
$pic = $("").addClass("pic").appendTo($box);
$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;
}
下面还有另外一种 “带分散效果的瀑布流”,上面提到的“分散”是同时“分散”摆放到正确的位置,下面则是一张一张摆放到正确的位置。
加载数据时也类似同样的效果。
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 = $("").addClass("box");
$pic = $("").addClass("pic").appendTo($box);
$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;
}