XZ_HTML5之实现瀑布流的3种方式

瀑布流的特点是: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值