瀑布流的特点是:1、等宽;2、高度不一样;2、每一个盒子相对于父标签定位;4、第二行第一个元素拼接到第一行最矮的盒子底下;
瀑布流的布局原理:子盒子相对于父盒子的一个定位,所以,先将第一行排列好,求出每个盒子的高度,如果是第一行的盒子,加入到数组中,如果是其他行的,遍历查找上一行的最矮盒子,把当前盒子相对于最矮盒子进行一下定位,然后更新数组最矮盒子的高度;
实现思路:每一个盒子,包含上边距和左边距,这样就省去计算图片与图片之间的间距了。这是比较简单一点的,如果需要在图片上添加赞或者购买等按钮或其他介绍信息的话,再当前的基础上再进行一些修改即可。
因为每个盒子都是等宽的,所以,布局的时候,只需要知道每个盒子距离浏览器的上边距和左边距是多少,左边距只需要当前盒子的索引 * 每个盒子的宽度即可,上边距就是最矮盒子的高度;
实现方式
1、用JS实现瀑布流布局
2、用CSS3
3、用jQuery
代码的地址
方式一:JS实现瀑布流布局
js实现瀑布流布局代码:
// 实现瀑布流布局
function
waterFall
(
parent
,
child
) {
// 最需要的两个参数:父盒子和子盒子
// -----子盒子在父盒子中居中-----
// 获取屏幕宽度,然后除以图片宽度,得到图片的列数
// 1.1 拿到父盒子中所有的子盒子
var
allbox
=
$(parent).getElementsByClassName(child);
// 1.2 求出盒子的宽度 202
var
boxWidth
=
allbox[
0
].offsetWidth;
// 1.3 动态求出浏览器的宽度,包括边线的宽
var
screenWidth
=
document
.body.offsetWidth;
// 1.4 求出列数并取整
var
columns
=
Math.floor(screenWidth
/
boxWidth);
// 1.5 让父标签居中
$(parent).
style
.width
=
boxWidth
*
columns
+
'px'
;
$(parent).
style
.margin
=
'0 auto'
;
// ---- 子盒子定位 ----
// 1.1 高度数组
var
heightArr
=
[];
// 1.2 遍历所有的盒子,将每个盒子的高度放在数组中
for
(
var
i
=
0
;i
<
allbox.length;i
++
) {
// 1.2.1 求出单个盒子的高度
var
boxHeight
=
allbox[i].offsetHeight;
if
(i
<
columns) {
// 取出第一行的盒子
heightArr.push(boxHeight);
}
else
{
// 需要定位的盒子
// 1.2.1 求出最矮盒子的高度
var
minBoxHeight
=
Math.min.apply(
this
,heightArr);
// 1.2.2 求出最矮盒子对应的索引
var
minBoxIndex
=
getMinBoxIndex(minBoxHeight,heightArr);
// 1.2.3 盒子定位
allbox[i].
style
.
position
=
'absolute'
;
allbox[i].
style
.top
=
minBoxHeight
+
'px'
;
allbox[i].
style
.left
=
minBoxIndex
*
boxWidth
+
'px'
;
// 1.2.4 更新数组中最矮盒子的高度
heightArr[minBoxIndex]
+=
boxHeight;
}
}
console
.log(heightArr);
}
// 取出数据中最矮盒子对应的索引
function
getMinBoxIndex
(
val
,
arr
) {
for
(
var
i
in
arr) {
if
(val
==
arr[i])
return
i;
}
}
实现瀑布流布局页面滚动加载的原理:
当(最后一个盒子高度的一半 + 头部偏离位置) > (浏览器的高度+页面偏离屏幕的高度)时,就加载下一页的数据,从最外层往里一层一层的创建盒子,将里层盒子加到外层盒子的里面,然后再将下一页的数据进行瀑布流布局;
// 滚动加载盒子
window
.
onscroll
=
function
() {
//
alert(0);
// 条件是否加载
if
(checkWillLoad()) {
// 假数据
var
data
=
{
'dataImg'
:
[{
'img'
:
'1.jpg'
},{
'img'
:
'10.jpg'
},{
'img'
:
'13.jpg'
},{
'img'
:
'15.jpg'
},{
'img'
:
'17.jpg'
},{
'img'
:
'19.jpg'
}]}
// 加载数据
for
(
var
i
=
0
;i
<
data.dataImg.length;i
++
) {
// 创建最外面的盒子
var
newBox
=
document
.createElement(
'div'
);
newBox.className
=
'box'
;
// 拿到父盒子,并插入
$(
'main'
).appendChild(newBox);
// 创建里面的盒子
var
newPic
=
document
.createElement(
'div'
);
newPic.className
=
'pic'
;
// 插入到父盒子,
newBox.appendChild(newPic);
// 创建img
var
newImg
=
document
.createElement(
'img'
);
newImg.src
=
'imgs/'
+
data.dataImg[i].img;
newPic.appendChild(newImg);
}
// 瀑布流布局
waterFall(
'main'
,
'box'
);
}
}
}
实现的页面效果:
方式二:CSS实现瀑布流布局
css实现瀑布局布局的大致框架的一个代码,在最外层的div的css布局中写如下代码即可,这只能实现一个瀑布流布局:
#
main
{
/*多栏布局:设置栏宽*/
-
webkit
-
column
-
width
:
202
px;
-
moz
-
column
-
width
:
202
px;
column
-
width
:
202
px;
}
方式三:jQuery实现瀑布流布局
jQuery实现瀑布流布局与CSS的不同在于,语言的的不同,思路都是一样的,只是js代码中换了一种写法
实现代码:
// 当页面加载完毕
$(
window
).on(
'load'
,
function
() {
// 1.实现瀑布流布局
waterFall();
// 2.实现滚动加载
$(
window
).on(
'scroll'
,
function
() {
// 判断是否加载
if
(checkWillLoad()) {
// 造数据
var
data
=
{
'dataImg'
:[{
'img'
:
'1.jpg'
},{
'img'
:
'10.jpg'
},{
'img'
:
'13.jpg'
},{
'img'
:
'15.jpg'
},{
'img'
:
'17.jpg'
},{
'img'
:
'19.jpg'
}]};
// 遍历创建盒子,创建了一个div,设置类名为box,
$.each(data.dataImg,
function
(
index
,
value
) {
var
newBox
=
$(
'<div>'
).addClass(
'box'
).appendTo($(
'#main'
));
var
newPic
=
$(
'<div>'
).addClass(
'pic'
).appendTo($(newBox));
$(
'<img />'
).
attr
(
'src'
,
'imgs/'
+
$(value).
attr
(
'img'
)).appendTo($(newPic));
})
// 实现瀑布流布局
waterFall();
}
});
//
alert(134);
});
// 实现瀑布流布局
function
waterFall
(){
// 拿到所有的盒子
var
allBox
=
$(
'#main .box'
);
//
alert($(allBox).length);
// 取出其中一个盒子的宽度,outerWidth带边距的宽度 202
var
boxWidth
=
$(allBox).eq(
0
).outerWidth();
// 取出屏幕的宽度
var
screenWidth
=
$(
window
).width();
// 求出列数
var
cols
=
Math.floor(screenWidth
/
boxWidth);
// 父标签居中
$(
'#main'
).
css
({
width:cols
*
boxWidth
+
'px'
,
margin:
'0 auto'
})
// 对子盒子定位
var
heightArr
=
[];
// 遍历
$.each(allBox,
function
(
index
,
value
) {
// 取出单独的盒子高度
var
boxHeight
=
$(value).outerHeight();
// 判断,
if
(index
<
cols) {
// 第一行盒子
heightArr[index]
=
boxHeight;
}
else
{
// 剩余行的盒子
// 取出高度数组中最矮的高度
var
minBoxHeight
=
Math.min.apply(
null
,heightArr);
// 取出最矮高度对应的索引
var
minBoxIndex
=
$.inArray(minBoxHeight,heightArr);
// 定位
$(value).
css
({
position
:
'absolute'
,
top:minBoxHeight
+
'px'
,
left:minBoxIndex
*
boxWidth
+
'px'
});
// 更新数组中最矮的高度
heightArr[minBoxIndex]
+=
boxHeight;
}
});
//
alert(cols);
}
// 设置滚动条件
function
checkWillLoad
() {
// 拿到最后一个盒子
var
lastBox
=
$(
'#main>div'
).last();
// 取出最后一个盒子高度的一半 + 头部偏离位置
var
lastBoxDis
=
$(lastBox).outerHeight()
+
$(lastBox).offset().top;
// 求出浏览器高度
var
clientHeight
=
$(
window
).height();
// 求出页面偏离浏览器的高度
var
scrollTopHeight
=
$(
window
).scrollTop();
console
.log(lastBoxDis,clientHeight,scrollTopHeight);
// 比较返回
return
lastBoxDis
<=
clientHeight
+
scrollTopHeight;
}