瀑布流是当前一种比较流行的网站界面布局方式,参差不齐的多栏布局以及到达底部自动加载的方式,使网站在视觉和用户体验上都能得到较大的提升。最早使用此布局的是国外的图片网站Pinterest,之后国内的一些图片网站也开始使用瀑布流布局,包括和Pinterest类似的花瓣网、图片社区lofter、美丽说、蘑菇街等等。
瀑布流在布局上对于大多数人来说应该是很简单的,比较只有几列而已。瀑布流最主要的还是数据的异步加载。
首先说一下这次实例所用的瀑布流式方法。瀑布流布局实现的方法很多,具体可以自行百度,此处不再赘述。本文中瀑布流实现方法为四列布局(li*4),每个图片为一个盒子(div>img+p),从后台读取数据后赋值给盒子中的元素,判定此时高度最小的列(li),然后将盒子添加到对应的列(li),之后进行下一次判定,以此类推,直至本页所有数据加载完成。
代码部分:
html+css
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>瀑布流布局</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
ul{
width: 1200px;
margin: 0 auto;
}
ul li{
float: left;
width: 250px;
list-style: none;
margin: 20px;
}
ul li div{
width: 250px;
margin-bottom: 20px;
padding: 10px;
box-sizing: border-box;
border-radius: 5px;
box-shadow: 2px 2px 10px #919B9C;
}
ul li img{
width: 100%;
margin-bottom: 10px;
}
ul li p{
font-family: "microsoft yahei";
font-size: 14px;
}
</style>
<script src="ajax.js" type="text/javascript" charset="utf-8"></script>
<script src="pubuliu.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<ul id="ul1">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
</html>
javascript部分:ajax部分和实现部分
/**
*
* @param {Object} method get和post方式
* @param {Object} url 文件路径
* @param {Object} data 页码
* @param {Object} success 成功的函数
*/
function ajax(method, url, data, success) {
var xhr = null;
try {
xhr = new XMLHttpRequest();
} catch (e) {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
if (method == 'get' && data) {
url += '?' + data;
}
xhr.open(method,url,true);
if (method == 'get') {
xhr.send();
} else {
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
xhr.send(data);
}
xhr.onreadystatechange = function() {
if ( xhr.readyState == 4 ) {
if ( xhr.status == 200 ) {
success && success(xhr.responseText);
console.log(xhr.responseText);
} else {
alert('出错了,Err:' + xhr.status);
}
}
}
}
ajax部分是在之前所写的Ajax工作原理以及函数的简单封装上修改而来,理解那个之后看这个基本没难度。这个相对那个来说多了一个data参数,data是用来读取数据的页码。
window.onload = function() {
//获取界面节点
var ul = document.getElementById('ul1');
var li = document.getElementsByTagName('li');
var liLen = li.length;
var page = 1;
var bool = false;
//调用接口获取数据
loadPage();//首次加载
/**
* 加载页面的函数
*/
function loadPage(){
ajax('get', 'api', 'cpage='+page, function(data) {
//将数据库中获取的数据转换成数组形式,这里要根据数据库中的数据形式来写,这里我获取到的是json形式
var data = JSON.parse(data);
//将数据写入到div中
for(var i = 0; i < data.length; i++) {
var index = getShort(li);//查找最短的li
//创建新的节点:div>img+p
var div = document.createElement('div');
var img = document.createElement('img');
img.src = data[i].preview;//img获取图片地址
img.alt = "等着吧..."
//根据宽高比计算img的高,为了防止未加载时高度太低影响最短Li的判断
img.style.height = data[i].height * (230 / data[i].width) + "px";
div.appendChild(img);
var p = document.createElement('p');
p.innerHTML = data[i].title;//p获取图片标题
div.appendChild(p);
//加入到最短的li中
li[index].appendChild(div);
}
bool = true;//加载完成设置开关,用于后面判断是否加载下一页
});
}
window.onscroll = function (){
var index = getShort(li);
var minLi = li[index];
var scrollTop = document.documentElement.scrollTop||document.body.scrollTop;
if(minLi.offsetHeight+minLi.offsetTop<scrollTop+document.documentElement.clientHeight){
//开关为开,即上一页加载完成,才能开始加载
if(bool){
bool = false;
page++;
loadPage();
}
}
}
}
/**
* 获取数组中高度最小的索引
* @param {Object} li 数组
*/
function getShort(li) {
var index = 0;
var liHeight = li[index].offsetHeight;
for(var i = 0; i < li.length; i++) {
if(li[i].offsetHeight < liHeight) {
index = i;
liHeight = li[i].offsetHeight;
}
}
return index;
}
这部分的功能主要是动态的将生成的div写入到页面中,其中包含对盒子样式的修改和数据的写入,数据通过ajax函数从服务器端获取。
数据源:
数据源可以通过nodejs模拟接口返回,具体可以查看另一篇文章。nodejs数据mock服务https://blog.csdn.net/sir1241/article/details/80636795