前端瀑布流布局实现

337 阅读1分钟

前端开发的过程中难免会遇到瀑布流布局的需求,接下来我就给大家展示代码然后与大家一起分析

首先你的目录结构可以和笔者保持一致:
在这里插入图片描述
JS笔者单独封装了一个小的工具,用来获取DOM元素
tools.js代码如下:

/**
 * 解决根据类名查找元素的兼容问题
 * @param className 待查找的类名
 * @param context 可选,查找元素的上下文:即在指定的 context 元素后代查找,该参数不传递,则默认为 document
 * @return 查找到的元素集合(HTMLCollection 或 Array)
 */
function getElementsByClassName(className, context) {
	// 未传递 context 这个参数,则默认为 document
	context = context || document;

	// 如果浏览器本身就支持使用 document.getElementsByClassName 方法,则直接调用
	if (context.getElementsByClassName) // 支持使用
		return context.getElementsByClassName(className);

	/* 不支持使用 */
	// 定义数组保存查找结果
	var result = [];
	// 查找所有元素
	var elements = context.getElementsByTagName("*");
	// 遍历所有元素
	for (var i = 0, len = elements.length; i < len; i++) {
		// 将当前遍历到元素的类名获取到
		var classNames = elements[i].className.split(" ");
		// 遍历当前元素的所有类名
		for (var j = 0, l = classNames.length; j < l; j++) {
			// 判断当前遍历到的类名是否和待查找的类名一致
			if (classNames[j] === className) {
				// 有相同,则说明当前遍历到的元素是待查找的元素
				result.push(elements[i]);
				break;
			}
		}
	}
	// 将查找结果返回
	return result;
}
/**
 * 根据选择器查找元素
 * @param selector 选择器   #id    .className   element
 * @param context 可选,查找元素的上下文:即在指定的 context 元素后代查找,该参数不传递,则默认为 document
 * @return 返回根据选择器查找到的元素
 */
function $(selector, context) {
	// 默认在文档中查询
	context = context || document;

	if (selector.indexOf("#") === 0) // id
		return document.getElementById(selector.slice(1));
	if (selector.indexOf(".") === 0) // className,调用自定义的函数解决根据类名查找元素兼容问题
		return getElementsByClassName(selector.slice(1), context);
	// element
	return context.getElementsByTagName(selector);
}

images文件夹里面放到的就是事例图片,你可以随意找N张图片放到images文件夹里面
CSS样式笔者是直接写到html里面了,你也可以单独提取出来。
index.html代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title></title>
	<style type="text/css">
		#container {
			width: 95%;
			position: relative;
			margin: auto;
		}
		#container div {
			width: 200px;
			padding: 10px;
			border: 1px solid;
			border-radius: 5px;
			overflow: hidden;
			position: absolute;
			top: 0;
			left: 0;
		}
		#container div img {
			width: 200px;  /* 将所有图片统一宽度 */
		}
	</style>
</head>
<body>
	<div id="container">
		<div><img src="./images/imgs (1).jpg" alt=""></div>
		<div><img src="./images/imgs (2).jpg" alt=""></div>
		<!-- 此处省略无用代码,你有多少图片就复制多少份这个格式就OK了。 -->
		<div><img src="./images/imgs (30).jpg" alt=""></div>
	</div>
	<script type="text/javascript" src="./js/tools.js"></script>
	<script type="text/javascript">
		window.onload=function(){  //避免代码在引入tools.js文件之前执行
			let spacing = 10,					//间距
				divs = $("div",$("#container")),//获取#container下的所有div
				len = divs.length,				//一共有多少个div
				colWidth = divs[0].offsetWidth, //获取div的宽度
				cols = 5;						//限定一行放五个图片
			let height = new Array(cols);		//定义一个数组,数组的容量为5
			height.fill(0);						//将数组中每个元素以0填充
			for(let i = 0;i < len;i++){			//循环迭代每一个div,设置定位
				let colIndex = min(height);		//调用函数min,获取每一行的数组当中高度最短的下标
				//设置定位
				divs[i].style.top = height[colIndex] +10+"px";
				divs[i].style.left = (colIndex + 1)*spacing + colIndex * colWidth + "px";
				//累加列高度
				height[colIndex] += divs[i].offsetHeight + 10;
			}
			//求数组元素最小值的下标的函数
			function min(array){
				return array.indexOf(Math.min(...array))    //将传递过来的数组当中最小值的下标返回
			}
		}
	</script>
</body>
</html>

代码的解读笔者都标记到代码的注释当中咯,如果还有不懂的直接评论留言就可以了哦,快快动手搞写图片试试效果吧!
最后附上笔者的效果图!
在这里插入图片描述
全是美女,哈哈!养眼吧!