[js点滴]JavaScript瀑布流实现技巧

##基本结构

每一张图片,外层是不可见的box,中间是可见的pic装着img,要求盒子宽度固定。

##距离控制

要使多个盒子间隙相同时,指定向左浮动并且设定box的上左内边距即可,因为box不可见,实现的效果就类似于pic互相间隔开。

##排列规则

先固定第一行,然后按照第一行的宽高,将后续图片插入上一行最短的图片下面。

  1. 获取文档宽度和每个盒子宽度(此处取第一个盒子),然后相除获得一行排列盒子的个数,将容器设置为盒子。

  2. 定位第一行盒子:top为0,left为单个盒子宽度×盒子顺序的下标,将每一列盒子的高度存储在一个数组中。

  3. 获取第一行盒子高度的最小值(Math.min),然后依次比较确定是第几个盒子,对于顺序大于cnum的盒子,即第一行以后,位置即在第一行最短的盒子之下,定位为absolute,top值为最短盒子的高度,left值和上面的最短盒子一样。

  4. 然后将盒子高度的数组相应列数的高度值更新,继续排列下一个盒子。

##更新图片

当滚动条拉到最后张图片露出一半时,加载剩余的图片。

A 是最后一个 box 盒子的上边距(offsetTop),B 是最后一个盒子高度的一半,C 是用户拉动滚轴的长度(scrollTop),D 是页面高度(clientHeight)。从上图可以看出,当最后的 box 盒子没出到一半时满足
A+B>C+D
而当最后一个盒子出来一半时应该加载剩余图片了,此时A+B<C+D。

  1. 分别获取A,B,C,D的值,然后比较判断,符合要求时,开始加载数据。
  2. 数据储存在json数组中或者从服务器端请求等等,创建一个盒子and里面的图片等等,加入到容器中,然后调用瀑布流的布局函数进行布局。

##适应浏览器宽度变化

一行能排列的盒子个数在文档刚加载完成时就固定了。当后续改变宽度时,需要随之进行改变。
在window.onresize时调用waterfall函数。


<script type="text/javascript">

	var arrH = [];//记录每一列的高度
	var k = 0;//用来记录当前第几个div的个数
	createDiv(20)
	change()
	//1.创建DIV多少个div,通过函数的封装
	function createDiv(n) {
		for (var i = 0; i < n; i++) {
			k++;//每次调用for循环都对k进行++
			var div = document.createElement("div");
			// 3.div的高度通过调用随机函数进行创建
			div.style.height = rndFn(100,300) + "px";
			div.innerHTML = k;
			document.body.appendChild(div);
		}
	}

	//2.封装一个随机函数
	function rndFn(min,max) {
		return Math.round(Math.random()*(max-min)+min);
	}

      // 4.封装函数,根据窗口大小制定div的排列方式
	function change() {
		//可视窗口的宽度
		var winW = document.documentElement.clientWidth || window.innerWidth;
		//获取所有DIV
		var aDiv = document.querySelectorAll("div");
		//计算一行放多少列
		var num = parseInt(winW/(aDiv[0].offsetWidth+10));
		//计算空余位置的一半
		var center = (winW - (num*310-10))/2;
		// 0 310 620 930
		arrH = [];
		for (var i = 0; i < aDiv.length; i++) {	
			// 前一排按照从左到右排列顺序排列即可
			if (i<num) {
				aDiv[i].style.left = center+i*(300+10) + "px";
				aDiv[i].style.top = 0;
				//记录每一列的高度
				arrH[i] = aDiv[i].offsetHeight+10;
				// arrH.push(aDiv[i].offsetHeight+10)
			}else{
                  // 第二排开始就要开始查找最小高度的div,然后在最小高度的div下插入新的元素
				var min = findMin(arrH);
				aDiv[i].style.left = center+min*(300+10) + "px";
				aDiv[i].style.top = arrH[min] + "px";
				
				arrH[min] += aDiv[i].offsetHeight + 10;
			}
		}
	}


	function findMin(arr) {
		var min = arr[0];
		var index = 0;
		for (var i = 1; i < arr.length; i++) {
			if (min>arr[i]) {
				min = arr[i];
				index = i;
			}
		}
		return index;
	}

	

	window.onresize = function () {
		change();
	}

	window.onscroll = function () {
		var sTop = document.body.scrollTop || document.documentElement.scrollTop;
		var winH = document.documentElement.clientHeight;
		
		if (sTop+winH+20>=arrH[0]) {
			createDiv(10);
			change();
		}

	}

</script>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图解AI

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值