Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
82
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

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

はじめに

記事のタイトルからして今更感満載ですが,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に上記の値の違いが確かめられるサンプルを置きました.気になる方は色々値をいじって確かめてみてください.
マウスイベントのカーソル座標取得についてはに記事をあげているので,興味のある方はそちらも御覧ください.

参考文献

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
82
Help us understand the problem. What are the problem?