共计 5249 个字符,预计需要花费 14 分钟才能阅读完成。
web 前端瀑布流的算法分析与代码实现是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
瀑布流效果目前应用很广泛, 像花瓣, 新浪轻博, 蘑菇街, 美丽说等好多网站都有. 也有好多支持该效果的前段框架, 今天学习了一下这种效果的实现, 不依赖插件, 自己动手分析实现过程, 为了便于叙述清楚, 分析中的一些名词为自己拟定, 不当之处还望见谅.
思路分析
步骤一: 构建成行元素 + 寻找新增元素追加位置
瀑布流所有元素的宽度是固定的, 我们用浏览器的宽度除以每个瀑布流块的宽度, 就是每一行可容纳的瀑布流块的个数. 因为, 每个瀑布流块的高度不一, 我们姑且把组成一行的这组元素称为成行元素, 在成行元素放置完毕后, 我们如果要再增加一个元素, 那么它的位置应该这样找?
“获取成行元素集合中高度最低的那个元素, 待放置的元素的 top 值应该是这个最低元素的高,left 值应该是这个最低元素的 left 值”
这样, 新增的这一个元素我们就找到了它存放的位置. 这样成行元素中的最低高度值就变为了原来的高度 + 新增元素的高度.
步骤二: 重复步骤一, 依赖成行元素追加新元素
步骤一中我们已经实现了一次成行元素追加一个新的元素, 这样新元素增加之后我们就构建了新的成行元素, 之后的操作就是在新的成行元素中追加新元素, 原理同步骤一.
步骤三: 实现滚动位置监听, 到底部时加载数据
代码实现
实现步骤一描述效果:
实现代码
!doctype html
html
head
meta charset= UTF-8
title 瀑布流效果实现 /title
script type= text/javascript src= scripts/jquery-1.8.2.min.js /script
script type= text/javascript src= scripts/jquery.easydrag.handler.beta2.js /script
script type= text/javascript
window.onload=function(){
// 获取父级对象
var oParent = document.getElementById( main
// 获取父级 [第一个参数] 下的所有的子元素[按照第二个参数匹配]
var aPin = getClassObject(oParent, pin
// 获取每一个块的宽度
var iPinW = aPin[0].offsetWidth;
// // 计算每行放多少个 pin(瀑布流块)页面的宽度 / 每一个瀑布流块的宽度
var num = Math.floor(document.documentElement.clientWidth/iPinW);
// 重置父级的样式, 这样保证图片整体居中
oParent.style.cssText= width: + num*iPinW + px;margin:0 auto;
var compareArray = [];
// 将一整行的瀑布流块的高度压入一个数组
for (var i = 0; i i++) { compareArray[i] = aPin[i].offsetHeight;
}
// 获取该行瀑布流高度最低的值
var minHeight = Math.min.apply(,compareArray);
//alert(compareArray + ,min= + minHeight);
// 获取改行高度值最小的瀑布流块的索引
var minHkey = getMinHeightKey(compareArray,minHeight);
// 为新增的瀑布流块增加样式
aPin[num].style.position = absolute
aPin[num].style.top = minHeight + px
// 设定新增加的瀑布流块的 top 和 left
aPin[num].style.left =aPin[minHkey].offsetLeft + px
// 将该索引位置的高度改变为新增后的高度[原来瀑布流块的高度 + 新增的瀑布流块的高度]
compareArray[minHkey] += aPin[num].offsetHeight;
}
/**
* 获取 parent 下所有样式名为 className 的对象集合
*/
function getClassObject(parent,className){
var obj = parent.getElementsByTagName( *
var result = [];
for(var i=0; i obj.length;i++){
// 变量如果匹配 className, 将匹配的对象放入数组
if(obj[i].className==className){ result.push(obj[i]);
}
}
return result;
}
/**
* 获取 arr 数组中值为 minH 的值在数组中的索引
*/
function getMinHeightKey(arr,minH){ for(key in arr){ if(arr[key] == minH){
return key;
}
}
}
/script
style type= text/css
/* 设置每一个瀑布流块 */
#main .pin{
width:220px;
height: auto;
padding: 15px 0px 0px 15px; /* 上 右 下 左 */
float: left;
}
/* 设置每一个瀑布流块中的图像样式 */
#main .pin .box{
width: 200px;
height: auto;
padding: 10px;
background: #FFF;
border: 1px solid #ccc;
box-shadow: 0px 0px 6px #ccc; /* 中间投影 */
border-radius: 5px; /* 圆角 */
}
#main .pin .box img{
width: 200px;
}
/style
/head
body
div id= main
!-- 每一个小块 --
div >实现步骤二描述效果
实现代码 !doctype html
html
head
meta charset= UTF-8
title 瀑布流效果实现 /title
script type= text/javascript src= scripts/jquery-1.8.2.min.js /script
script type= text/javascript src= scripts/jquery.easydrag.handler.beta2.js /script
script type= text/javascript
window.onload=function(){
// 获取父级对象
var oParent = document.getElementById( main
// 获取父级 [第一个参数] 下的所有的子元素[按照第二个参数匹配]
var aPin = getClassObject(oParent, pin
// 获取每一个块的宽度
var iPinW = aPin[0].offsetWidth;
// // 计算每行放多少个 pin(瀑布流块)页面的宽度 / 每一个瀑布流块的宽度
var num = Math.floor(document.documentElement.clientWidth/iPinW);
// 重置父级的样式, 这样保证图片整体居中
oParent.style.cssText= width: + num*iPinW + px;margin:0 auto;
var compareArray = [];
// 遍历获取到的所有瀑布流块
for (var i = 0; i aPin.length; i++) { if(i num){
// 成行元素
compareArray[i] = aPin[i].offsetHeight;
}else{
// 获取成行元素中高度最低的值
var minHeight = Math.min.apply(,compareArray);
//alert(compareArray + ,min= + minHeight);
// 获取成行元素中高度最低元素的索引
var minHkey = getMinHeightKey(compareArray,minHeight);
// 为新增的瀑布流块设置定位
aPin[i].style.position = absolute
aPin[i].style.top = minHeight + px
// 设定新增加的瀑布流块的 top 和 left
aPin[i].style.left =aPin[minHkey].offsetLeft + px
// 将该索引位置的高度改变为新增后的高度[原来瀑布流块的高度 + 新增的瀑布流块的高度]
compareArray[minHkey] += aPin[i].offsetHeight;
}
}
}
/**
* 获取 parent 下所有样式名为 className 的对象集合
*/
function getClassObject(parent,className){
var obj = parent.getElementsByTagName( *
var result = [];
for(var i=0; i obj.length;i++){
// 变量如果匹配 className, 将匹配的对象放入数组
if(obj[i].className==className){ result.push(obj[i]);
}
}
return result;
}
/**
* 获取 arr 数组中值为 minH 的值在数组中的索引
*/
function getMinHeightKey(arr,minH){ for(key in arr){ if(arr[key] == minH){
return key;
}
}
}
/script
style type= text/css
/* 设置每一个瀑布流块 */
#main .pin{
width:220px;
height: auto;
padding: 15px 0px 0px 15px; /* 上 右 下 左 */
float: left;
}
/* 设置每一个瀑布流块中的图像样式 */
#main .pin .box{
width: 200px;
height: auto;
padding: 10px;
background: #FFF;
border: 1px solid #ccc;
box-shadow: 0px 0px 6px #ccc; /* 中间投影 */
border-radius: 5px; /* 圆角 */
}
#main .pin .box img{
width: 200px;
}
/style
/head
body
div id= main
!-- 每一个小块 --
div >会看到新增的瀑布流块在新的成行元素中自动寻找高度最低的那个元素块的相对位置进行追加. 添加更多元素查看效果
步骤三:实现滚动到底部时加载数据
该部分没有什么功能, 只是检测滚动条的位置距离浏览器底部的相对距离进行数据加载, 加载数据时创建对应的瀑布流块. 判断相对距离的实现逻辑如下
function checkScrollSite(){
var oParent = document.getElementById( main
var aPin = getClassObject(oParent, pin
// 加载数据依赖最后一个瀑布流块变化
var lastPinHeight = aPin[aPin.length-1].offsetTop + Math.floor(aPin[aPin.length-1].offsetHeight/2) ;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 浏览器高度
var documentH = document.documentElement.clientHeight;
if(lastPinHeight documentH + scrollTop){
// 请求数据
return true;
}
return false;
}
看完上述内容,你们掌握 web 前端瀑布流的算法分析与代码实现是怎样的的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注丸趣 TV 行业资讯频道,感谢各位的阅读!