Submit Search
Upload
マウスホイールイベント処理マニアックス
•
12 likes
•
8,121 views
Masayuki Nakano
Follow
標準化されたWheelEventや、様々なブラウザで利用されてきたレガシーイベントの紹介です。
Read less
Read more
Technology
Report
Share
Report
Share
1 of 49
Download now
Download to read offline
Recommended
インタフェース完全に理解した
インタフェース完全に理解した
torisoup
C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版
信之 岩永
コールバックと戦う話
コールバックと戦う話
torisoup
Unityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャ
torisoup
強いて言えば「集約どう実装するのかな、を考える」な話
強いて言えば「集約どう実装するのかな、を考える」な話
Yoshitaka Kawashima
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
Mikiya Okuno
「伝わるチケット」の書き方
「伝わるチケット」の書き方
onozaty
UniRx完全に理解した
UniRx完全に理解した
torisoup
Recommended
インタフェース完全に理解した
インタフェース完全に理解した
torisoup
C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版
信之 岩永
コールバックと戦う話
コールバックと戦う話
torisoup
Unityでオニオンアーキテクチャ
Unityでオニオンアーキテクチャ
torisoup
強いて言えば「集約どう実装するのかな、を考える」な話
強いて言えば「集約どう実装するのかな、を考える」な話
Yoshitaka Kawashima
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
Mikiya Okuno
「伝わるチケット」の書き方
「伝わるチケット」の書き方
onozaty
UniRx完全に理解した
UniRx完全に理解した
torisoup
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理
KageShiron
C# 8.0 null許容参照型
C# 8.0 null許容参照型
信之 岩永
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
増田 亨
C++でできる!OS自作入門
C++でできる!OS自作入門
uchan_nos
できる!並列・並行プログラミング
できる!並列・並行プログラミング
Preferred Networks
ドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解する
増田 亨
人生で大事なことは XP白本と参考文献に教わった in ESM
人生で大事なことは XP白本と参考文献に教わった in ESM
Takeshi Kakeda
Unity開発で使える設計の話+Zenjectの紹介
Unity開発で使える設計の話+Zenjectの紹介
torisoup
UniRxでMV(R)Pパターンをやってみた
UniRxでMV(R)Pパターンをやってみた
torisoup
目grep入門 +解説
目grep入門 +解説
murachue
WebGL Performance Tuning Tips
WebGL Performance Tuning Tips
Yukio Andoh
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
mosa siru
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
増田 亨
デキるプログラマだけが知っているコードレビュー7つの秘訣
デキるプログラマだけが知っているコードレビュー7つの秘訣
Masahiro Nishimi
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
Takuya Akiba
.NETで動くチケット管理ツール「プリザンター」
.NETで動くチケット管理ツール「プリザンター」
Taiji Uchida
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
Yoshitaka Kawashima
UniTask入門
UniTask入門
torisoup
型安全性入門
型安全性入門
Akinori Abe
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方
増田 亨
More Related Content
What's hot
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理
KageShiron
C# 8.0 null許容参照型
C# 8.0 null許容参照型
信之 岩永
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
増田 亨
C++でできる!OS自作入門
C++でできる!OS自作入門
uchan_nos
できる!並列・並行プログラミング
できる!並列・並行プログラミング
Preferred Networks
ドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解する
増田 亨
人生で大事なことは XP白本と参考文献に教わった in ESM
人生で大事なことは XP白本と参考文献に教わった in ESM
Takeshi Kakeda
Unity開発で使える設計の話+Zenjectの紹介
Unity開発で使える設計の話+Zenjectの紹介
torisoup
UniRxでMV(R)Pパターンをやってみた
UniRxでMV(R)Pパターンをやってみた
torisoup
目grep入門 +解説
目grep入門 +解説
murachue
WebGL Performance Tuning Tips
WebGL Performance Tuning Tips
Yukio Andoh
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
mosa siru
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
増田 亨
デキるプログラマだけが知っているコードレビュー7つの秘訣
デキるプログラマだけが知っているコードレビュー7つの秘訣
Masahiro Nishimi
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
Takuya Akiba
.NETで動くチケット管理ツール「プリザンター」
.NETで動くチケット管理ツール「プリザンター」
Taiji Uchida
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
Yoshitaka Kawashima
UniTask入門
UniTask入門
torisoup
型安全性入門
型安全性入門
Akinori Abe
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方
増田 亨
What's hot
(20)
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理
C# 8.0 null許容参照型
C# 8.0 null許容参照型
ドメイン駆動設計 ( DDD ) をやってみよう
ドメイン駆動設計 ( DDD ) をやってみよう
C++でできる!OS自作入門
C++でできる!OS自作入門
できる!並列・並行プログラミング
できる!並列・並行プログラミング
ドメイン駆動設計 基本を理解する
ドメイン駆動設計 基本を理解する
人生で大事なことは XP白本と参考文献に教わった in ESM
人生で大事なことは XP白本と参考文献に教わった in ESM
Unity開発で使える設計の話+Zenjectの紹介
Unity開発で使える設計の話+Zenjectの紹介
UniRxでMV(R)Pパターンをやってみた
UniRxでMV(R)Pパターンをやってみた
目grep入門 +解説
目grep入門 +解説
WebGL Performance Tuning Tips
WebGL Performance Tuning Tips
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
デキるプログラマだけが知っているコードレビュー7つの秘訣
デキるプログラマだけが知っているコードレビュー7つの秘訣
プログラミングコンテストでのデータ構造
プログラミングコンテストでのデータ構造
.NETで動くチケット管理ツール「プリザンター」
.NETで動くチケット管理ツール「プリザンター」
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
UniTask入門
UniTask入門
型安全性入門
型安全性入門
ドメインオブジェクトの見つけ方・作り方・育て方
ドメインオブジェクトの見つけ方・作り方・育て方
マウスホイールイベント処理マニアックス
1.
2.
Text マウスホイールイベント処理 マニアックス
3.
中野雅之 • 肩書き • 正式:
Mozilla Japan 国際化担当マネージャ • 半公式: Mozilla Japan ジョギング部大阪支部長 • 非公式: Mozilla Japan 大阪支部長 • 大阪の自宅で、自宅警備しながら仕事してます
4.
中野雅之 • 色んなアカウント • メールアドレス:
masayuki@d-toybox.com • Skype: masayuki-nakano • Twitter: @d_toybox • Facebook: masayuki.nakano.560 • Blog: 「もずはっく日記」で検索
5.
アジェンダ • 各プラットフォームのネイティブイベント • レガシーイベント •
MouseScrollEvent • MouseWheelEvent • WheelEvent • WheelEventとレガシーイベントの関係 • デフォルトアクションの考え方
6.
各プラットフォームの ネイティブイベント
7.
各プラットフォームのネイティブイベント • Windows • WM_MOUESEWHEEL
(Win 98以降) • 垂直方向へのホイール操作に対するイベント • マウスホイールの回転量が伝達される • 1ノッチあたり120 • Vista以降では120未満のデルタ値でも発生する (高解像度スクロ ール) • ページ単位でのスクロールにも設定可能 • WM_MOUSEHWHEEL (Win Vista以降) • 水平方向へのホイール操作に対するイベント • 詳細はWM_MOUSEWHEELと同様
8.
各プラットフォームのネイティブイベント • Mac • -deltaX、-deltaY、-deltaZ •
ピクセルスクロールをサポートしていないデバイスで利用 • スクロールする行数を示すと思われる(ドキュメントに明記されてい ない) • deltaZを利用するデバイスは無い? • -scrollingDeltaX、-scrollingDeltaY • ピクセルスクロールをサポートしているデバイスで利用 • 連続スクロールをサポートするデバイスか否か、という概念がある • OSレベルで操作量・頻度に応じて、加速が行われる • システム設定でスクロール速度はカスタマイズ可能
9.
各プラットフォームのネイティブイベント • Linux • GdkEventScrollというイベントが発生し、スクロール方向のみ が分かる •
システム設定でもスクロール量は設定できないので、アプリの 解釈によってスクロール量が決まる
10.
MouseScrollEvent
11.
MouseScrollEvent • Firefox独自イベント • Firefoxでは、window.MouseScrollEventは、undefined にはならない •
DOMMouseScrollと、MozMousePixelScrollの二つのイ ベントが存在する • 関係性や動作が非常に複雑
12.
MouseScrollEvent • 属性 • detail •
スクロール量を表す • 正なら、下、もしくは右方向 • 負なら、上、もしくは左方向 • axis • HORIZONTAL_AXIS (1) なら水平方向 • VERTICAL_AXIS (2) なら垂直方向
13.
MouseScrollEvent • DOMMouseScroll • detail値は、スクロールする行数 •
detail値がSCROLL_PAGE_DOWN (32768)か、 SCROLL_PAGE_UP (-32768)なら、1ページ、スクロール (Windowsのみ) • MozMousePixelScroll • detail値は、スクロールするピクセル数
14.
MouseScrollEvent • DOMMouseScrollとMozMousePixelScrollの関係 • MozMousePixelScrollのスクロール量がtargetの行高 で、1行分以上累積した場合にのみ、 DOMMouseScrollイベントも発生する •
両方発生する場合の発生順序は、 DOMMouseScroll が先で、 MozMousePixelScrollが後
15.
MouseScrollEvent • DOMMouseScrollとMozMousePixelScrollの関係 • MozMousePixelScrollのみが発生することがあること に注意 •
DOMMouseScrollイベントだけでpreventDefault()を呼 び出してもスクロールは完全に抑制できない • Google Mapsでも実際に、これが原因のバグがある • Bug 681200 - Mouse wheel on google maps zooms map and scrolls page
16.
MouseWheelEvent
17.
MouseWheelEvent • IE発祥のイベント。Firefox以外のメジャーブラウザは実 装している • ただし、実装方法は、ブラウザ間でバラバラ •
IEでのみwindow.MouseWheelEventがundefinedではな い (Chrome 27、Safari 6、Opera12.12では、サポートし ているにも関わらず、undefined) • mousewheelイベントのみが存在する
18.
MouseWheelEvent • 属性 • wheelDelta •
ホイールの回転量を表す • 正なら、奥方向、負なら、手前方向へホイールが回転 したことを表す • IEでは垂直方向へのホイール操作でしか発生しない • 値については後ほど解説
19.
MouseWheelEvent • 属性 • detail値 •
Opera以外では常にゼロ • Operaではスクロールする行数を示すと思われる値 • 下、もしくは右への操作なら、正の値 • 上、もしくは左への操作なら、負の値
20.
MouseWheelEvent • 属性 • wheelDeltaX •
水平方向へのホイールの回転量を表す • Chrome、Safari、Operaでのみサポート • IE非サポート • 値の内容はwheelDeltaと同様 • 右への操作なら、負の値、左への操作なら正の値
21.
MouseWheelEvent • 属性 • wheelDeltaY •
垂直方向へのホイールの回転量を表す • Chrome、Safari、Operaでのみサポート • IE非サポート • 値の内容はwheelDeltaと同様 • 下への操作なら、負の値、上への操作なら正の値
22.
MouseWheelEvent • wheelDelta*の値の闇 • IEでは、ネイティブイベントのWM_MOUSEWHEEL、 WM_MOUSEHWHEELのデルタ値がそのまま設定されるため、 常に、ホイールの回転量を表す •
高解像度スクロールがサポートされていないデバイス であれば、1ノッチあたり、120になる
23.
MouseWheelEvent • wheelDelta*の値の闇 • Windows版Chromeでは、IE同様、ネイティブイベント のWM_MOUSEWHEEL、WM_MOUSEHWHEELのデルタ値がその まま設定されるため、常に、ホイールの回転量を表す •
高解像度スクロールがサポートされていないデバイス であれば、1ノッチあたり、120になる
24.
MouseWheelEvent • wheelDelta*の値の闇 • Mac版Chromeでは、連続スクロールがサポートされて いないデバイスの場合、加速を考慮しない値、つまり、 純粋な操作量が利用される。手元のマウスでは1ノッチ で120 •
連続スクロールがサポートされているデバイスの場合、 加速を考慮した値を使用している。おそらく、Safariと同 じ結果になる
25.
MouseWheelEvent • wheelDelta*の値の闇 • Safariでは、連続スクロールがサポートされているデバ イスでも、そうではないデバイスでも関係なく、加速を考 慮した値を使用している •
連続スクロールがサポートされていないデバイスの場 合、Mac版Chromeとは異なる値になる
26.
MouseWheelEvent • wheelDelta*の値の闇 • Mac版Operaでは、連続スクロールがサポートされてい るデバイスでも、そうではないデバイスでも関係なく、加 速を考慮した値を使用している •
スクロール量(detail値)に対して、-40倍の値が用いら れているため、多くの場合、同じ操作で、Chromeや Safariよりも格段に大きな数字になる
27.
MouseWheelEvent • wheelDelta*の値の闇 • Mac版のブラウザでは、加速を考慮した場合には、 Windows版や、Linux版の同じブラウザとも互換性がな くなる •
その理由は簡単で、デバイスの操作量を示す物理的な デルタ値のはずが、Macでのみ、論理的なスクロール 量に応じて算出した値を用いているため
28.
MouseWheelEvent • wheelDelta*の値の闇 • Linux版Chromeでは、1ネイティブイベントあたり、120 がセットされるため、Windows版との互換性が高い •
Linux版Operaでは、1ネイティブイベントあたり、80が セットされる
29.
レガシーイベントまとめ • Firefoxのみが独自イベントを実装しているが、理解すれ ば一番実用的(ただし、複雑で好ましいものではない) • IEでは横スクロールに対応できない •
Chrome、Safari、Operaでは互換性がなさ過ぎる上に、 Chromeの動作に関しては、ブラウザの名前から処理を 切り分けることも不可能にしている • 要するに、Firefox以外では使い物にならない
30.
WheelEvent
31.
WheelEvent • W3CのDOM Level
3 Eventsで標準化されている • IE 9発祥のイベントで、Firefoxも、17以降でサポート • Safari、Chromeはオブジェクトのみサポートしているた め、window.WheelEventは、IE、Firefox、Safari、 Chromeでundefinedとならない • wheelイベントのみが存在し、斜め方向のスクロールも ひとつのイベントで表現できるようになっている
32.
WheelEvent • 属性 • deltaX、deltaY •
X軸、Y軸方向へのスクロール量をdouble値で示す • 正なら、右、もしくは下方向 • 負なら、左、もしくは上方向 • Firefoxでは、Macで加速が行われている場合、その値 が反映される
33.
WheelEvent • 属性 • deltaZ •
Z軸方向へのスクロール量をdouble値で示す • Macのネイティブイベントに存在する概念なので存在 すると思われる • FirefoxではMac版でも常にゼロとなる(正負をどうす れば良いのか判断できないため) • 他のOSではそもそもこの概念はない
34.
WheelEvent • 属性 • deltaMode •
deltaX、deltaY、deltaZの値の単位を表す • DOM_DELTA_PIXEL (0)の場合、ピクセル数 • DOM_DELTA_LINE (1)の場合、行数 • DOM_DELTA_PAGE (2)の場合、ページ数 • delta*がdouble値のため、0.5行のスクロールや、0.5 ページのスクロール、といった表現が可能
35.
WheelEvent • IE9 • deltaX、deltaY、deltaZはdouble値ではなく、整数値 •
IE9、IE10 • deltaMode値はDOM_DELTA_PIXEL • 行単位のスクロールの場合、1行、もしくは1文字あたり、 固定値を乗算した値(参考: Y方向時: 32px (IE10)、 41px (IE9)、おそらく環境・設定依存) • ページ単位のスクロールの場合、そのページの高さ(≠ 実際にスクロールされる要素の高さ)
36.
WheelEvent • Firefox • Windows版では、deltaMode値は、DOM_DELTA_LINEか、 DOM_DELTA_PAGE
(システム設定依存) • Linux版では、deltaMode値は常に、DOM_DELTA_LINE • Mac版では、deltaMode値は、DOM_DELTA_LINEか、 DOM_DELTA_PIXEL (操作したデバイスがピクセル単 位のスクロールをサポートしているか否かに依存) • 各delta値は設定で変更できるため、ゲームの入力のよ うな用途では利用できない
37.
WheelEventと レガシーイベントの関係
38.
WheelEventとレガシーイベントの関係 • IE、Firefox共通 • "wheel"イベントが発生した後に、レガシーイベントが発 生する •
"wheel"イベント、レガシーイベントのどちらの preventDefault()でも、デフォルトアクションをキャン セルできる • "wheel"イベントで、preventDefault()を呼び出すと、 レガシーイベントは発生しない
39.
WheelEventとレガシーイベントの関係 • Firefox • "wheel"イベントの情報と、イベントのターゲットの行高 や、targetに一番近い、スクロール可能な要素の幅・高 さから、レガシーイベントが生成される
40.
WheelEventとレガシーイベントの関係 • まとめると、WheelEventをサポートしているブラウザであ れば、"wheel"イベントのみを処理し、それ以外のブラウ ザでは、"mousewheel"イベントを処理すれば良い • しかし、Chrome、Safariでは、window.WheelEventが undefinedを返さないので正しい判定が不可能になって いる
41.
WheelEventとレガシーイベントの関係 • イベント処理後に必ず、preventDefault()を呼び出す のであれば、全てのイベントにリスナを設置することで解 決する • 例: foo.addEventListener("wheel",
wheelHandler, false); foo.addEventListener("mousewheel" mousewheelHandler, false);
42.
WheelEventとレガシーイベントの関係 • イベント処理後に、preventDefault()を呼び出さないの であれば、悩ましい。 • "onwheel"
in document.bodyはFirefoxではtrueにな るが、IEではfalse • window.MouseWheelEventはIE 8以前、Safari、Chrome、 Operaはundefinedを返すので、IE 9以降かどうかの判 定に使えるものの、Safari、Chromeが実装を改善すると、 破綻するので危険
43.
デフォルトアクションの考え方
44.
デフォルトアクションの考え方 • preventDefault()を呼び出さない場合に、ブラウザによ って実行されるのがデフォルトアクション • モディファイアキー無しであれば、スクロールが一般的 •
Windowsであれば、Ctrlキーを押している場合、スクロー ルではなく、ズームになるのが一般的 • つまり、"wheel"イベントや、レガシーホイールイベント は、スクロールが発生することを予告するイベントでは ない
45.
デフォルトアクションの考え方 • Firefoxでは、マウスホイールの操作にトランザク ションの概念があるため、targetに一番近い、スク ロール可能な祖先要素がスクロールされるとは限ら ない(Mouse wheel
transaction) • ページ全体にスクロール中に、他のスクロール可能な 要素がマウスカーソルの下に移動してきても、ページ 全体をスクロール対象として考える(タイムアウトあり) • DOMイベントのtargetは、これに関係なく、常に、カー ソルの下にある要素になる
46.
デフォルトアクションの考え方 • つまり、デフォルトアクションがスクロールの場合であっ ても、"wheel"イベントは、実際のデフォルトアクション の内容と一致するとは限らない
47.
デフォルトアクションの考え方 • これらのことから言えるのは、"wheel"イベントやレガシ ーイベントを利用して、独自のスクロール可能な要素を 作る場合には細心の注意が必要 • 本当に必要なことか? •
アクセシビリティへの配慮は十分か? • 全てのプラットフォームの全てのブラウザの、全ての 現役のバージョンでテストする覚悟(予算)はあるか? • 万が一、問題が報告された場合に対応する覚悟(余 裕)はあるか?
48.
まとめ •できれば、面倒極まりないので、関わらない •やるなら、WheelEventをメインに、がんばる •WebKitとBlink陣営に、WheelEventを実装する ようにみんなで声をあげよう!
49.
Text Q&A?
Download now