108
95

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-10-03

はじめに

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

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

javascriptで

var el = document.getElementById("boxA");
el.onmousemove = function(event){
   event.offsetX;
};

のようにしてマウスベントを登録した場合,
event.offsetX,Yは下図のようにid=boxA要素の左上を原点とした座標値になります.

offset_a1.png

要素ってどれのこと?

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

offset_a3.png

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

offset_a2.png

なぜでしょうか.

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要素座標系でのカーソル位置を求めることができます.

offset_b1.png

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要素座標系でのカーソル位置を求めることができます.

offset_b2.png

# サンプルで確かめる
code.penに上記の値の違いが確かめられるサンプルを置きました.気になる方は色々値をいじって確かめてみてください.
マウスイベントのカーソル座標取得についてはに記事をあげているので,興味のある方はそちらも御覧ください.

参考文献

What is the exact difference between currentTarget property and target property in javascript (http://stackoverflow.com/questions/10086427/what-is-the-exact-difference-between-currenttarget-property-and-target-property)

108
95
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
108
95

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?