瀑布流的实现原理(不固定列)

OK,

我们接到上一篇瀑布流的实现,下面我们来讲讲不固定列的实现瀑布流

像花瓣网,百度图片的实现方式一样。

根据调整窗口也就是可视区的大小来改变显示图片的列数。同时也有个运动的效果。

实现原理:

布局:有一个容器,为相对定位,里面的img为绝对定位。

数据添加:因为每张图片的宽度是固定的,高度是不固定的。所以我们先要算出可视区的宽度能放下几列图片,然后在算出每列图片的高度,由高度最低的那列在添加下一张图片,我们用一张图片来形象说明下:

不固定列实现原理图片

这一种实现可谓是最优的一种方案,方便添加数据内容,窗口变化,列数会自动调整。

OK那么下面就给出实现的代码吧,用jquery来实现的。

 

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>瀑布流</title>
<style>
* {margin: 0; padding: 0;}
#container { width: 1000px; border: 1px solid red; position: relative; margin: 50px auto 0; }
#container img { position: absolute; }

#loader { width: 100%; height: 60px; background: url('loader.gif') no-repeat center #FFF; position: fixed; bottom: 0; left: 0; display: none; }
</style>
<script src="jquery-1.9.1.min.js"></script>
<script>
/*
不固定列:定位
根据可视区调整列数(非固定列数)
怎么添加数据的呢,每列图片添加好之后,在算出每列的高度,下一张图片添加到高度最低的那一列的下面。
*/
$(function() {
	//计算列
	var oContainer = $('#container');
	var oLoader = $('#loader');
	var iCells = 0;//总列
	var iWidth = 200;//每列宽度
	var iSpace = 10;//间隔宽
	var iOuterWidth = iWidth + iSpace;//实际列宽
	var sUrl = 'http://www.wookmark.com/api/json/popular?callback=?';
	var arrT = [];
	var arrL = [];
	var iPage = 0;//一开始加载第一页的数据
	var iBtn = true;
	
	function setCell() {//计算可视区有多少列
		iCells = Math.floor($(window).innerWidth() / iOuterWidth);
		//列数固定在3到6列之间,避免列数太多太卡。
		if (iCells < 3) {
			iCells = 3;
		} else if (iCells > 6) {
			iCells = 6;
		}
		//alert(iCells);
		oContainer.css('width', iCells * iOuterWidth) - 10;//占位宽度
	}
	setCell();
	
	for (var i=0; i<iCells; i++) {
		arrT[i] = 0;
		arrL[i] = iOuterWidth * i;
	}
	//console.log(iCells);
	//console.log(arrL);
	
	function getData() {
		if (!iBtn) {
			return ;
		}
		iBtn = false;
		iPage++;//加载一批显示一批
		oLoader.show();//数据加载完成之前显示转圈loading
		$.getJSON(sUrl, {page:iPage}, function(jData) {
			//$('#loader').show();
			$.each(jData, function(index, obj) {//循环数据
				
				var oImg = $('<img />');
				
				//宽高
				var iHeight = obj.height * (iWidth / obj.width);
				oImg.css({
					width	:	iWidth,
					height	:	iHeight
				});
				//获取arrT最小值的位置
				var _index = getMin();

				//设置定位
				oImg.css({
					left	:	arrL[_index],
					top	:	arrT[_index]
				});

				arrT[_index] += iHeight + 10;
				
				oContainer.append(oImg);
				
				var objImg = new Image();
				objImg.onload = function() {
					oImg.attr('src', this.src);
				}
				objImg.src = obj.preview;
				
				/*setTimeout(function() {
					$('#loader').hide();
				},1000)*/
				
				iBtn = true;
				oLoader.hide();//数据加载完成之后隐藏转圈loading
			})
			
		});
	}
	getData();//初始化的时候调用一次
	//arrT = [11,23,5,7];
	//获取数据中最小值的位置
	function getMin() {
		var v = arrT[0];
		var _index = 0;
		
		for (var i=1; i<arrT.length; i++) {
			if (arrT[i] < v) {
				v = arrT[i];
				_index = i;
			}
		}
		return _index;
	}
	
	//alert(getMin());
	//滚动条的滚动事件
	$(window).on('scroll', function() {
		var _index =getMin();
		var iH = $(window).scrollTop() + $(window).innerHeight();
		//document.title = iH + ':' + (arrT[_index] + oContainer.offset().top);
		if (arrT[_index] + oContainer.offset().top < iH) {
			//alert(1);
			iPage++;
			getData();
		}
		
	})
	
	$(window).on('resize', function() {
		var iLen = iCells;
		setCell();
		if (iLen == iCells) {
			return ;
		}
		arrT = [];
		arrL = [];
		for (var i=0; i<iCells; i++) {
			arrT[i] = 0;
			arrL[i] = iOuterWidth * i;
		}
		oContainer.find('img').each(function() {
			
			var _index = getMin();
			/*$(this).css({
				left	:	arrL[_index],
				top	:	arrT[_index]
			});*/
			$(this).animate({
				left	:	arrL[_index],
				top	:	arrT[_index]
			}, 1000);
			arrT[_index] += $(this).height() + 10;
			
		});
	})
	
	
	
})
</script>
</head>

<body>
	<div id="container"></div>
    <div id="loader"></div>
</body>
</html>

 

可以复制代码到本地试试体验效果如何

不错就给赞吧!

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值