jquery實(shí)現(xiàn)簡單的瀑布流布局
是開頭都會說的原理
瀑布流布局有兩種,一種是固定列,一種是非固定列。在此主要記述第一種的實(shí)現(xiàn)。
固定列的特征是:無論頁面如何縮放,每行的總列數(shù)都一致。
一行4列的瀑布流從布局的角度來說,就是4個li標(biāo)簽。通過一定的事件(比如滾動條滾動多少px),然后讀取之,再把數(shù)據(jù)動態(tài)地添加到頁面中。
添加數(shù)據(jù)原則,不是根據(jù)li索引值來加,而是根據(jù)各列中高度最短的的那列動態(tài)添加。否則可能導(dǎo)致頁面很難看(左右高度不統(tǒng)一)。
實(shí)例涉及ajax方法??稍诜?wù)器環(huán)境下運(yùn)行。
廢話不多說了。直接上樣式。
<ul id="ul1"> <li> <div> <img src="images/1.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> <li> <div> <img src="images/2.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> <li> <div> <img src="images/3.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> <li> <div> <img src="images/4.jpg"> <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p> </div> </li> </ul>
css
*{
margin:0;
padding: 0;
}
ul li{
list-style: none;
}
#ul1{
width: 1080px;
margin: 100px auto 0;
}
li{
width: 247px;
float: left;
margin-right: 10px;
}
li div{
border:1px solid #000;padding:10px;
margin-bottom:10px;
}
li div img{
width: 225px;display: block;
}
基本效果如圖:

樣式顯示沒問題之后,就把li里面的代碼刪掉。
接下來通過ajax來動態(tài)添加。
數(shù)據(jù)哪里來?
這里用的是wookmark的數(shù)據(jù)接口。
http://www.wookmark.com/api/json/popular?page=1
點(diǎn)開url得到是一個json。
信息量很大。怎么分析?
一般可以看文檔。但是手頭沒有文檔的情況下,可以看看鏈接。返回是什么鬼。
function createUrl(num){
return 'http://www.wookmark.com/api/json/popular?page='+num+'&callback=?';
}
$(function(){
$.getJSON(createUrl(1),function(data){
console.log(data);
})
})
控制臺打印結(jié)果為:

原來是一個50個圖片信息組成的數(shù)組。每個數(shù)組元素都是一個json。在這個簡單的demo里面,暫時(shí)只需要取preview屬性和title屬性就好了。
布局實(shí)現(xiàn)
關(guān)鍵之一在于,判斷最短的li,事實(shí)上我們需要最短高度li的索引值。
//找出高度最小li的索引值
function getShortestLi(){
var shortest=0;
for(var i=1;i<4;i++){
if($('li').eq(i).height()<$('li').eq(shortest).height()){
shortest=i;
}
}
return shortest;
}
然后就是getJSON方法
$(function(){
$.getJSON(createUrl(1),function(data){
//console.log(data);
for(var i=0;i<dataArr.length;i++){
var $html=$('<div><img src="'+data[i].preview+'"><p>'+data[i].title+'</p></div>');
//console.log($('li').eq(getShortestLi()).height())
$('li').eq(getShortestLi()).append($html);
};
console.log([$('li').eq(0).height(),$('li').eq(1).height(),$('li').eq(2).height(),$('li').eq(3).height()])
})
})
再加載看看,布局就出來了。簡單又漂亮。

做到這里,看起來一切都挺好。然而潛伏著一個致命的問題。
for循環(huán)惹的禍?
看看console.log的信息。為了分析,我把4個li的高度放進(jìn)了一個數(shù)組:

