首頁 web前端 js教程 jquery實作簡單的瀑布流佈局

jquery實作簡單的瀑布流佈局

Dec 28, 2016 am 10:10 AM

是開頭都會說的原理

瀑布流佈局有兩種,一種是固定列,一種是非固定列。在此主要記述第一種的實現。

固定列的特徵是:無論頁面如何縮放,每行的總列數都一致。

一行4列的瀑布流從佈局的角度來說,就是4個li標籤。透過一定的事件(例如滾動條滾動多少px),然後讀取之,再把資料動態地加入頁面中。

新增資料原則,不是根據li索引值來加,而是根據各列中高度最短的那列動態添加。否則可能導致頁面很難看(左右高度不統一)。

實例涉及ajax方法。可在伺服器環境下運作。

廢話不多說了。直接上樣式。

<ul id="ul1">
 <li>
  <div>
   <img  src="/static/imghw/default1.png"  data-src="images/1.jpg"  class="lazy"   alt="jquery實作簡單的瀑布流佈局" >
   <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p>
  </div>
 </li>
 <li>
  <div>
   <img  src="/static/imghw/default1.png"  data-src="images/2.jpg"  class="lazy"   alt="jquery實作簡單的瀑布流佈局" >
   <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p>
  </div>
 </li>
 <li>
  <div>
   <img  src="/static/imghw/default1.png"  data-src="images/3.jpg"  class="lazy"   alt="jquery實作簡單的瀑布流佈局" >
   <p>我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述我是文字描述</p>
  </div>
 </li>
 <li>
  <div>
   <img  src="/static/imghw/default1.png"  data-src="images/4.jpg"  class="lazy"   alt="jquery實作簡單的瀑布流佈局" >
   <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;
}
登入後複製

基本效果如圖:

jquery實作簡單的瀑布流佈局

樣式顯示沒問題之後,就把li裡面的程式碼刪除。

接下來透過ajax來動態加入。

資料哪裡來?

這裡用的是wookmark的資料介面。

http://www.wookmark.com/api/json/popular?page=1

點開url得到是一個json。

資訊量很大。怎麼分析?

一般可以看文件。但是手頭上沒有文件的情況下,可以看看連結。返回是什麼鬼。

function createUrl(num){
 return &#39;http://www.wookmark.com/api/json/popular?page=&#39;+num+&#39;&callback=?&#39;;
}
$(function(){
 $.getJSON(createUrl(1),function(data){
  console.log(data);
 })
})
登入後複製

控制台列印結果為:

jquery實作簡單的瀑布流佈局

原來是一個50個圖片資訊組成的陣列。每個數組元素都是一個json。在這個簡單的demo裡面,暫時只需要取preview屬性和title屬性就好了。

佈局實現

關鍵之一在於,判斷最短的li,事實上我們需要最短高度li的索引值。

