IScroll的誕生和缺點


轉自http://lhdst-163-com.iteye.com/blog/1239784

iscroll.js是Matteo Spinelli開發的一個js文件,使用原生js編寫,不依賴與任何js框架。旨在解決移動webkit系瀏覽器的區域滾動問題,兼容mobile safari、Android默認瀏覽器、safari、chrome、firefox5+、opera11+、IE9+及其他webkit核心瀏覽器。最新版本為iscroll4。 

官方網站:iscroll4 

iscroll的用武之地 

1.區域滾動 

我們在pc端web開發中,有時會用固定某一區域的寬度和高度,然后使用overflow:auto,使其內容在該區域內滾動。 

iphone默認瀏覽器(mobile safari)也支持固定區域的滾動,但必須雙指滑動操作,而且沒有滾動條。mobile safari中的單指滑動只針對頁面級別,不針對頁面元素。這樣的操作體驗很麻煩,而且很多用戶根本不知道雙指能夠區域滑動。 

android自帶瀏覽器也支持區域滾動,且可以單指滑動操作,但是滑動起來卡的半死半活,很不流暢。 

使用iscroll,可以完美解決上述問題了,不僅可以在iphone和android上單指滑動,而且滑動起來流暢之極,酣暢淋漓。滑動過程中也有漂亮的滾動條提示,讓你舒心不已。 

2.固定定位 

固定定位不是iscroll的原生用法,而是使用iscroll協助解決固定定位問題。 

話說iphone很先進,但就是不支持position:fixed。這下苦了我們了,固定定位怎么解決啊,我們會經常遇到固定標題欄、固定工具欄等情況啊!! 

使用iscroll協助解決:首先獲取瀏覽器窗口高度;然后獲取固定工具欄的高度;接着將除固定工具欄之外的內容全部放在一個固定區域內,該固定區域的高度=窗口高度-工具欄高度;之后對固定區域使用iscroll。這樣,整個html頁面的高度正好等於窗口高度,頁面級別不會出現滾動,工具欄就一直固定在當前的位置。在固定區域內滑動,可以查看頁面其他內容,不會影響工具欄的定位。 


鼠標滾輪滾動 

iscroll支持在pc端瀏覽器中使用鼠標滾輪控制區域滾動,但操作起來很不靈敏。這是由於iscroll對鼠標滾輪事件做了攔截,然后縮小了滾輪的滾動距離,詳見iscroll4.js源代碼608-609行: 

wheelDeltaX = e.wheelDeltaX / 12;//控制X軸鼠標滾輪速度 
wheelDeltaY = e.wheelDeltaY / 12;//控制Y軸鼠標滾輪速度 
    iscroll將每次的滾輪距離縮小為系統默認距離的12分之一,難怪滾起來很慢,感覺不靈敏。只需要將12改成1,滾輪的滾動速度就恢復正常了。你也可以根據實際需要設置成其他值。 
輸入框聚焦不靈敏、無法選擇文字 

    使用了iscroll之后,你會發現點擊輸入框時不靈敏,經常無法聚焦;頁面文字也無法選擇和復制。這是由於iscroll要監聽鼠標事件和觸摸事件來進行滾動,所以禁止了瀏覽器的默認行為,詳見源代碼92行: 
onBeforeScrollStart: function (e) { e.preventDefault(); }, 
iscroll不分青紅皂白,禁止了瀏覽器的一切默認行為,導致上述問題。所以我們需要稍作修改: 
onBeforeScrollStart: function (e) { 
var target = e.target; 
while (target.nodeType != 1) target = target.parentNode; 
if (target.tagName != ‘SELECT’ && target.tagName != ‘INPUT’ && target.tagName != ‘TEXTAREA’) 
e.preventDefault(); 
}, 
    判斷觸發事件的元素是不是input、select、textarea等表單輸入類元素,如果不是就阻止默認行為。這樣保證了輸入類元素能正確快速聚焦。 
在上述修改中追加一個條件 target.tagName != ‘body’或者直接將onBeforeScrollStart修改為null,即可做到鼠標選取文字,但這樣的修改會導致iscroll滾動失效或不靈敏,所以無法選取文字這個問題先放一邊吧。如你有更好的方法,歡迎回復。 
select元素操作不靈敏或操作后白屏 

    使用iscroll后,還有一個較麻煩的問題,就是select元素點擊不靈敏(滾動之后點擊select,經常無響應);有時點擊有反應了,下拉菜單顯示卻錯位(pc端);選擇一項之后,頁面直接變成了空白(iphone、android中)或者頁面位置向上偏離,滾動區域位置出現偏離。 
    說白了,就是導致select沒法用。為此我調試了很久,最后發現了問題所在:iscroll默認使用的是css的transform變形中的translate3d實現區域滾動,每次滾動實際是改變translate3d中的y軸值,實際的dom位置並沒有發生變化。translate3d會導致頁面的焦點錯誤,系統級下拉菜單的顯示則會導致其出現顯示偏離。 
    控制滾動模式的代碼在67行:useTransform: true。好在iscroll提供了另一種滾動方式,基於絕對定位位置變化的滾動。修改為useTransform: false之后,iscroll就會使用對定位位方式來實現滾動,該方式是我們在web開發中模擬動畫的最常用方式,滾動之后dom的實際位置也同步發生了變化,不會出現錯位偏離現象。 
    在pc端主流瀏覽器、iphone、android2.2下測試,select問題完美解決。 
    不過需要注意,使用對position決定定位后,滾動區的寬度默認會自適應內容寬度,而不是父元素的100%,所以最好將滾動區域寬度設為100%。 