50張圖片分4列,少說平均高度也得有三四千像素。
而到循環(huán)結(jié)束,程序判斷的終點(diǎn)竟然只有令人發(fā)指的1000多個px,因?yàn)閳D片加載過程慢于for循環(huán)執(zhí)行速度。雖然demo里的顯示還算正常,但這種代碼在網(wǎng)速不好時(shí),會造成工作事故。
思路一:可以判斷圖片是否加載完成。
可以用個定時(shí)器監(jiān)聽下,然后用遞歸實(shí)現(xiàn),我的方案是這樣
var index=0;
function LoadPic(index){
var $html=$('<div><img src="'+data[index].preview+'"><p>'+data[index].title+'</p></div>')
$('li').eq(getShortestLi()).append($html);
var oImg=$html.find('img');
var t=setInterval(function(){
if(oImg.height()!=0){//如果加載完了。
clearInterval(t);
//console.log([$('li').eq(0).height(),$('li').eq(1).height(),$('li').eq(2).height(),$('li').eq(3).height()])
if(index<50){
return LoadPic(index+1);
}else{
return false;
}
}else{
console.log('wait')
}
},50)//每隔50ms監(jiān)聽一次
}
LoadPic(0);
但是,從用戶體驗(yàn)的角度來說,等一張圖加載完成再進(jìn)行下一張加載是不友好的。數(shù)據(jù)提供方都應(yīng)該直接把圖片的高度在服務(wù)器處理好,json數(shù)據(jù)里面返回過來。網(wǎng)速很慢的時(shí)候,要等好久,然后一下子圖片都出來了,不覺得很詭異嗎?尤其是第三方接口。一加載不出來就出大問題了。
所幸的是,第三方提供了圖片的寬高信息。
因此for循環(huán)還是可以有的,在返回的數(shù)據(jù)里面,有寬度和高度值。利用它們就可以實(shí)現(xiàn)定寬(255px)和定高(原始高度乘上一個比例)。
$(function(){
$.getJSON(createUrl(1),function(data){
console.log(data);
for(var i=0;i<data.length;i++){
//console.log(data[i].preview);
var $html=$('<div><img src="'+data[i].preview+'"><p>'+data[i].title+'</p></div>')
$('li').eq(getShortestLi()).append($html);
$html.find('img').css('height',(data[i].height*225/data[i].width)+'px');
$html.find('img').css('width','225px');
};
//console.log([$('li').eq(0).height(),$('li').eq(1).height(),$('li').eq(2).height(),$('li').eq(3).height()])
})
})
事實(shí)上個人認(rèn)為這是最簡單且用戶體驗(yàn)最好的方案。
有了瀑布,還需要流
流的邏輯
往下拉(滾動),第一個底部進(jìn)入可視區(qū)的li,優(yōu)先加載。

