Article Outline
瀑布流_懒加载_ajax结合使用
<!--more-->
整体的布局是瀑布流效果,然后滚动到底部进行懒加载。 大体的实现思路:
- 获取数据
- 将数据变为DOM,然后通过瀑布流(绝对定位)的形式将其放到页面上
- 当页面滚动(滚动到底)时,继续执行获取数据的操作。
需要注意的地方:
- 对于判断是否滚动到底,可以预先设置一个锚点元素。当其出现在视野中时,触发获取数据的请求。但是由于我们的容器里的元素是绝对定位,高度是撑不开的,导致整个锚点元素一直在顶部,这时候我们就要在进行瀑布流布局的时候,每排放一个元素,就要手动将容器的高度撑开,让其等于瀑布流布局的数组的最大值,即最大高度。
- 关于瀑布流布局的问题:我们的数据是ajax请求来的,所以在加载完成之前得不到整个元素的高度,不能进行判断。所以要设置等加载完成之后在执行瀑布流布局。
进行布局的时候,先将表达思路的伪代码写好,再去一个个写好这些函数:
getData (newsList) {//从后端得到数据数组
getNode(newsList); //将得到的数组进行渲染,拼接成html字符串
//判断页面是否完全加载完,然后进行瀑布流布局
if (isLoaded) {
waterFall(node); //waterFall()每布局一个元素,就要手动将容易高度撑开,便于进行懒加载
}
};
//然后监听滚动事件,滚动到底进行懒加载
$(window).on('scroll',function () {
//里面的代码也是一样的,只是加一个判断是否出现的函数
if(checkshow($('#load'))) {
getData (newsList) {//从后端得到数据数组
getNode(newsList); //将得到的数组进行渲染,拼接成html字符串
//判断页面是否完全加载完,然后进行瀑布流布局
if (isLoaded) {
waterFall(node); //waterFall()每布局一个元素,就要手动将容易高度撑开,便于进行懒加载
}
};
}
})
写好思路伪代码之后,进行其中各种函数的书写。将重复的代码进行封装,将scroll事件处理进行优化,最终结果为:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>瀑布流_懒加载_ajax结合使用</title>
</head>
<style>
* {
margin: 0;;
padding: 0;
box-sizing: border-box;
list-style-type: none;
}
.wrap {
width: 900px;
margin: 0 auto;
}
.clearfix:after {
content: '';
display: block;
clear: both;
}
#pic-ct {
position: relative;
}
#pic-ct .item {
position: absolute;
padding: 0 0 10px 0;
width: 280px;
margin: 10px;
border: 1px solid #dfdfdf;
background: #fff;
/*opacity: 0;*/
transition: all 1s;
}
#pic-ct .item img {
margin: 10px;
width: 260px;
}
#pic-ct .item .header {
height: 25px;
margin: 0 12px;
border-bottom: 1px solid #dbdbdb;
}
#pic-ct .desp {
font-size: 12px;
line-height: 1.8;
margin: 10px 15px 0;
color: #777371;
}
#load {
visibility: hidden;
height: 20px;
}
.hide {
display: none;
}
</style>
<body>
<div class="wrap">
<div class="ct-watefall">
<ul id="pic-ct" class="clearfix">
<!--<li class="item">-->
<!--<a href="#" class="link">![](http://upload-images.jianshu.io/upload_images/7113407-b30662b4652b17ae.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)</a>-->
<!--<h4 class="header">标题</h4>-->
<!--<p class="desp">asdasdasdasdas</p>-->
<!--</li>-->
<!--用于计算item宽度和列数进行瀑布流布局,但是其本身不展示出来-->
<li class="item hide"></li>
</ul>
<div id="load">本身看不见</div>
</div>
</div>
<script src="../jquery-3.2.1.min.js"></script>
<!--<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>-->
<script>
var currentPage = 1;
var waterFallArr = [];
var waterFallCol = parseInt($('#pic-ct').width() / $('.item').width());
for (var i = 0; i < waterFallCol; i ++ ) {
waterFallArr[i] = 0;
}
var clock;
run();
$(window).on('scroll',function () {
if (clock) {
clearTimeout(clock);
}
clock = setTimeout(function () {
if (checkShow($('#load'))) { //当这个看不见的锚点出现时,进行懒加载
run();
}
},300)
})
function run() {
getData(function (newsList) {
$(newsList).each(function (i,e) {
var $node = getNode(e);
$node.find('img').on('load',function () { //当当前元素的图片加载完成之后,才能进行瀑布流布局,否则没高度不能进行瀑布流布局
$('#pic-ct').append($node); //不能在getNode()中就将其添加到页面中,得等到加载完成后再添加到页面中。否则没有width和height,不能进行瀑布流布局
waterFall($node);
})
})
});
}
function getData (callback) {
$.ajax({
url: 'http://platform.sina.com.cn/slide/album_tech',
method: 'get',
dataType: 'jsonp',
jsonp: 'jsoncallback',
data: {
app_key: 1271687855,
num: 10,
page: currentPage,
}
}).done(function (ret) {
if (ret.status.code == 0) {
callback(ret.data);
currentPage++;
}
})
}
function getNode (e) {
var html = '';
html += '<li class="item">';
html += '<a href=" ' +e.url + ' " class="link">![]( '+e.img_url +' )</a>'
html += '<h4 class="header">' +e.short_name+ '</h4>';
html += '<p class="desp">'+e.short_intro+'</p></li>';
return $(html);
}
function waterFall ($node) {
var minHeight = Math.min.apply(null,waterFallArr);
var minHeightIndex = waterFallArr.indexOf(minHeight);
$node.css({
left: minHeightIndex * $node.outerWidth(true),
top: minHeight,
opacity: 1,
})
waterFallArr[minHeightIndex] = $node.outerHeight(true) + waterFallArr[minHeightIndex];
$('#pic-ct').height(Math.max.apply(null,waterFallArr));//因为子元素都是绝对定位,高度撑不开的话顶部的锚点就一直在页面顶部。所以要手动撑开容易高度
}
function checkShow($node) {
var windowHeight = $(window).height();
var scrollTop = $(window).scrollTop();
var nodeOffsetTop = $node.offset().top;
if (nodeOffsetTop < (windowHeight + scrollTop + 500)) {
return true;
}
return false;
}
</script>
</body>
</html>
其实还可以监听窗口的变化,当窗口变化时,瀑布流布局也可以相应的改变