瀑布流实现需求:
1、ajax请求数据,渲染页面
2、根据高度不同,自动排列位置 (封装位置函数)
3、当滚动页面到最后一张图片之前时,ajax请求加载数据
4、重复 3 操作 滚动页面加载数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="referrer" content="no-referrer" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body,
html {
height: 100%;
background-color: #ddd;
}
li {
list-style-type: none;
}
.container {
width: 1000px;
margin: 0 auto;
}
.container ul {
width: 1100px;
}
.container ul::after {
content: "";
clear: both;
display: block;
}
.container ul li {
float: left;
height: auto;
margin: 0 20px 20px 0;
border-top: 0 none;
background-color: #fff;
border-radius: 2px;
width: 235px;
}
.container ul li img {
width: 100%;
}
.container ul li p {
width: 100%;
line-height: 40px;
padding-left: 10px;
}
</style>
</head>
<body>
<!-- 瀑布流容器 -->
<div class="container">
<!-- 瀑布流定位容器 -->
<ul class="wrapper">
<!-- 每个瀑布流元素 -->
<!-- <li>
<img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
<p>粘土手作希小怪</p>
</li>
<li>
<img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
<p>粘土手作希小怪</p>
</li>
<li>
<img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
<p>粘土手作希小怪</p>
</li>
<li>
<img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
<p>粘土手作希小怪</p>
</li> -->
</ul>
</div>
<script src="./javascripts/libs/jquery.js"></script>
<script src="./javascripts/jquery.waterfall.js"></script>
<script>
// 瀑布流实现需求:
// 1、ajax请求数据,渲染页面
// 2、根据高度不同,自动排列位置 (封装位置函数)
// 3、当滚动页面到最后一张图片之前时,ajax请求加载数据
// 4、重复 3 操作 滚动页面加载数据
// 1. 发起请求渲染页面;
$(function () {
//1. 记录最后一个元素;
var last_ele = null;
// 2. 页面的高度获取;
var clientHeight = document.body.clientHeight;
// 3. 限制加载的变量(标记当前的加载状态);
var loading = false;
// 4. 接口数据;
var next_start = 0;
// 1. 发起请求;
$.ajax({
url: "http://localhost:3000/dt",
data: {
include_fields: "top_comments,is_root,source_link,item,buyable,root_id,status,like_count,sender,album,reply_count",
filter_id: "手工DIY",
start: next_start,
_: Date.now()
}
})
.then(function (res) {
// 测试数据是否可以正常获取;
// console.log(res);
render(res.data.object_list);
$(".wrapper li").waterFall({
max_col: 4
});
// 最后一个元素高度此时才有;
last_ele = $(".wrapper li:last");
next_start = res.data.next_start;
})
// 2. 渲染页面;
function render(list) {
// 1. 根据数据拼接字符串;
var html = "";
for (var i = 0; i < list.length; i++) {
// 当前图片的宽度;
var n_w = 235;
// 图片实际的宽度;
var w = list[i].photo.width;
// 图片的实际高度;
var h = list[i].photo.height;
// 当前图片的高度;
var n_h = n_w / w * h;
html += `<li>
<img src="${list[i].photo.path}" height=${parseInt(n_h)}>
<p>${list[i].msg}</p>
</li>`
}
// 2. 把字符串放入页面之中;
$(".wrapper").append(html);
}
// 无限加载 :
// 数据 :
// 1. 最后一个元素的offsetTop值;
// 2. 页面的高度;
// 3. scrollTop;
$(document).on("scroll", throttling(function () {
// console.log(1);
// 安全逻辑 : 如果 最后一个元素为null, 我们应该直接跳出逻辑;或者loading为false
if (!last_ele || loading) {
return false;
}
// 如果 页面的高度 + scrollTop 大于等于 最后一个元素的高度; 需要加载数据了;
if (clientHeight + $("html,body").scrollTop() >= last_ele.offset().top) {
// 逻辑 : 加载如果没有结束,就不再发起新的请求;
loading = true;
// 发送请求,渲染页面,瀑布流排序;
$.ajax({
url: "http://localhost:3000/dt",
data: {
include_fields: "top_comments,is_root,source_link,item,buyable,root_id,status,like_count,sender,album,reply_count",
filter_id: "手工DIY",
start: next_start,
_: Date.now()
}
})
.then(function (res) {
// 测试数据是否可以正常获取;
render(res.data.object_list);
$(".wrapper li").waterFall({
max_col: 4
});
// 最后一个元素高度此时才有;
last_ele = $(".wrapper li:last");
// 改变加载的值
loading = false;
next_start = res.data.next_start;
})
}
}, 200))
// 事件 节流:
function throttling(callback, delay) {
var t = null;
return function () {
if (t !== null) {
return false;
}
t = setTimeout(function () {
t = null;
callback();
}, delay)
}
}
})
</script>
</body>
</html>
waterfall封装函数
// 1. 我们要把插件写在局部作用域之中; 防止变量冲突;
// 2. 在写代码之前加上两个分号;
// 为啥要加分号 :
// 在这种情况下不加分号就错误了;
/*
(function(){
})()
(function(){
})
*/
// 3. 把jQuery当做局部变量传入进去;
// 3.1. 可以优化性能; 不用进行两次查找就可以访问到 jQuery 了;
// 3.2. 防止和别人的 $ 符号冲突;
;;
(function ($) {
// 开发一个局部方法还是全局方法;
// 以下两种方法二选一 :
// $.extend( $.fn , {
// waterFall : function(){
// }
// })
// 高度列表;
var height_list = [];
// 定义一个API方法
$.fn.waterFall = function (options) {
// 如果上一次的数组不清空,那么下次会沿用之前的数据导致数据失真;
height_list.length = 0;
// console.log("waterfall功能被调用,页面上的元素都排列好了");
// 为什么在操作DOM的时候我们去使用原型方法;
// this 指向实例对象;
// console.log(this); //例如:原生中的DOM元素
// 1. 前四个不动后面的都跟着前四个进行排列;
// 为了防止出现问题,给options设置一波默认参数;
options = $.extend({
max_col: 4
}, options);
// 2. 遍历所有元素;
// 所有的元素其实都放在 this 上;
// this === 需要排列的元素;
for (var i = 0; i < this.length; i++) {
if (i < options.max_col) {
// 第一排的元素,获取元素的高度作为每一列的基数;
height_list.push(this.eq(i).height());
} else {
// 剩余的元素; 根据高度数组进行排列;
// 找到数组之中的最小高度;
// 技巧解释; 这是一个快速找到数组之中最小值的API;
// 直接使用即可;
// console.log(height_list) // 里面每次有四个值 求出四个值中最小高度
var min_height = Math.min.apply(false, height_list);
// 获取最小值的下标;
var min_index = height_list.indexOf(min_height);
// console.log(min_index)
// 让元素进行拼接;
// console.log(this.eq(i))
this.eq(i).offset({
// 最小下标那一列的left值;
left: this.eq(min_index).offset().left,
// 最小高度值;
top: min_height + 20
});
// 改变高度数组; 这里 +20 是 margin 值
height_list[min_index] += this.eq(i).height() + 20;
}
}
}
})(jQuery);
注意:接口在gulp自动化构建的服务器中已经处理