Edited at

event.offsetX,Yの罠...どこが原点の座標値なのかを理解する (currentTargetとtarget)

More than 1 year has passed since last update.


はじめに

記事のタイトルからして今更感満載ですが,mouse eventのoffsetX,Yに関して長年勘違いをしていたので備忘録を残しておきます.


offsetX,Y は要素内でのカーソル座標.

javascriptで

var el = document.getElementById("boxA");

el.onmousemove = function(event){
event.offsetX;
};

のようにしてマウスベントを登録した場合,

event.offsetX,Yは下図のようにid=boxA要素の左上を原点とした座標値になります.


要素ってどれのこと?

では下図のようにboxAの中にboxBがある状態で,boxAに対してmouseEventを付与した場合はどうなるでしょうか.

この場合,event.offsetX,Yで取得される座標値は,そのイベントハンドラが付与されている要素(boxA)の左上を原点としたものではなく,マウスが載っている要素(boxB)の左上を原点とした座標値になります.

なぜでしょうか.


event.curerntTargetとevent.target

重要な点は,イベントを登録した要素とイベントが発火する要素は必ずしも一致しないということです.

targetは実際にイベントが発火した要素,currentTargetはイベントを登録した要素になります.

イベントは子から親へと伝播するようになっており,targetで発火したイベントがcurrentTargetにまで伝播してきています.

先の例では,イベントを登録したのはbox1に対してですが,実際はbox2で発火したために,offsetX,Yの基準がbox2左上原点になった,ということです.

上の例では,

var el = document.getElementById("container");

el.onmousemove = function(e){
console.log("currentTarget: " + e.currentTarget.id);
console.log("target: " + e.target.id);
};

等で確認してみれば,それぞれに何が入ってくるのかがわかると思います.

jQueryを使用する場合は基本的に$(this)で意図した要素を取得できるため,あまり意識する必要はありません.ただ,

最近はReact等が流行ってきてjQueryが不要な場面も増えてきているので今一度確認しておきました.


規定の要素からのカーソル座標値を求めるためには

では,カーソルがbox2に乗っていようといまいと,box1左上を原点としたカーソル座標値を求める方法を見ていきましょう.


1. getBoundingClientRect().left/topとevent.clientX/Yを使用

document.getElementById("id").getBounndingClientRect().left/top

でウィンドウ座標から見た要素の左上座標値を得ることができます.これとevent.clientX/Yを組み合わせて

var el = document.getElementById("box1");

el.onmousemove = function(e){
var target_rect = e.currentTarget.getBoundingClientRect();
var x = e.clientX - target_rect.left;
var y = e.clientY - target_rect.top;
console.log("(x, y) = (" + x + "," + y + ")");
};

でid=box1要素座標系でのカーソル位置を求めることができます.


2. jQueryのoffset()とevent.pageX/Yを使用

$("#id").offset().left/top

でページ全体から見た要素の左上座標を得ることができます.これとevent.pageX/Yを組み合わせて

$("#box1").on('mousemove',function(e){

var offset = $(this).offset();
var x = e.pageX - offset.left;
var y = e.pageY - offset.top;
console.log("(x, y) = (" + x + "," + y + ")");
});

でid=box1要素座標系でのカーソル位置を求めることができます.


 サンプルで確かめる

code.penに上記の値の違いが確かめられるサンプルを置きました.気になる方は色々値をいじって確かめてみてください.

マウスイベントのカーソル座標取得についてはに記事をあげているので,興味のある方はそちらも御覧ください.


参考文献