php 瀑布流 分页,waterfall瀑布流布局+动态渲染的实现
瀑布流典型网站
花瓣网、堆糖
瀑布流布局原理
大体思路
首先先是页面布局 特点是:宽度一样,长度不一样
由此可以知道,这种布局要用到 绝对定位 的思想来做。
上面的五个正常排列,到了第六个以后就要找最矮的追加了。
如何获取最矮的一列呢?
第一个最好找,其他的每一个盒子可以获取它的高度,找最矮的盒子,然后找到最矮盒子的定位。
新追加进去的盒子的定位是:
left:最矮盒子的索引*(盒子的宽度+左右间距)
top: 这个盒子的高度 + 上下间距
放进去之后这一列的高度变化,记录下来生成新的高度,然后进行下一轮高度的比较。以此类推。
waterful 是一个组件,基于 jquery 的一个组件。
具体思路
最外边的左右两边是没有间距的,所以 5 列的情况下有 4 个间距。所以宽度 width 一定的情况下,间距的宽度 space 是可以计算出来的:
间距
var space = (wParent - 5 * width) / (col - 1);
// wParent 父盒子的宽度,width是子盒子的宽度,col是列数
第一排的盒子的定位:
top : 0
left : 索引*(width + space)
第二排的盒子的定位:
top : minHeight + space
left : 索引*(width + space)
所以 5 列的高度要用一个数组表示,可以找到最矮的元素以及其当前的索引。
插件封装
因为在第一次加载和第 n 次加载的时候,都要进行瀑布流布局。所以将瀑布流布局的方法进行一个插件进行封装,可以形成代码的复用。 首先了解瀑布流的 html 布局
hello
hello
下面就来封装一个 jquery 的插件
第一步
将 jquery 中的全局变量转化为局部变量。
防止全局污染,提高性能 形成一个闭包,闭包里面定义的变量是不会影响外部变量的。
/*自调用 形成一个闭包 */
(function($){
/*如果不加jQuery里面使用的$是全局变量,加了之后使用的就是成员变量*/
})(jQuery);
第二步
jquery.fn.extend(object)
jquery 中的 fn 函数
提供一个第三方方法的一个入口,扩展 jquery 元素集(使用 $ 可以获取到的元素) 来提供新的方法(通常用来制作插件)
/*js/jquery-waterfall.js*/
(function($){
$.fn.waterfall = function(){
/*this指向的是当前调用这个方法的元素集(元素集是jquery获取元素是一个伪数组)*/
console.log(this);
}
})(jQuery);
第三步
对第一排进行排列
(function($){
$.fn.waterfall = function(){
// this指向的是当前调用这个方法的元素集
// 当前的瀑布流父容器
var items = $(this);
//父容器的宽度
var wParent = items.width();
//当前的瀑布流子容器
var child = items.children();
//获取子容器的宽度
var width = child.width();
//假设排多少列
var col = 5;
//计算间距(父元素的宽度减所有盒子的宽度/4)
var space = (wParent - col * width) / (col - 1);
//记录每列高度的数组
var colHeightArr = [];
//遍历每一个子元素
$.each(child,function(i,item){
var $item = $(item);
var height = $item.height();
//设置定位
//第一排的元素都是靠顶部的,所以索引从0开始,小于5的时候都是靠顶部的
if(i < col ){
$item.css({
top: 0,
left:i * (width + space)
});
//把高度添加进数组中
colHeightArr[i] = height;
//也可以用 colHeightArr.push(height);
}
//其他的都要根据最矮的一列进行排列
});
}
})(jQuery);
这样你就看到了效果图(因为模拟做了 13 个盒子,所以剩下的叠在了一起)
这个时候打印以下高度数组:
可以看到前 5 个的高度都存到数组中去了。可以判断出来数组中最小的是 289 , 289 对应的数组的索引就是那一列的索引。
第四步
对其余的排进行排列。找最小的追加,然后本列的高度增加。以此类推。 最大的 items 等于最大的高度。这样才可以把下面的加载移动到下边去。
(function($){
$.fn.waterfall = function(){
// this指向的是当前调用这个方法的元素集
// 当前的瀑布流父容器
var items = $(this);
//父容器的宽度
var wParent = items.width();
//当前的瀑布流子容器
var child = items.children();
//获取子容器的宽度
var width = child.width();
//假设排多少列
var col = 5;
//计算间距
var space = (wParent - col * width) / (col - 1);
//记录每列高度的数组
var colHeightArr = [];
//遍历每一个子元素
$.each(child,function(i,item){
var $item = $(item);
var height = $item.height();
//定位
//第一排的元素都是靠顶部的
//索引从0开始,小于5的时候都是靠顶部的
if(i < col ){
$item.css({
top: 0,
left:i * (width + space)
});
//colHeightArr[i] = height;
colHeightArr.push(height);
//其他的都要根据最矮的一列进行排列
}else{
//找到最矮的那一列进行排列
//索引
var index = 0;
//假设最小的高度是第一个索引对应的高度
var minHeight = colHeightArr[index];
//遍历数组,找到最小值和最小值对应的索引
//k是索引,v是值
$.each(colHeightArr,function(k,v){
if(minHeight > v){
index = k;
minHeight = v;
}
});
//定位
$item.css({
top:minHeight + space,
left:index * (width + space)
})
//当前数组中最小的高度进行新的高度的更新
colHeightArr[index] = minHeight + space + height;
}
//console.log(colHeightArr);
});
//设置父容器的高度
var maxHeight = colHeightArr[0];
$.each(colHeightArr,function(k,v){
if(maxHeight < v){
maxHeight = v;
}
});
//给父容器设置最高的高度
items.height(maxHeight);
}
})(jQuery);
效果图:
第五步
html 中调用(上面的效果图都是已经调用过的)
$(".items").waterfall();
但是如果有图片的话,这样调用在网络比较慢的情况下会出现问题。在图片没有加载出来的时候排列,中间图片加载完毕会造成盒子重叠的效果。
解决办法:
/*页面上所有的资源都加载完成后进行布局,否则获取不到图片的尺寸撑不开盒子的高度*/
window.onload = function(){
$(".items").waterfall();
}
//为什么不用jquery的,因为这个是在dom元素下载完毕之后进行加载这个方法,需要等所有的资源加载完之后进行排列
/*
$(function(){
//console.log('dom loaded');
});
*/
动态渲染
因为数据很多,所以会进行分批次渲染。
原理图:
接口文档:
接口说明: 瀑布流分页数据
接口地址:data.php
请求方式:get
接口参数:page 当前是第几页
pageSize 当前页要显示多少条
返回类型:json
返回数据:
{ page:2,items:[{path:"./images/1.jpg",text:'''},...] }
page 下一页的页码(根据页码获取下一页的数据)
items 返回当前页的数据
path 图片地址
text 文字
此时我们要准备好壳子
需求分析
加载第一页的时候
1.加载第一页的数据 ajax
2.按钮需要显示成加载更多
3.加载完成渲染到页面当中 artTemplate
4.初始化成瀑布流布局 waterfall
加载下一页的时候
1.加载数据
手动加载:点击按钮加载下一页的数据
自动加载:滚动到底部的时候主动加载下一页
2.按钮需要显示 “正在加载中...” 不能点击 防止重复提交
3.加载完成渲染到页面当中
4.初始化成瀑布流布局
5.按钮需要显示成加载更多
没有更多数据把按钮禁用 显示 “没有更多数据了”
渲染第一页数据
发送请求
既然加载页面的时候都会用到加载数据、渲染页面、初始化瀑布流,就把这三个动能封装到一个函数中去,先实现第一个功能:
$(function(){
//实现动态的瀑布流渲染
//渲染
var render = function(){
// 加载数据 渲染页面 瀑布流布局
$.ajax({
type:'get',
url:'data.php',
data:{
//第一页
page:1,
//每页10条
pageSize:10
},
dataType:'json',
success:function(data){
console.log(data);
}
});
}
render();
});
拿到的数据如图:
渲染页面
准备模板
$(function(){
//获取需要操作的dom
var $items = $(".items");
var $btn = $(".btn");
//渲染
var render = function(){
// 加载数据 渲染页面 瀑布流布局
$.ajax({
type:'get',
url:'data.php',
data:{
page:1,
pageSize:10
},
dataType:'json',
success:function(data){
console.log(data);
$items.append(template('template',data));
//瀑布流布局
$items.waterfall();
//更改按钮
$btn.removeClass('loading').html('加载更多');
}
});
}
render();
});
第二页面的渲染(手动加载)
第二页需要改变的东西:
添加按钮的点击事件,点击按钮之后就进行渲染。
点击按钮加载的时候,要给按钮加锁,因为不加的话会发送多个ajax请求,判断按钮是不是loading状态,如果是的话就不渲染数据。
render函数中,在进行按钮状态改变的时候,用自定义属性记录下来下一页的要获取的页数。利用data(),里面传一个page,把data.page放进去。所以在拿数据的时候,要从按钮的data中获取page的值。第一次是空的,所以就设定一个默认值为1
render函数中在数据成功加载之前,按钮还是loading状态,所以加一个beforeSend的函数,里面是loading状态。
render函数中在渲染的时候判断一下是不是没有数据了,根据返回的数组中的长度是不是为零来判断,如果是零的话就显示没有更多数据了。
$(function(){
//获取需要操作的dom
var $items = $(".items");
var $btn = $(".btn");
//渲染
var render = function(){
// 加载数据 渲染页面 瀑布流布局
$.ajax({
type:'get',
url:'data.php',
data:{
//取下一页的页码,没有的话就默认是1
page:$btn.data("page")||1,
//每页10条
pageSize:10
},
beforeSend:function(){
$btn.addClass("loading").html('正在加载中...');
},
dataType:'json',
success:function(data){
console.log(data);
//准备模板
//因为是追加所以不能用html,要用append
//直接用data的原因是因为data本来就是一个对象,里面有很多的属性,而不是一个数组,数组的话不能这样,因为数据只有length一个属性
$items.append(template('template',data));
//瀑布流布局
$items.waterfall();
if(data.items.length){
//更改按钮
//data是一个自定义属性,把数据中传输出来的page保存在自定义属性当中,
$btn.data("page",data.page).removeClass('loading').html('加载更多');
}else{
//没有更多数据
//判断什么时候就没有数据了,打开最后的一个对象,里面items的数组的长度为零
$btn.addClass("loading").html("没有更多数据了");
}
}
});
}
//按钮加载
$btn.on('click',function(){
//避免发送多个ajax请求,就进行判断,如果是loading状态,就退出,
if($btn.hasClass("loading")){
return false;
}
render();
})
render();
});
第二页面的渲染(滚动加载)
说到滚动渲染,就是要我们渲染过的页面到浏览器底部的一定距离就要进行下一次的请求了,这就要进行一个判断了。
原理图:
当 bottom < 200px 的时候进行 ajax 请求。
其中 bottom 要怎么计算?
bottom = items的高度 + items距离顶部的距离 - 向上卷曲的高度 - 整个浏览器的高度
$(function(){
//实现动态的瀑布流渲染
//获取需要操作的dom
var $items = $(".items");
var $btn = $(".btn");
//渲染
var render = function(){
// 加载数据 渲染页面 瀑布流布局
$.ajax({
type:'get',
url:'data.php',
data:{
page:$btn.data("page")||1,
pageSize:10
},
beforeSend:function(){
$btn.addClass("loading").html('正在加载中...');
},
dataType:'json',
success:function(data){
console.log(data);
$items.append(template('template',data));
//瀑布流布局
$items.waterfall();
//判断数组中有没有数据
if(data.items.length){
$btn.data("page",data.page).removeClass("loading").html('加载更多');
}else{
$btn.addClass("loading").html("没有更多数据了");
}
}
});
}
//滚动加载
$(window).on('scroll',function(){
//文档距离底部的距离小于200px 去加载
//并且加载完成才能继续加载
//items的高度
var itemsHeight = $items.height();
//items距离顶部的偏移量
var itemsTop = $items.offset().top;
//整个页面距离顶部的卷曲出去的距离
var scrollTop = $(document).scrollTop();
// 浏览器的高度
var winHeight = $(window).height();
// 浏览器底部距离items底部的距离
var bottom = itemsHeight + itemsTop - scrollTop -winHeight;
// 判断按钮是不是loading状态
var loading = $btn.hasClass("loading");
//如果按钮小于200 且 不是loading状态就开始加载
if(bottom < 200 && !loading){
render();
}
})
render();
});
需要特别注意的问题
之前我们在静态加载页面的时候使用的是 window.onload ,是为了让页面上的资源全部加载完成之后再进行页面的渲染。否则就会产生页面重叠的现象。
在动态加载页面的时候,我们先拿到后台的数据,然后转化成 html 追加到页面上之后,才开始加载 img 图片。这里也遇到了之前的问题。
之所以后面没有用 window.onload 那样的做,是因为原本设置的图片已经设定可宽和高。 img 有的设定了 250px ,有的设定了 450px 。 但是这样做不合理,因为有的图片会变形。
下面提供解决问题的方法:
等所有的图片加载完成进行页面渲染,但是这样时间会比较长,不合理。
参考花瓣
花瓣在加载图片的时候也进行了宽高的设定,但是这个大小要根据原图片的尺寸进行大小的缩放。
原来的尺寸是 608 ,现在的宽度是 200 ,那么现在的高度就进行一个换算
现在的高度 = 200 / 806 * 782
width 是现在的宽度
// 模板引擎中写
/*
同样在ajax的success中
$items.append(
template('template',{
data:data,
width:width
})
);
这样width变量就可以使用了。
*/
这样瀑布流就完成了.
到此这篇关于waterfall瀑布流布局+动态渲染的实现的文章就介绍到这了,更多相关waterfall瀑布流布局内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!
php 瀑布流 分页,waterfall瀑布流布局+动态渲染的实现相关推荐
- .Net/C#分库分表高性能O(1)瀑布流分页
框架介绍 依照惯例首先介绍本期主角:ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖.零学习成本.零业务代码入侵 dotnet下唯一一款全自动分表 ...
- JS——瀑布流无限加载以及动态生成a标签
如何实现瀑布流排列效果?看下面这张图 通过js去比较每张图片的高度,然后进行排列. 这是一个模拟的瀑布流的list列表项 <div id="main"><div ...
- html 手机端瀑布流,移动端 瀑布流布局
html {$item['teacher']} {$item['fl']} {$item['city']} js //重新定义瀑布流 window.onresize = function() { wa ...
- masonry ajax瀑布流,jquery.masonry瀑布流插件的4个使用步骤
解释:很简单,就是把下载之后的脚本文件嵌入到你想使用2.瀑布流布局样式代码 .container-fluid { padding: 20px; } .box { margin-bottom: 20px ...
- ajax瀑布流插件,jQuery瀑布流无限加载插件:jquery.falless.js
慌慌张张,匆匆忙忙,为何生活总是这样? 难道说,我的理想,就是这样度过一生的时光?........... 真的是一年一年飞逝而去,而人的一生,又有几个一年? 第一个四年即将结束,得到了什么?又失去了什 ...
- android 瀑布流 空白,Android瀑布流优化,解决Recyclerview展示大批量图片时Item自动切换、闪烁、空白等问题...
本文涉及的代码案例可以在下方的链接中找到,如果对你有帮助,请给个Star(#^.^#) 问题分析 这段时间业务需求用到RecyclerView瀑布流加载并展示大批量图片,但一开始单纯使用Recycle ...
- html li 做瀑布流,js实现瀑布流效果(自动生成新的内容)
当滚动条接近底部会自动生成新的内容(色块) 效果图: 代码如下: Title *{list-style: none;} div{overflow: hidden;} ul{float: left;} ...
- html瀑布流原理,什么是瀑布流布局?
首先我们来看一下瀑布流布局是什么? 根据百度百科上面的定义我们可以知道瀑布流,又称瀑布流式布局.是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载 ...
- html动态加载图片,javascript实现瀑布流动态加载图片原理
本文实例为大家分享了js瀑布流加载效果,动态加载图片,供大家参考,具体内容如下 鼠标滚动事件,当鼠标滚动到下边,动态加载图片. 1. HTML代码 js实现瀑布流效果-动态加载图片 2. CSS代码 ...
- 教你如何实现一个完美的移动端瀑布流组件(附源码)
背景 瀑布流是大家日常开发过程中经常遇到的一个场景,我们公司内部的组件库中也提供了一些解决方案.但这些方案适用场景都很单一,且每个实现方案都或多或少存在一些问题,基于此,我们设计与开发了一个兼容多场景 ...
最新文章
- 神经网络-预测财产损失
- Spring AOP 源码分析 - 筛选合适的通知器
- 入门Web前端要注意什么?要学哪些软件?
- 实验7-3-1 字符串逆序 (15分)
- 卓越性能代码_装好win10后,应该这样设置,才能压榨出系统十足的性能
- Stack(nowcoder 11253-K)
- java 字符串对齐_最佳字符串对齐的Java实现
- 计算机专业考研过关率高么,考研过国家线的几率有多大?被刷的有多少?
- 排序系列【比较排序系列之】直接插入排序
- MongoDB未授权访问漏洞记录(端口:27017,37017)
- 华为hcnp认证考试已过
- 实验五 单表查询(V2.0版)
- 二维几何变换---其他二维变换
- java vm 参数及设置(转载)
- adobe cs5中文补丁 indesign_indesign cs5下载_Adobe InDesign CS5简体中文版下载 - 下载之家...
- incaseformat蠕虫病毒样本分析
- Opencv 中的向量类Vec
- 数字兆欧表的使用及安全注意事项
- dex2jar源码解析----解析dex文件一
- 解决苹果手机点击输入框页面自动放大问题