iScroll.js的scroll不順怎麼辦?

如果有寫WebApp的人一定會遇到要對content做scroll的需求。這時候你通常有幾種選擇:
  1. 把不需要scroll的DOM元件的CSS position屬性設定為fixed,然後依靠device上預設的web browser的scroll功能。這個功能絕對行得通,但是如果是在iOS上的話,你一定會覺得為什麼這個scroll特別黏?就是一做fling的動作,就是沒有其他原生App的scroll的流暢。其實你試試iOS上的Safari,的確就是這個行為沒錯,感覺是特別設計有什麼特殊用意並不清楚。但是很明顯的這個方法對於要求原生App的UI體驗是不夠的。
  2. iOS5之後的WebBrower有支援一個特別的overflow值,也就是 overflow:scroll 。設定這個之後,超過容器空間的iOS會自動套用原生的scroll功能。也行得通,如果你不打算支援iOS4的話。
  3. 為了克服以上兩個問題,我的選擇是使用iScroll.js,一個Open Source的JavaScript library。很強大,把scroll模擬的很好,而且也會自動產生捲軸。大致上的原理是使用Timer(window.setTimeout)來模擬scroll,也有支援momentum。但是我一直很疑惑的是怎麼在實際的iOS裝置上的scroll animation的frame rate 竟然或是這麼低呢?好吧,重點就在他用了setTimeout! setTimeout! setTimeout! 所以frame rate低是很正常的啊,大概連15fps都不到吧。這時候想說如果用CSS transition(感謝我曾經在之前的公司present過CSS3)的話應該會順暢很多吧。畢竟transition是native code在做animation,而且適當的trick(就是設定一個完全沒作用的3D Transform)還可以啓動硬體加速,FPS一定可以提升到30以上。於是我打開iScroll的source code:
     // Constructor
     iScroll = function (el, options) {
      var that = this,
       doc = document,
       i;
    
      that.wrapper = typeof el == "object" ? el : doc.getElementById(el);
      that.wrapper.style.overflow = "hidden";
      that.scroller = that.wrapper.children[0];
    
      // Default options
      that.options = {
       hScroll: true,
       vScroll: true,
       x: 0,
       y: 0,
       bounce: true,
       bounceLock: false,
       momentum: true,
       lockDirection: true,
       useTransform: true,
       useTransition: false,
       topOffset: 0,
       checkDOMChanges: false,  // Experimental
    
       // Scrollbar
       hScrollbar: true,
       vScrollbar: true,
       fixedScrollbar: isAndroid,
       hideScrollbar: isIDevice,
       fadeScrollbar: isIDevice && has3d,
       scrollbarClass: "",
    
       // Zoom
       zoom: false,
       zoomMin: 1,
       zoomMax: 4,
       doubleTapZoom: 2,
       wheelAction: "scroll",
    
       // Snap
       snap: false,
       snapThreshold: 1,
    
       // Events
       onRefresh: null,
                onBeforeScrollStart: function (e) { e.preventDefault(); },
       onScrollStart: null,
       onBeforeScrollMove: null,
       onScrollMove: null,
       onBeforeScrollEnd: null,
       onScrollEnd: null,
       onTouchEnd: null,
       onDestroy: null,
       onZoomStart: null,
       onZoom: null,
       onZoomEnd: null
      };

    你看到第22行了嗎?useTransition: false,哇,太令人欣慰了。我什麼都不用改耶。只要把它改成 useTransition: true 就好了耶(但還是要記得把要scroll的DOM加上null 3D transform)。果然一改完就很順。省了我很多時間:)



Comments
  1. 回覆

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *