共計 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 行業資訊頻道,感謝各位的閱讀!