LoginSignup
18
25

More than 5 years have passed since last update.

iScroll.js と drawer.js のハンバーガーメニューがAndroidで動かない

Last updated at Posted at 2017-05-22

概要

drawer.jsを使った、スマホ用バーガーメニュー実装で、新しいAndroidのChromeにおいて長いメニューがスクロールしない症状がありました。スクロールは、全くしない訳では無く、フリックで素早く動かすと若干スクロールするものの、通常のタップ移動では指を離したタイミングでメニューが閉じてしまいます。この不具合の修正を試みました。

詳細

Androidでは、2016年末頃からスクロール動作を滑らかにするために、addEventListenerにイベントを登録する際、デフォルトでそのイベント内部の preventDefault を実行しないモードになりました。
jQuery の on() でイベントを登録している場合、addEventListener の第3引数に {passive: false} を加えられるようなオプションは無いため、drawer.js内部で on()を使用している箇所をaddEventListener を使って書き直す必要があります。加えて何かとバグの多いiscroll.js ではAndroidのタッチ動作をうまく検出出来ていない様子なので、スマホだけに表示させる画面、という前提で動作するよう修正試みました。

修正ポイント

drawer.js(v3.2.2)

19行目

iScroll.js のデフォルトオプションを定義している部分。preventDefaultが基本ONになるようにしている。
修正前

drawer.js
          preventDefault: false

修正後

drawer.js
          preventDefault: true,

107行目

修正前

drawer.js
      if (touches) { 
        $this.on('touchmove.' + namespace, function disableTouch(event) { 
          event.preventDefault(); 
        }); 
      } 

修正後

drawer.js
      if (touches) {
        document.addEventListener('touchmove.' + namespace, function disableTouch(event) {
          event.preventDefault();
        }, {passive: false});
      }

iscroll.js(v5.2.0)

42行目

内部でaddEventListnerを addEventとしてエイリアスを作っている部分があるので、ここで Android対応の書き方にする。
修正前

iscroll.js
    me.addEvent = function (el, type, fn, capture) { 
        el.addEventListener(type, fn, !!capture); 
    }; 

修正後

iscroll.js
    me.addEvent = function (el, type, fn, capture) {
        el.addEventListener(type, fn, {passive: false});
    };

191行目

マウスポインタの場合の処理だが、スマホのみで使う前提なので、タッチイベントと同じものとして扱わせる。

修正前

iscroll.js
        pointerdown: 3,
        pointermove: 3,
        pointerup: 3,

修正後

iscroll.js
        pointerdown: 1,
        pointermove: 1,
        pointerup: 1,

331行目

ポインター、マウスなどをdisableにする処理だが、条件分岐がAndroidの場合、望んだとおりにならないようなので、タッチデバイスしか扱わないのとChromeのデバッグ環境でも動くことを考えて修正。

修正前

iscroll.js
        disablePointer : !utils.hasPointer,
        disableTouch : utils.hasPointer || !utils.hasTouch,
        disableMouse : utils.hasPointer || utils.hasTouch,

修正後

iscroll.js
        disablePointer : false,
        disableTouch : false,
        disableMouse : false,

482行目、622行目

e.preventDefault();をコメントアウト

これは
IScroll.prototype = {の中の
_start: と
_end: のpreventDefault を無効にしている。

以上で Android と iPhoneで正常動作するようになった。

参考

この問題が起きているときに、Chromeブラウザのデバッグコンソールに以下のメッセージがでます。
Unable to preventDefault inside passive event listener due to target being treated as passive.

18
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
25