javascriptで、スマホのスクロールを制御する方法をご紹介します。
ハンバーガーメニューを開いたとき、画面のスクロールを停止する例を実装します。
ぼちぼち役立つ時があると思うので、頭の片隅に置いてみてください。
スマホのスクロールをキャンセルする方法
まずはデモをご覧ください。(スマートフォンで開いてください。PCだとイベントが発生しないので)
右上から展開するナビを開いている間はスクロールができません。
overflow:hiddenは間違い。
たとえば、ハンバーガーメニューを開いたときに、body要素にclassをつけたりして「overflow: hidden;」すればいいんじゃね?と思いがちですが、これは誤りで、
iOSのsafariやAndroidのChromeだと普通にスクロールできてしまうので、大抵のケースで、開いたナビの下に隠れているコンテンツがスクロールされてしまうことになります。
解決法1 : position: fixed;
bodyタグにposition: fixedを指定することでもスクロールを阻止することができます。(厳密には「キャンセル」ではないのですが
この場合は高さや幅の指定が要るんじゃないかな、と思います。
1 2 3 4 5 6 7 8 9 10 11 | body.fixed{ width: 100%; height: 100%; margin: auto; position: fixed; top: 0; right: 0; bottom: 0; left: 0; overflow: hidden; } |
解決法2: touchmoveをキャンセルする
ケースによりますが、今回の正解はこちらです。
スマホでスクロールするときに発生する「touchmove」イベントをキャンセルします。
デモで使っている手法ですが、ざっくりと簡略化して書くとこのようになります。
1 2 3 4 5 6 7 | var scrollOff = function( e ){ e.preventDefault(); } // スクロールをキャンセル document.addEventListener( ‘touchmove’,scrollOff, false); //removeEventListenerで「スクロールをキャンセル」をキャンセル document.removeEventListener( ‘touchmove’, scrollOff, false ); |
touchmoveが発生したときに、e.preventDefaultで動作を初期化します。
ここでポイントなのは、スクロールをキャンセルする動作は関数化することと、addEventListenerで呼び出すときは引数で「e」を渡さないことです。
スクロールをキャンセルする動作は関数化する
removeEventListenerでイベントに対する操作を無効化するためには、そとからでも参照できるように処理を関数化しなくてはいけません。
https://developer.mozilla.org/ja/docs/Web/API/EventTarget/removeEventListener
jQueryで言うところの「.off」です。
addEventListenerで呼び出すときは引数で「e」を渡さない
関数化したpreventDefaultは「e 」を受け取っていますが、関数の引数でeを渡してしまうと、別のオブジェクトが渡ってしまうようです。これは気付かず少しハマってしまいました…
addEventListenerに対してremoveEventListener
リッチな表現にも使うことの出来る技術なので覚えて損はないですよ。
でわ!