//找出高度最小li的索引值
function getShortestLi(){
 var shortest=0;
 for(var i=1;i<4;i++){
  if($(&#39;li&#39;).eq(i).height()<$(&#39;li&#39;).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=$(&#39;<div><img  src="/static/imghw/default1.png"  data-src="&#39;+data[i].preview+&#39;"  class="lazy"   alt="jquery實作簡單的瀑布流佈局" ><p>&#39;+data[i].title+&#39;</p></div>&#39;);
   //console.log($(&#39;li&#39;).eq(getShortestLi()).height())
   $(&#39;li&#39;).eq(getShortestLi()).append($html);
  };
  console.log([$(&#39;li&#39;).eq(0).height(),$(&#39;li&#39;).eq(1).height(),$(&#39;li&#39;).eq(2).height(),$(&#39;li&#39;).eq(3).height()])
 })
})
登入後複製

再載入看看,版面就出來了。簡單又漂亮。

jquery實作簡單的瀑布流佈局

做到這裡,看起來一切都還挺好。然而潛伏著一個致命的問題。

for循環惹的禍?

看看console.log的資訊。為了分析,我把4個li的高度放進了一個陣列:

50張圖片分4列,少說平均高度也得有三四千像素。

而到循環結束,程式判斷的終點竟然只有令人髮指的1000多個px,因為圖片載入過程慢於for迴圈執行速度。雖然demo裡的顯示還算正常,但這種程式碼在網路速度不好時,會造成工作事故。

思路一:可以判斷圖片是否載入完成。

可以用個定時器監聽下,然後用遞歸實現,我的方案是這樣

var index=0;
function LoadPic(index){
 var $html=$(&#39;<div><img  src="/static/imghw/default1.png"  data-src="&#39;+data[index].preview+&#39;"  class="lazy"   alt="jquery實作簡單的瀑布流佈局" ><p>&#39;+data[index].title+&#39;</p></div>&#39;)
 $(&#39;li&#39;).eq(getShortestLi()).append($html);
 var oImg=$html.find(&#39;img&#39;);
 var t=setInterval(function(){
  if(oImg.height()!=0){//如果加载完了。
   clearInterval(t);
   //console.log([$(&#39;li&#39;).eq(0).height(),$(&#39;li&#39;).eq(1).height(),$(&#39;li&#39;).eq(2).height(),$(&#39;li&#39;).eq(3).height()])
   if(index<50){
    return LoadPic(index+1);
   }else{
    return false;
   } 
  }else{
   console.log(&#39;wait&#39;)
  }
 },50)//每隔50ms监听一次
}
LoadPic(0);
登入後複製

但是,從用戶體驗的角度來說,等一張圖加載完成再進行下一張加載是不友好的。資料提供方都應該直接把圖片的高度在伺服器處理好,json資料裡面回傳過來。網速很慢的時候,要等好久,然後一下子圖片都出來了,不覺得很詭異嗎?尤其是第三方介面。一加載不出來就出大問題了。

所幸的是,第三方提供了圖片的寬高資訊。

因此for迴圈還是可以有的,在回傳的資料裡面,有寬度和高度值。利用它們就可以實現定寬(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=$(&#39;<div><img  src="/static/imghw/default1.png"  data-src="&#39;+data[i].preview+&#39;"  class="lazy"   alt="jquery實作簡單的瀑布流佈局" ><p>&#39;+data[i].title+&#39;</p></div>&#39;)
    $(&#39;li&#39;).eq(getShortestLi()).append($html);
     
    $html.find(&#39;img&#39;).css(&#39;height&#39;,(data[i].height*225/data[i].width)+&#39;px&#39;);
    $html.find(&#39;img&#39;).css(&#39;width&#39;,&#39;225px&#39;); 
   };
  //console.log([$(&#39;li&#39;).eq(0).height(),$(&#39;li&#39;).eq(1).height(),$(&#39;li&#39;).eq(2).height(),$(&#39;li&#39;).eq(3).height()])
 })
})
登入後複製

事實上個人認為這是最簡單且使用者體驗最好的方案。

有了瀑布,還需要流

流的邏輯

往下拉(滾動),第一個底部進入可視區的li,優先加載。

jquery實作簡單的瀑布流佈局

換句話說,最短li的高度與該li到頁面頂部之和小於滾動條高度和可視區高度之和時,觸發li加載。

li的高度好求。但是最短li到頁面頂部距離怎麼求?

原生的方法可以這樣實現:

function getTop(obj){
 var iTop=0;
 while(obj){
  iTop+=obj.offsetTop;
  obj=obj.offsetParent;
 }//累加元素本身和自身所有父级高度偏移值
 return iTop;
}
登入後複製

但是本案例既然是用jquery,自然有它的方法。

obj.offset().top

滾動事件

原生的實作方法是:window.onscroll=function(){...}

jquery的實作方法是:$(window).scroll(function( ){...})

現在驗證一下寫出的代碼代碼有沒問題

(window).scroll(function(){
 var $li=$(&#39;li&#39;).eq(getShortestLi());
 var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
 //console.log([$li.offset().top+$li.height(),document.documentElement.clientHeight+scrollTop])
 //如果li高度与li到页面顶部的高度之和<可视区高度+滚动距离
 if($li.offset().top+$li.height()<document.documentElement.clientHeight+scrollTop){
   alert(1);
 }
})
登入後複製

運行代碼,發現第一個到底的li出現是可視區時,彈出1.證明可用。

因為涉及滾動事件,所以getJSON相關函數應該封裝為getList()方便呼叫。所以需要重新調整一下。

此時的程式碼是這樣的:

//找出高度最小li的索引值
function getShortestLi(){
 var shortest=0;
 for(var i=1;i<4;i++){
  if($(&#39;li&#39;).eq(i).height()<$(&#39;li&#39;).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;ijquery實作簡單的瀑布流佈局

'+data[i].title+'

'); //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()
登入後複製

這樣一來,好像可以實現了。但是一看控制台的console.log,又發現問題。

如廁的邏輯

在触发加载前提时,图片正在加载,期间动了滚动条,就又触发第二次加载,再动一下,就触发第三次,于是短短一瞬间,触发了n次加载。

那就做一个开关吧。

就跟公厕逻辑一样。n个人排队进一个坑位。外面的人想要进去首先得判断门是否锁上了。没锁才能进。进去之后第一件事把门锁上。等如厕完毕,门就打开。后面的人才能进

新设置一个开关bCheck,默认为true。

到触发加载条件时,还要判断bCheck是否为真(门开),为真时才能触发getList()(如厕)。否则return false(只能等)。

getList一开始就把bCheck设为false(如厕前先锁门)。等到getList回调函数执行到尾声。再把bCheck设为true(开门)。

这一段不贴代码了。

总有流完的一天。

当数据结束时(所有人上完厕所),就没有必要再进行加载了(自动把门锁上)。

所以在getJSON回调函数内锁门之后发现进来的是个空数组,那就进行判断,当获取到data的length为空时,直接returnfalse。那么bCheck就永远关上了。

全部代码如下:

//找出高度最小li的索引值
function getShortestLi(){
 var shortest=0;
 for(var i=1;i<4;i++){
  if($(&#39;li&#39;).eq(i).height()<$(&#39;li&#39;).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;ijquery實作簡單的瀑布流佈局

'+data[i].title+'

'); $('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到页面顶部的高度之和<可视区高度+滚动距离 if($li.offset().top+$li.height()
登入後複製

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持PHP中文网!

更多jquery實作簡單的瀑布流佈局相关文章请关注PHP中文网!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1675
14
CakePHP 教程
1429
52
Laravel 教程
1333
25
PHP教程
1278
29
C# 教程
1257
24
Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript和Web:核心功能和用例 JavaScript和Web:核心功能和用例 Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在行動中:現實世界中的示例和項目 JavaScript在行動中:現實世界中的示例和項目 Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

了解JavaScript引擎:實施詳細信息 了解JavaScript引擎:實施詳細信息 Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:社區,圖書館和資源 Python vs. JavaScript:社區,圖書館和資源 Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

Python vs. JavaScript:開發環境和工具 Python vs. JavaScript:開發環境和工具 Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

C/C在JavaScript口譯員和編譯器中的作用 C/C在JavaScript口譯員和編譯器中的作用 Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

Python vs. JavaScript:比較用例和應用程序 Python vs. JavaScript:比較用例和應用程序 Apr 21, 2025 am 12:01 AM

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

See all articles