Upload
masayuki-nakano
View
4.771
Download
0
Embed Size (px)
Citation preview
中野雅之
•肩書き
•正式: Mozilla Japan 国際化担当マネージャ
•半公式: Mozilla Japan ジョギング部大阪支部長
•非公式: Mozilla Japan 大阪支部長
•大阪の自宅で、自宅警備しながら仕事してます
中野雅之
•色んなアカウント
•メールアドレス: [email protected]
• Skype: masayuki-nakano
• Twitter: @d_toybox
• Facebook: masayuki.nakano.560
• Blog: 「もずはっく日記」で検索
アジェンダ
•各プラットフォームのネイティブイベント
•レガシーイベント
• MouseScrollEvent
• MouseWheelEvent
• WheelEvent
• WheelEventとレガシーイベントの関係
•デフォルトアクションの考え方
各プラットフォームのネイティブイベント
• Windows
• WM_MOUESEWHEEL (Win 98以降)
• 垂直方向へのホイール操作に対するイベント
• マウスホイールの回転量が伝達される
• 1ノッチあたり120
• Vista以降では120未満のデルタ値でも発生する (高解像度スクロ
ール)
• ページ単位でのスクロールにも設定可能
• WM_MOUSEHWHEEL (Win Vista以降)
• 水平方向へのホイール操作に対するイベント
• 詳細はWM_MOUSEWHEELと同様
各プラットフォームのネイティブイベント
• Mac
• -deltaX、-deltaY、-deltaZ
• ピクセルスクロールをサポートしていないデバイスで利用
• スクロールする行数を示すと思われる(ドキュメントに明記されてい
ない)
• deltaZを利用するデバイスは無い?
• -scrollingDeltaX、-scrollingDeltaY
• ピクセルスクロールをサポートしているデバイスで利用
• 連続スクロールをサポートするデバイスか否か、という概念がある
• OSレベルで操作量・頻度に応じて、加速が行われる
• システム設定でスクロール速度はカスタマイズ可能
各プラットフォームのネイティブイベント
• Linux
• GdkEventScrollというイベントが発生し、スクロール方向のみ
が分かる
•システム設定でもスクロール量は設定できないので、アプリの
解釈によってスクロール量が決まる
MouseScrollEvent
• Firefox独自イベント
• Firefoxでは、window.MouseScrollEventは、undefined
にはならない
• DOMMouseScrollと、MozMousePixelScrollの二つのイ
ベントが存在する
•関係性や動作が非常に複雑
MouseScrollEvent
•属性
• detail
•スクロール量を表す
•正なら、下、もしくは右方向
•負なら、上、もしくは左方向
• axis
• HORIZONTAL_AXIS (1) なら水平方向
• VERTICAL_AXIS (2) なら垂直方向
MouseScrollEvent
• DOMMouseScroll
• detail値は、スクロールする行数
• detail値がSCROLL_PAGE_DOWN (32768)か、
SCROLL_PAGE_UP (-32768)なら、1ページ、スクロール
(Windowsのみ)
• MozMousePixelScroll
• detail値は、スクロールするピクセル数
MouseScrollEvent
• DOMMouseScrollとMozMousePixelScrollの関係
• MozMousePixelScrollのスクロール量がtargetの行高
で、1行分以上累積した場合にのみ、
DOMMouseScrollイベントも発生する
•両方発生する場合の発生順序は、 DOMMouseScroll
が先で、 MozMousePixelScrollが後
MouseScrollEvent
• DOMMouseScrollとMozMousePixelScrollの関係
• MozMousePixelScrollのみが発生することがあること
に注意
• DOMMouseScrollイベントだけでpreventDefault()を呼
び出してもスクロールは完全に抑制できない
• Google Mapsでも実際に、これが原因のバグがある
• Bug 681200 - Mouse wheel on google maps
zooms map and scrolls page
MouseWheelEvent
• IE発祥のイベント。Firefox以外のメジャーブラウザは実装している
•ただし、実装方法は、ブラウザ間でバラバラ
• IEでのみwindow.MouseWheelEventがundefinedではない (Chrome 27、Safari 6、Opera12.12では、サポートしているにも関わらず、undefined)
• mousewheelイベントのみが存在する
MouseWheelEvent
•属性
• wheelDelta
•ホイールの回転量を表す
•正なら、奥方向、負なら、手前方向へホイールが回転
したことを表す
• IEでは垂直方向へのホイール操作でしか発生しない
•値については後ほど解説
MouseWheelEvent
•属性
• detail値
• Opera以外では常にゼロ
• Operaではスクロールする行数を示すと思われる値
•下、もしくは右への操作なら、正の値
•上、もしくは左への操作なら、負の値
MouseWheelEvent
•属性
• wheelDeltaX
•水平方向へのホイールの回転量を表す
• Chrome、Safari、Operaでのみサポート
• IE非サポート
•値の内容はwheelDeltaと同様
•右への操作なら、負の値、左への操作なら正の値
MouseWheelEvent
•属性
• wheelDeltaY
•垂直方向へのホイールの回転量を表す
• Chrome、Safari、Operaでのみサポート
• IE非サポート
•値の内容はwheelDeltaと同様
•下への操作なら、負の値、上への操作なら正の値
MouseWheelEvent
• wheelDelta*の値の闇
• IEでは、ネイティブイベントのWM_MOUSEWHEEL、
WM_MOUSEHWHEELのデルタ値がそのまま設定されるため、
常に、ホイールの回転量を表す
•高解像度スクロールがサポートされていないデバイス
であれば、1ノッチあたり、120になる
MouseWheelEvent
• wheelDelta*の値の闇
• Windows版Chromeでは、IE同様、ネイティブイベント
のWM_MOUSEWHEEL、WM_MOUSEHWHEELのデルタ値がその
まま設定されるため、常に、ホイールの回転量を表す
•高解像度スクロールがサポートされていないデバイス
であれば、1ノッチあたり、120になる
MouseWheelEvent
• wheelDelta*の値の闇
• Mac版Chromeでは、連続スクロールがサポートされて
いないデバイスの場合、加速を考慮しない値、つまり、
純粋な操作量が利用される。手元のマウスでは1ノッチ
で120
•連続スクロールがサポートされているデバイスの場合、
加速を考慮した値を使用している。おそらく、Safariと同
じ結果になる
MouseWheelEvent
• wheelDelta*の値の闇
• Safariでは、連続スクロールがサポートされているデバ
イスでも、そうではないデバイスでも関係なく、加速を考
慮した値を使用している
•連続スクロールがサポートされていないデバイスの場
合、Mac版Chromeとは異なる値になる
MouseWheelEvent
• wheelDelta*の値の闇
• Mac版Operaでは、連続スクロールがサポートされてい
るデバイスでも、そうではないデバイスでも関係なく、加
速を考慮した値を使用している
•スクロール量(detail値)に対して、-40倍の値が用いら
れているため、多くの場合、同じ操作で、Chromeや
Safariよりも格段に大きな数字になる
MouseWheelEvent
• wheelDelta*の値の闇
• Mac版のブラウザでは、加速を考慮した場合には、
Windows版や、Linux版の同じブラウザとも互換性がな
くなる
•その理由は簡単で、デバイスの操作量を示す物理的な
デルタ値のはずが、Macでのみ、論理的なスクロール
量に応じて算出した値を用いているため
MouseWheelEvent
• wheelDelta*の値の闇
• Linux版Chromeでは、1ネイティブイベントあたり、120
がセットされるため、Windows版との互換性が高い
• Linux版Operaでは、1ネイティブイベントあたり、80が
セットされる
レガシーイベントまとめ
• Firefoxのみが独自イベントを実装しているが、理解すれ
ば一番実用的(ただし、複雑で好ましいものではない)
• IEでは横スクロールに対応できない
• Chrome、Safari、Operaでは互換性がなさ過ぎる上に、
Chromeの動作に関しては、ブラウザの名前から処理を
切り分けることも不可能にしている
•要するに、Firefox以外では使い物にならない
WheelEvent
• W3CのDOM Level 3 Eventsで標準化されている
• IE 9発祥のイベントで、Firefoxも、17以降でサポート
• Safari、Chromeはオブジェクトのみサポートしているため、window.WheelEventは、IE、Firefox、Safari、Chromeでundefinedとならない
• wheelイベントのみが存在し、斜め方向のスクロールもひとつのイベントで表現できるようになっている
WheelEvent
•属性
• deltaX、deltaY
• X軸、Y軸方向へのスクロール量をdouble値で示す
•正なら、右、もしくは下方向
•負なら、左、もしくは上方向
• Firefoxでは、Macで加速が行われている場合、その値
が反映される
WheelEvent
•属性
• deltaZ
• Z軸方向へのスクロール量をdouble値で示す
• Macのネイティブイベントに存在する概念なので存在
すると思われる
• FirefoxではMac版でも常にゼロとなる(正負をどうす
れば良いのか判断できないため)
•他のOSではそもそもこの概念はない
WheelEvent
•属性
• deltaMode
• deltaX、deltaY、deltaZの値の単位を表す
• DOM_DELTA_PIXEL (0)の場合、ピクセル数
• DOM_DELTA_LINE (1)の場合、行数
• DOM_DELTA_PAGE (2)の場合、ページ数
• delta*がdouble値のため、0.5行のスクロールや、0.5
ページのスクロール、といった表現が可能
WheelEvent
• IE9
• deltaX、deltaY、deltaZはdouble値ではなく、整数値
• IE9、IE10
• deltaMode値はDOM_DELTA_PIXEL
•行単位のスクロールの場合、1行、もしくは1文字あたり、
固定値を乗算した値(参考: Y方向時: 32px (IE10)、
41px (IE9)、おそらく環境・設定依存)
•ページ単位のスクロールの場合、そのページの高さ(≠
実際にスクロールされる要素の高さ)
WheelEvent
• Firefox
• Windows版では、deltaMode値は、DOM_DELTA_LINEか、
DOM_DELTA_PAGE (システム設定依存)
• Linux版では、deltaMode値は常に、DOM_DELTA_LINE
• Mac版では、deltaMode値は、DOM_DELTA_LINEか、
DOM_DELTA_PIXEL (操作したデバイスがピクセル単
位のスクロールをサポートしているか否かに依存)
•各delta値は設定で変更できるため、ゲームの入力のよ
うな用途では利用できない
WheelEventとレガシーイベントの関係
• IE、Firefox共通
• "wheel"イベントが発生した後に、レガシーイベントが発
生する
• "wheel"イベント、レガシーイベントのどちらの
preventDefault()でも、デフォルトアクションをキャン
セルできる
• "wheel"イベントで、preventDefault()を呼び出すと、
レガシーイベントは発生しない
WheelEventとレガシーイベントの関係
• Firefox
• "wheel"イベントの情報と、イベントのターゲットの行高
や、targetに一番近い、スクロール可能な要素の幅・高
さから、レガシーイベントが生成される
WheelEventとレガシーイベントの関係
•まとめると、WheelEventをサポートしているブラウザであ
れば、"wheel"イベントのみを処理し、それ以外のブラウ
ザでは、"mousewheel"イベントを処理すれば良い
•しかし、Chrome、Safariでは、window.WheelEventが
undefinedを返さないので正しい判定が不可能になって
いる
WheelEventとレガシーイベントの関係
•イベント処理後に必ず、preventDefault()を呼び出す
のであれば、全てのイベントにリスナを設置することで解
決する
•例:
foo.addEventListener("wheel", wheelHandler, false);
foo.addEventListener("mousewheel"
mousewheelHandler, false);
WheelEventとレガシーイベントの関係
•イベント処理後に、preventDefault()を呼び出さないの
であれば、悩ましい。
• "onwheel" in document.bodyはFirefoxではtrueにな
るが、IEではfalse
• window.MouseWheelEventはIE 8以前、Safari、Chrome、
Operaはundefinedを返すので、IE 9以降かどうかの判
定に使えるものの、Safari、Chromeが実装を改善すると、
破綻するので危険
デフォルトアクションの考え方
• preventDefault()を呼び出さない場合に、ブラウザによ
って実行されるのがデフォルトアクション
•モディファイアキー無しであれば、スクロールが一般的
• Windowsであれば、Ctrlキーを押している場合、スクロー
ルではなく、ズームになるのが一般的
•つまり、"wheel"イベントや、レガシーホイールイベント
は、スクロールが発生することを予告するイベントでは
ない
デフォルトアクションの考え方
• Firefoxでは、マウスホイールの操作にトランザク
ションの概念があるため、targetに一番近い、スク
ロール可能な祖先要素がスクロールされるとは限ら
ない(Mouse wheel transaction)
•ページ全体にスクロール中に、他のスクロール可能な
要素がマウスカーソルの下に移動してきても、ページ
全体をスクロール対象として考える(タイムアウトあり)
• DOMイベントのtargetは、これに関係なく、常に、カー
ソルの下にある要素になる
デフォルトアクションの考え方
•これらのことから言えるのは、"wheel"イベントやレガシ
ーイベントを利用して、独自のスクロール可能な要素を
作る場合には細心の注意が必要
•本当に必要なことか?
•アクセシビリティへの配慮は十分か?
•全てのプラットフォームの全てのブラウザの、全ての
現役のバージョンでテストする覚悟(予算)はあるか?
•万が一、問題が報告された場合に対応する覚悟(余
裕)はあるか?
まとめ
•できれば、面倒極まりないので、関わらない
•やるなら、WheelEventをメインに、がんばる
•WebKitとBlink陣営に、WheelEventを実装する
ようにみんなで声をあげよう!