JS Girls Osaka #1 サンプルコード
ドロワー
ドロワーとは
ドロワーというナビゲーションの再考 | Reflection | UIデザイン会社Standard Incのブログ
コーディングパターン
パターン1
- メニューボタンのクリックでの開閉
- スライドアニメーションをjQueryの
animate()
で実現 position
プロパティのleft
/right
の値を操作- スライドアニメーションはIE8でも動作
パターン2
- メニューボタンのクリックでの開閉
- スライドアニメーションをCSSの
transition
プロパティで実現 position
プロパティのleft
/right
の値を操作- スライドアニメーションはIE10以上で動作、一部ブラウザでは
transition
プロパティに-webkit-
プレフィックスが必要(参照:Can I use)
パターン3
- メニューボタンのクリックでの開閉
- スライドアニメーションをCSSの
transition
プロパティで実現 transform
プロパティのtranslateX
の値を操作transform: translateZ(0)
によりハードウェア・アクセラレーションを有効化しスムーズにアニメーションさせる- スライドアニメーションはIE10以上で動作、一部ブラウザでは
transition
プロパティ(参照:Can I use)およびtransform
プロパティ(参照:Can I use)に-webkit-
プレフィックスが必要
パターン4
- パターン3のプラスアルファ版
- ドロワーの開閉にタッチイベントを使うことでスマホなどタッチデバイスにおける操作をより快適に
- 300msディレイ問題
- タッチイベントには、
touchstart
(画面に指が触れた)touchmove
(画面上で指が動いている)touchend
(画面から指が離れた)touchcancel
(タッチイベントをキャンセル)がある(Appleによる詳細説明) - iPhoneやAndroidのwebkitでは、
touchend
してからclick
イベントが起きるまでに300ms程度の待ち時間がある - その待ち時間では、ダブルタップによるズーム(一度画面から指を離してから、もう一度タップされるかどうか)の判定をしている
- つまり
click
イベントだとその待ち時間によってタッチデバイスではモッサリ(反応が鈍い)ように感じるため、タッチイベント(touchstart
かtouchend
)を使う方がよい - Chrome for Android 32、Firefox for Android 11ではviewportの設定で300msの遅延を防げるようになった
- 【参考】 Chrome Developer Teamから学ぶサイトパフォーマンス
- このため、GoogleのWeb Starter Kitのドロワーの開閉には
click
イベントのみの設定になっている
- タッチイベントには、
touchstart
とtouchend
どちらがいいのか問題- コードでは
touchstart
でイベントが起きるようにしているが、それだとその要素がある場所(より画面の**に近い位置など)によっては、ただ画面をスクロールしたいだけなのに、指を置いた場所にtouchstart
でイベントが起きる要素があると、スクロールできずにイベントが発火してしまい、ユーザーの意図した操作ができなくなってしまう - 一方
touchend
にした場合、要素の外から指を動かしてきて、その要素の上で指を離すとtouchend
イベントが発火してしまう - 逆に言うと、
touchend
だともし間違ってタップしてしまったとしても、指をそのまま画面の外に出してしまえばキャンセルできるという利点があったりする - その辺りを厳密に処理しようと思うと、
touchstart
を検知してからtouchmove
で指を動かしたかどうかを確認し、動かしてなければtouchend
としてそれを「タップした」と判定する必要がある - その処理を自前で書くのもいいが、プラグインを使う手もある(ftlabs/fastclick)
- コードでは
- Win8対応めんどい問題
- Win8は、画面のタッチもでき、マウスでの操作もできるということを前提に設計されたOS
- Win8上で動くChromeやFirefoxにはタッチイベントが実装されているため、このパターン4のコードだとマウスで操作しても
click
イベントが使われず、何も反応しないことになる(mousedown
/mousemove
/mouseup
で設定したイベントも同様) - 一方、Win8上のIE10は、画面のタッチを内部的にマウスイベントに置き換えて処理するため、タッチでもマウスでもパターン4のコードで動作する
- Win8のIE10以降では、Microsoft独自仕様のPointer Eventsが使える
- このPointer Eventsによって、マルチタッチに対応したり、スタイラスペンのタッチに反応したり、筆圧やペンの傾きを検出できたりする
- 300msディレイ問題
- メニューボタンだけでなくコンテンツ部分のタップ/クリックでもドロワーを閉じるようにすることでより使いやすく
- 今回のHTMLでは、メニューボタンがコンテンツ
#content
の中に含まれているので、メニューボタンのイベントが#content
に伝播(バブリング)して#content
に設定したイベントが発火してしまう - これをイベントバブリングという
- これを防ぐために、メニューボタンのイベント設定で
event.stopPropagation()
しておき、イベントがバブリングしないようにする - じゃあ何でもかんでもイベントバブリングを止めておけばよいかというとそうでもなく、イベントデリゲートも止まってしまうという弊害もあるので注意が必要
- 今回のHTMLでは、メニューボタンがコンテンツ
パターン5
- jQueryを使わずに書いたもの