美中不足 

    iscroll是小而精的經典作品,名字也帶着apple范。但唯一美中不足的是,只能使用id調用。

=================================================================================

下面是另一篇博文,轉自http://blog.chinaunix.net/uid-25820084-id-3524194.html

 

iscroll4 是一款針對web app使用的滾動控件,它可以模擬原生iOS應用里的滾動列表操作,雖然插件不大但是效果十分好。是web app開發必備的控件之一。

iscroll4官網 : http://cubiq.org/iscroll-4

 

為什么要用iscroll4

因為在IOS5之前,web webkit是不支持一種原生方法去滾動固定 長/寬 容器里的內容的。簡單的說,就是css屬性 overflow:scroll在IOS5 之前是不生效的。

這就像兼容萬惡的IE6一樣,作者希望通過寫一個控件,讓所有web瀏覽器支持這種滾動,於是iscroll4應運而生。

在解決了兼容性的問題之外,它還提供了需求許多交互的解決方案,如:

1.雙指放大縮小操作

2.下拉刷新/上拉加載更多

3.逐個元素定位的滾動列表

 

使用iscroll4可能會遇到的問題

1.在iscroll4的滾動容器范圍內,點擊input框、select等表單元素時沒有響應

這個問題原因在於iscroll需要一直監聽用戶的touch操作,以便靈敏的做出對應效果,所以它把其余的默認事件屏蔽了,解決的方法是,在iscroll4源碼里面找到這一行

1
onBeforeScrollStart: function (e) { e.preventDefault(); }

然后把它改成

1
onBeforeScrollStart: function (e) { var nodeType = e.explicitOriginalTarget © e.explicitOriginalTarget.nodeName.toLowerCase():(e.target © e.target.nodeName.toLowerCase():'');if(nodeType !='select'&& nodeType !='option'&& nodeType !='input'&& nodeType!='textarea') e.preventDefault(); }

這樣只要你touch的元素是 select || option || input || textarea時,它就不會執行e.preventDefault(),默認的事件就不會被屏蔽了。

 

如果你有其他不想被屏蔽的元素,可以自己修改,不過需要注意onBeforeScrollStart里的屏蔽默認事件很重要,它是iscroll進行流暢滾動的基礎,不要隨便的把它去掉,否則你會發現滾動起來很卡頓。

2.往iscroll容器內添加內容時,容器閃動的bug

我在做上拉加載更多內容的時候,肯定需要把新的內容插入到容器內,這時發現有時容器會出現閃動,一開始認為是insert進去的內容太多,后來又覺得是不是因為里面布局用了float的原因導致重新渲染,最后通通排除。

其實病灶在於iscroll使用了太為先進的CSS3屬性,可能web webkit對這些屬性的支持力度還是不夠好。

涉及的兩個屬性是  translate3d 和 TransitionTimingFunction,或許是這兩個屬性在列表長度改變時會影響到渲染,所以導致頁面閃動,解決辦法就是找到源代碼的

1
has3d = 'WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix()

改成

1
has3d = false

和在配置iscroll時,useTransition設置成false就可以了(useTransition默認是false的)。

 

這樣做有一點瑕疵就是滾動起來和原來比沒那么流暢了(原來的效果真的是可以媲美原生app的),但是假如你不對比的話,是看不出來了。

在效果和體驗上面選擇,我更看重體驗。

不夠如果你符合下面的條件,我還是不建議你修改成我這樣

1)即使你不修改,無論你怎么往iscroll容器里面插內容,它都不會閃動,這種情況大多出現在純文字的列表。假如列表涉及復雜的布局和圖片,很多時候會出現閃動bug

2)如果你的web app只是單純在手機瀏覽器瀏覽。translate3d 和 TransitionTimingFunction只是在ios里的uiwebview支持不成熟,但是在手機上的safari完全沒有問題,所以如果你不是用phonegap之類的框架開發混合app,你不需要擔心這個問題。

3)只針對android,因為android的webkit暫時還不支持translate3d,iscroll會自動選擇不用。

3.過長的滾動內容,導致卡頓和app直接閃退

說白了iscroll都是用js+css3實現的,對瀏覽器的消耗肯定是可觀的,避免無限制的內容加載本身就是web產品應該避免的。

假如無可避免,我們可以盡量減低iscroll對瀏覽器內存的消耗

1)不要使用checkDOMChanges。雖然checkDOMChanges很方便,定時檢測容器長度是否變化來refresh,但這也意味着你要消耗一個Interval的內存空間

2)隱藏iscroll滾動條,配置時設置hScrollbar和vScrollbar為false。

3)不得已的情況下,去掉各種效果,momentum、useTransform、useTransition都設置為false

4.左右滾動時,不能正確響應正文上下拉動

在做這種效果時 ,假如這個幻燈片模塊只是你頁面的一部分,你還需要上下拉動頁面去瀏覽其它內容時,你的手指在這個模塊上做上下撥動時,恐怕會沒有反應。原因還是和問題1一樣的,因為屏蔽了默認事件。

完美的解決方法是沒有的,如果把 e.preventDefault() 去掉,幻燈片的滾動效果就會大打折扣,而且有時用戶上下撥動的操作會被誤操作成幻燈片的滾動。所以在效果還是體驗上,大家還是自己選擇吧。在技術上解決不了的問題,我認為還是多和產品和UI溝通比較好,共同協商一個良好的方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM