很多时候项目中图片的排布都是**以div定宽高包裹,img设置100%**实现。这样在只有少量图片的网站上有奇效——样式简单、布局便捷。 以前一直为发现了这一方法而“沾沾自喜”,但近来浏览了【百度图片】网页 。。。 莫名的就想到了【瀑布流布局】


开篇

何为瀑布流布局

形似瀑布排列,通常来说高度不固定而 宽度固定(以达到页面resize排列改变的效果),下一排图片紧接着上一排放,如下:

前端轶事:奇妙的个性化瀑布流布局_项目实战


要达到这种效果,首先我们要分析图片的排列特点: 上面说“下一行紧贴着上一行排列”,我们顺着“上一行”网上找,发现了一个特殊的地方——第一行。 我们很容易知道,第一行就是整个【(图片)瀑布流】的基础/参照。 有了这个,我们又能得到——除了第一行,其余的图片都要进行position:absolute; 处理。也就是说,整个区域内,只有第一行图片在文档流内:知道这一点很重要。

我们继续往下看,假如说现在我们有这样一行:

前端轶事:奇妙的个性化瀑布流布局_Web_02

并且设定了其高度分别为100、120、200,宽度为200,那么下一行应该这样排列:

前端轶事:奇妙的个性化瀑布流布局_项目实战_03

我们可以发现一个规律:

position: absolute;
left: i*图片宽度
top: 最小高度

如何求这个【最小高度】值呢?这可是解决的关键! 我们不妨将数据都放到数组中:

数组 [100,120,200]

配合【列数】,进行求解。


大致思路如此,让我们一起来看下代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>试验图片动态响应排列</title>
		<script src="../js/jquery.min.js"></script>
		<script src="../js/mxc.js"></script>
		<style>
			/* overflow:hidden;在此利用了BFC原理,使得大div边框能包裹所有元素 */
			.mxc{width: 90%;border: 1px solid red;margin-left: 5%;overflow: hidden;}
			.mxc img{float: left;width: 90px;height: 60px;}
		</style>
	</head>
	<body>
		<div class="mxc">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/small_red_triangle_down.png" alt="" />
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smile.png" alt="" />
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smile_cat.png" alt="" />
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smiley.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smiley_cat.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smiling_imp.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smirk.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smoking.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/small_red_triangle_down.png" alt="" />
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smiliie.png" alt="" />
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smile_catbb.png" alt="" />
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smileycc.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smiley_catdd.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smiling_impee.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smiggrk.png" alt="">
			<img src="../Web项目实战/app/src/components/inputBar/img/emoji/pngs/smokinghh.png" alt="">
		</div>
	</body>
</html>

因为这里用的jQuery,js文件中应该这样写:

$(function(){   //这是$(document).ready(function(){})的缩写
	
})

在正式开始处理图片之前,我们首先要获取到需要的信息——宽度 & 列数:

var allBox=$(".mxc img")   //-- 如果每个图片外有小div包裹,这里改变
var boxWidth=allBox.outerWidth();   //一个img的宽度
var screenWidth=$(window).width();   //可见区域的宽
var cols=parseInt(screenWidth/boxWidth);   //列数
var heightArr=[];   //获取高度的数组

然后去处理图片:

$.each(allBox,function(index,item){
	var boxHeight=item.outerHeight();   //每张图片高度 -- 如果每个图片外有小div包裹,这里item换成$(item)即可
	if(index < cols){
		heightArr[index]=boxHeight;
	}else{
		item.css({
			position:'absolute',
			left:i*boxWidth
			top:'最小高度'
		})
	}
	
})

这个 i 是什么?=> 最小高度的索引。 那如何求出所谓“最小的i”? 我们首先想到的几乎一定是【遍历数组】了。 有没有人会想到Math.min()函数呢?这可是个好工具:他能简便的求出字符串中的最小值。 字符串?对了,我们得到的是数组!

没关系,我们不是还有apply的嘛 —— apply,其主要作用是将第二个参数代入第一个参数中运算(因为第一个参数通常是this,所以常用于this指针的重定向)

apply函数的第二个参数是数组

前端轶事:奇妙的个性化瀑布流布局_数组_04

所以上面代码中else部分可以改为下面这样:

var minBoxHeight=Math.min.apply(Math.min,heightArr);
var minHeightIndex=$.inArray(minBoxHeight,heightArr);   //jQuery中的求索引函数
item.css({   // -- 如果每个图片外有小div包裹,这里item换成$(item)即可
	position:'absolute',
	left:minHeightIndex*boxWidth+'px',
	top:minBoxHeight+'px'
})
//改变了宽高,我们要将“最小高度”进行更新
heightArr[minHeightIndex]+=boxHeight;

Tip: outerWidth():不包含margin(jQuery-API,相当于js中的offsetWidth) innerWidth():不包含margin、border width():不包含padding、margin、border

这样,功能上算是完成了。但是当我们打开页面,会发现每一次刷新都有可能有的地方会出现高度上的错误。 此时笔者的内心是懵逼的...

在笔者将代码从上往下再从下往上看了一遍又一遍时,突然想到了页面加载时图片后于文档流加载 啊呀,把这个忘了:我们应当把开头的$(function(){}) 换成:

$(window).on('load',function(){
})