D3.jsでは、selection.on(イベント名, イベントリスナー, オプション)
という形で任意の要素にイベントリスナーを設定できる。イベント名には、ブラウザがサポートするすべてのDOMイベントタイプが使える。
なお、selection
はDOMオブジェクトのラッパーで、単一でも複数でも同じようなインターフェースでDOMを操作できる。
addEventListenerとの違い
element.addEventListener()
とselection.on()
は、渡される引数が同じで、一見すると挙動も同じかと思える。
ただ、以下の点で微妙に異なる。
複数のリスナーの指定方法
ただ、D3.jsのselection
オブジェクトは同名のイベントに指定されたイベントリスナーを上書きする。
同名のイベントに複数のリスナーを指定するには、イベント名の末尾に.
をつけて任意の識別子を付与する必要がある。
イベントリスナーに渡される値
指定した要素で指定したイベントが発生すると、イベントリスナーにはイベントオブジェクトと現在のデータが渡される。
イベントリスナーのthis
イベントリスナーのthis
は、イベントリスナーを指定したDOM要素(event.currentTarget
)となる。
ただ、イベントリスナーをアロー関数で定義すると、そのthis
には関数が定義されたスコープが入る。例えばトップレベルではグローバルオブジェクト、あるいはundefined
が入る(strictモードの場合)。
最近はアロー関数が主流であるため、イベントの発生元を取得したい時はevent.currentTarget
を使うのが無難かと思う。
イベントリスナーの削除
イベントリスナーは、selection.on(イベント名, null)
で削除できる。
off()
とかはないので要注意である。
イベントの座標の取得
event.pageX
やevent.pageY
でも座標を取得できるが、ローカルの座標系に変換する際にはD3.jsが用意するd3.pointer(event, target)
あるいはd3.pointers(event, target)
といったメソッドを使うと便利である。
両者は、渡された引数をもとに、ターゲット要素の左上隅を基準にして変換した座標(SVG要素内での相対座標)あるいは座標の配列を返す。
If target is not specified, it defaults to the source event’s currentTarget property, if available. If the target is an SVG element, the event’s coordinates are transformed using the inverse of the screen coordinate transformation matrix.
target が指定されない場合、デフォルトではソースイベントのcurrentTargetプロパティが使われる。 もしtargetがSVG 要素の場合、イベントの座標はスクリーン座標変換行列の逆行列を用いて変換される。
"the inverse of the screen coordinate transformation matrix. "だなんて、なんとカッチョいい響きだろう(意味はわからないが)。
例えば、SVG要素にリスナーを指定すれば、pointer(event)
でイベントのSVG内での座標が取れる。また、リスナーの中でpointer(event, 任意のシェイプ要素など)
のようにすると、任意の要素の座標が取れる。これらを組み合わせれば、いい感じに図形の位置やサイズを操作できそうである。