換句話說,最短li的高度與該li到頁面頂部之和小于滾動條高度和可視區(qū)高度之和時(shí),觸發(fā)li加載。
li的高度好求。但是最短li到頁面頂部距離怎么求?
原生的方法可以這樣實(shí)現(xiàn):
function getTop(obj){
var iTop=0;
while(obj){
iTop+=obj.offsetTop;
obj=obj.offsetParent;
}//累加元素本身和自身所有父級高度偏移值
return iTop;
}
但是本案例既然是用jquery,自然有它的方法。
obj.offset().top
滾動事件
原生的實(shí)現(xiàn)方法是:window.onscroll=function(){...}
jquery的實(shí)現(xiàn)方法是:$(window).scroll(function(){...})
現(xiàn)在驗(yàn)證一下寫出的代碼代碼有沒問題
(window).scroll(function(){
var $li=$('li').eq(getShortestLi());
var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
//console.log([$li.offset().top+$li.height(),document.documentElement.clientHeight+scrollTop])
//如果li高度與li到頁面頂部的高度之和<可視區(qū)高度+滾動距離
if($li.offset().top+$li.height()<document.documentElement.clientHeight+scrollTop){
alert(1);
}
})
運(yùn)行代碼,發(fā)現(xiàn)第一個到底的li出現(xiàn)是可視區(qū)時(shí),彈出1.證明可用。
因?yàn)樯婕暗綕L動事件,所以getJSON相關(guān)函數(shù)應(yīng)該封裝為getList()方便調(diào)用。所以需要重新調(diào)整一下。
此時(shí)的代碼是這樣的:
//找出高度最小li的索引值
function getShortestLi(){
var shortest=0;
for(var i=1;i<4;i++){
if($('li').eq(i).height()<$('li').eq(shortest).height()){
shortest=i;
}
}
return shortest;
}
function createUrl(num){
return 'http://www.wookmark.com/api/json/popular?page='+num+'&callback=?';
}
function getList(n){
$.getJSON(createUrl(n),function(data){
//console.log(data);
for(var i=0;i<data.length;i++){
var $html=var $html=$('<div><img src="'+data[i].preview+'"><p>'+data[i].title+'</p></div>');
//console.log(data[i].height);
$('li').eq(getShortestLi()).append($html);
dataArr[i].height*=225/dataArr[i].width;
$html.find('img').css('height',dataArr[i].height+'px');
$html.find('img').css('width','225px');
};
}
$(function(){
var pageNum=1;
getList(pageNum);
$(window).scroll(function(){
var $li=$('li').eq(getShortestLi();
var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
if($li.offset().top+$li.height()<document.documentElement.clientHeight+scrollTop){
pageNum++;
console.log(pageNum);
getList(pageNum);
}
})
})
這樣一來,好像可以實(shí)現(xiàn)了。但是一看控制臺的console.log,又發(fā)現(xiàn)問題。
如廁的邏輯
在觸發(fā)加載前提時(shí),圖片正在加載,期間動了滾動條,就又觸發(fā)第二次加載,再動一下,就觸發(fā)第三次,于是短短一瞬間,觸發(fā)了n次加載。
那就做一個開關(guān)吧。
就跟公廁邏輯一樣。n個人排隊(duì)進(jìn)一個坑位。外面的人想要進(jìn)去首先得判斷門是否鎖上了。沒鎖才能進(jìn)。進(jìn)去之后第一件事把門鎖上。等如廁完畢,門就打開。后面的人才能進(jìn)
新設(shè)置一個開關(guān)bCheck,默認(rèn)為true。
到觸發(fā)加載條件時(shí),還要判斷bCheck是否為真(門開),為真時(shí)才能觸發(fā)getList()(如廁)。否則return false(只能等)。
getList一開始就把bCheck設(shè)為false(如廁前先鎖門)。等到getList回調(diào)函數(shù)執(zhí)行到尾聲。再把bCheck設(shè)為true(開門)。
這一段不貼代碼了。
總有流完的一天。
當(dāng)數(shù)據(jù)結(jié)束時(shí)(所有人上完廁所),就沒有必要再進(jìn)行加載了(自動把門鎖上)。
所以在getJSON回調(diào)函數(shù)內(nèi)鎖門之后發(fā)現(xiàn)進(jìn)來的是個空數(shù)組,那就進(jìn)行判斷,當(dāng)獲取到data的length為空時(shí),直接returnfalse。那么bCheck就永遠(yuǎn)關(guān)上了。
全部代碼如下:
//找出高度最小li的索引值
function getShortestLi(){
var shortest=0;
for(var i=1;i<4;i++){
if($('li').eq(i).height()<$('li').eq(shortest).height()){
shortest=i;
}
}
return shortest;
}
function createUrl(num){
return 'http://www.wookmark.com/api/json/popular?page='+num+'&callback=?';
}
var bCheck=false;
function getList(n){
$.getJSON(createUrl(n),function(data){
if(data.length==0){
return false;
}else{
for(var i=0;i<data.length;i++){
//console.log(data[i].preview);
var $html=$('<div><img src="'+data[i].preview+'"><p>'+data[i].title+'</p></div>');
$('li').eq(getShortestLi()).append($html);
$html.find('img').css('height',(data[i].height*225/data[i].width)+'px');
$html.find('img').css('width','225px');
};
}
bCheck=true;
});
}
$(function(){
var pageNum=1;
getList(pageNum);
$(window).scroll(function(){
var $li=$('li').eq(getShortestLi());
var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
//console.log([$li.offset().top+$li.height(),document.documentElement.clientHeight+scrollTop])
//如果li高度與li到頁面頂部的高度之和<可視區(qū)高度+滾動距離
if($li.offset().top+$li.height()<document.documentElement.clientHeight+scrollTop){
if(bCheck){
bCheck=false;
pageNum++;
//console.log(pageNum);
getList(pageNum);
}else{
return false;
}
}
})
})
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- jQuery Masonry瀑布流布局神器使用詳解
- 網(wǎng)頁瀑布流布局jQuery實(shí)現(xiàn)代碼
- 基于jquery實(shí)現(xiàn)瀑布流布局
- jQuery實(shí)現(xiàn)瀑布流布局詳解(PC和移動端)
- jQuery+HTML5美女瀑布流布局實(shí)現(xiàn)方法
- Jquery實(shí)現(xiàn)瀑布流布局(備有詳細(xì)注釋)
- jQuery實(shí)現(xiàn)瀑布流布局
- jQuery 瀑布流 絕對定位布局(二)(延遲AJAX加載圖片)
- jQuery 瀑布流 浮動布局(一)(延遲AJAX加載圖片)
- JQuery實(shí)現(xiàn)簡單瀑布流布局
相關(guān)文章
jQuery實(shí)現(xiàn)長按按鈕觸發(fā)事件的方法
這篇文章主要介紹了jQuery實(shí)現(xiàn)長按按鈕觸發(fā)事件的方法,可應(yīng)用于手機(jī)端應(yīng)用程序的開發(fā)中,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-02-02
jQuery實(shí)現(xiàn)table表格checkbox全選的方法分析
這篇文章主要介紹了jQuery實(shí)現(xiàn)table表格checkbox全選的方法,結(jié)合實(shí)例形式分析了jQuery事件響應(yīng)與元素遍歷實(shí)現(xiàn)table表格checkbox元素狀態(tài)動態(tài)修改相關(guān)操作技巧,需要的朋友可以參考下2018-07-07
jquery+ajax每秒向后臺發(fā)送請求數(shù)據(jù)然后返回頁面的代碼
jquery+ajax每秒向后臺發(fā)送請求數(shù)據(jù)然后返回頁面(包括jquery頁面加載完畢才執(zhí)行方法)2011-01-01
jquery實(shí)現(xiàn)簡單的表單驗(yàn)證
這篇文章主要介紹了jquery實(shí)現(xiàn)簡單的表單驗(yàn)證,思路大概是先為每一個required添加必填的標(biāo)記,用each()方法來實(shí)現(xiàn),感興趣的小伙伴們可以參考一下2015-11-11

