標籤:
現在類似於pinterest這類的表現效果很火,其實我比較中意的是他的布局效果,而不是那種瀑布流。
雖然我不是特別喜歡這種瀑布流的表現樣式,但是還是寫了幾篇關於無限滾動瀑布流效果的文章,Infinite scroll+Masonry=無限滾動瀑布流,infinite-scroll-jquery捲軸(下拉)載入資料外掛程式之類的文章。可能是我表達描述不是很詳細清楚,所以好多朋友看了不是很清楚,並發信給我求解釋。所以有了今天這篇文章。
其實早在:十幾款jquery無限滾動外掛程式這 篇文章中我就提到過這種效果的實現原理。主要是判斷捲軸滾動的位置距離底部的距離,如果小於或者等於設定的高度的話,那麼就執行ajax載入非同步資料到 固定的盒子中。我想大家對於這點是比較清楚的,恐怕對於怎樣擷取資料有點不甚了了的感覺。OK,下面看痞子的步步解析!
無限滾動第一步,ajax非同步載入的條件:
我們都知道,對於一些列表頁面的布局結構都是一樣的,資料部分是由程式產生的。並且每個頁面都有下一頁的連結地址。OK完畢,這點這是基本條件(注意紅色部分)。
為了給大家做直觀的對比,我這裡拿出3個頁面進行對比分析,其中採用的masonry的效果,關於這個外掛程式我這裡不多說,可以看Masonry-jquery外掛程式打造的瀑布流樣式效果來對該效果有個簡單的認識。這三個頁面的結構是一樣的,內容是不一樣的(我們用不同的圖片來區分)。
這三個頁面左邊都有下一頁的連結,連結層次分別是
default.html -> default1.html ->default2.html -> 無
下面是三個頁面地址:
http://www.niumowang.org/demo/infinite/default.html
http://www.niumowang.org/demo/infinite/default1.html
http://www.niumowang.org/demo/infinite/default2.html
我們點擊每個頁面的下一頁會看到,頁面會開啟一個新的頁面結構與之前的頁面相同,內容不同。最後一個頁面default2.html的下一頁連結處是空串連,代表後面沒有頁面了。
無限滾動第二步,ajax非同步載入如何進行:
第一步的工作完成後,我們要在上面的下一頁連結處做文章。在第一步提供的連結中,我們點擊下一頁都會開啟下一頁的連結,並顯示內容。但是我們現在要做的就是用ajax非同步載入資料到當前頁面,實現點選連結不開啟新的頁面,但是載入這個連結中的資料到本頁面。這裡當然就用到了ajax了,所幸jquery封裝的ajax比較簡單,我們很容易實現將其他頁面的內容載入到當前頁面中。
還是三個結構相同,內容不同的頁面:(點擊下一頁可以看到效果)
http://www.niumowang.org/demo/infinite/ajax.html
http://www.niumowang.org/demo/infinite/ajax1.html
http://www.niumowang.org/demo/infinite/ajax2.html
我們來看具體實現代碼部分:
$(".next_page a").click(function() { //首先取得下一頁的連結地址 var href = $(this).attr("href"); //判斷該連結是否被載入過 startHref = href; //判斷下一頁的連結地址是否存在 if (href != undefined) { //如果存在的話,用ajax擷取資料 $.ajax({ type: "get", url: href, success: function(data) { //將返回的資料進行處理,挑選出class是post的內容塊 var $res = $(data).find(".post"); //結合masonry外掛程式,將內容append進ID是content的內容塊中 $("#content").append($res).masonry(‘appended‘, $res); //newHref擷取返回的內容中的下一頁的連結地址 var newHref = $(data).find(".next_page a").attr("href"); //判斷下一頁地址是否存在,如果存在,替換當前頁的連結地址。不存在,將當前頁連結地址屬性href移除,並替換內容為“下一頁沒有了” if (newHref != undefined) { $(".next_page a").attr("href", newHref); } else { $(".next_page a").html("下一頁沒有了").removeAttr("href") } } }) } //返回false,使得點擊進入新頁面失效 return false; })
用文字表達一下這個過程就是:點選連結,非同步載入這個連結中的資料後,挑選出合格內容,然後將內容用js載入到這個頁面固定的容器中,並且將這個連結的地址替換成新的連結地址。並對如果沒有下一頁的情況進行處理。
其中找到下一頁的連結地址可能情況比較多變一些,比如存在“123456...”這樣的連結結構;當然這種情況的話,我們可以採用擷取比如 class為current的連結地址,那麼下一頁的地址就是current後面的一個連結,然後用返回資料將包含所有分頁地址的容器替換掉。所謂具體問 題具體分析,這裡點到即止。
另外就是masonry將ajax返回的資料進行重新布局的操作了,這個屬於masonry的範疇,不做過多解釋。關於masonry自己從本站找相關資料。
無限滾動第三步,捲軸控制無限載入:
所謂捲軸控制無限滾動,只不過把點擊的效果替換掉。我們通過滾動滑鼠滾輪,或者拖動捲軸到底部來實現原來的點擊非同步載入資料的情況。
如果你要實現的話,該怎麼做呢?
是的,我們只需要判斷捲軸距離底部的位置就行了。如果到了底部,我們就載入一次資料。
但是還有一個問題,由於我們需要即時擷取捲軸的最新位置,而擷取捲軸位置不是自動的,我們總不能點擊一個按鈕擷取一次資料吧,或者用setTimeout,每隔一段時間擷取一次資料。當然這些都是不可行的。
比較可行的方法就是:我們給(window)視窗綁定一個scroll事件,所謂綁定事件就是監聽這個對象,監視它的一舉一動。如果window視窗滾動的時候,捲軸到底了,那麼我們可以進行我們的小動作非同步載入資料進來了。OK,看代碼實現。
//首先給視窗綁定事件scroll $(window).bind("scroll",function() { // 然後判斷視窗的捲軸是否接近頁面底部,這裡的20可以自訂 if ($(document).scrollTop() + $(window).height() > $(document).height() - 20) { //我這裡偷個懶,沒有寫ajax的調用,直接觸發了連結的click事件。 if($(".next_page a").attr(‘href‘) != startHref){ //這裡判斷當前要載入的連結是否已經載入過 $(".next_page a").trigger("click"); } } })
示範地址:http://www.niumowang.org/demo/infinite/auto_ajax.html
上面代碼部分,我沒有寫ajax的具體調用過程,而是在原基礎上觸發了連結的點擊事件。如果想要看滾動實現的ajax效果的,開啟地址:http://www.niumowang.org/demo/infinite/auto_ajax1.html自行查看代碼部分。
上面有個數字是20,就是捲軸距離底部還是20像素的時候開始載入。這裡是為了實現積極式載入效果,不至於當使用者滾動到底部的時候,資料還沒有載入出來,如果你感覺你的內容較大的話,還可以增加這個值。
無限滾動效果實現原理,總結:
至此一個捲軸實現無限滾動的效果就說完了。做一個最後的總結工作。
可以說目前網上實現無限滾動的效果各有千秋,基於的架構也不盡相同。我寫這篇文章的目的是讓大家領會一種思路,能明白這種效果是怎麼做出來的。
我這種方法的文字原理部分:捲軸滾動後,如果到達底部,或者距離底部一段距離的時候,找到下一頁的連結地址,擷取這個地址中的資料。然後將返回的資料,採用重新布局添加到固定的容器中。OK,就這麼簡單。
無限滾動的進階進階部分:
話說進階進階也沒有多麼進階,只不過可能載入資料不是採用這種get或者post,哪怕load頁面的方式,而是通過傳參,從資料庫讀取資料。亦或 是增加一些返回資料的特效,比如返回資料後,重新布局的時候增加點動畫,或者捲軸增加點平滑滾動效果。不過爾爾,記住一句話:只要去實踐,一切技術派都 是紙老虎。
2012.08.30 BUG調整
下面好幾個朋友提到了多次載入的問題,由於當初設計的時候沒有考慮到載入內容後捲軸變化的問題。所以出現了這個情況。近日有時間解決一下。順便感謝下面提出問題的幾位朋友。
修改方法,主要是定義一個全域變數 var startHref ;
然後next_page觸發一次之後,修改此startHref的值,在滾動的時候拿到當前的next_page中連結的值,與startHref進行對比,如果不同的話再執行載入過程。
效果查看:http://www.niumowang.org/demo/infinite/auto_ajax.html
jquery實現無限滾動瀑布流實現原理