Hatena::ブログ(Diary)

三等兵

2009-11-05

座標取得するプロパティのそれぞれの違い

JSにおけるマウスなど座標を取得するプロパティというのはいくつかありまして、はっきりいって訳が分かりません。腹が立ちます。単なる八つ当たりであることをここに宣言しつつ、それを確かめるべく、斥候任務をこなすでありますキャプテン!

座標を取得するプロパティ

4種類のプロパティがあるとみてよいでしょう。IEは外して。

https://developer.mozilla.org/ja/DOM/event

  • event.clientX
  • event.clientY

イベントの水平・垂直座標を返す。

  • event.layerX
  • event.layerY

現在のレイヤー上における相対的な水平・垂直座標を返す。

  • event.pageX
  • event.pageY

イベントのページ上における相対的な水平・垂直座標を返す。

  • event.screenX
  • event.screenY

イベントのスクリーン上における水平・垂直位置を返す。


意味わからん。説明する気あるのか。


確かめましょう

というわけで確かめ。短絡的なアナログ手法でさっさと確かめる。ドキュメント上、エレメント上を比較しつつ、その他必要なら取り入れる。

なんか長くなったのでまとめだけみる方がいいかも。たいした情報ない。


event.clientX/Yプロパティ

イベントの水平・垂直座標を返すとのこと。

このへんてこなスクリプトはマウスを動かすと座標をリアルタイムで取得するようになってます。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  var box = document.getElementById('box');
  document.onmousemove = function(e) {
    x = e.clientX;
    y = e.clientY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

<p id="zx"></p>
<p id="zy"></p>
<div id="box" style="position:absolute;top:100px;left:200px; 
width:200px;height:200px;background-color:red;"></div>

</body>
</html>

id="box"関連は今のところ無視で。

clientX/Yプロパティはイベント上の座標を返します。今回はdocument.onmousemoveということで、ドキュメント上をイベントの範囲として指定しています。その範囲内でマウスを動かすと、ブラウザの描写部分左上を基点に座標を取得することができます。


では、例えばclientX/Yプロパティでイベントの範囲をid="box"にしてみたらどうなるでしょう。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  var box = document.getElementById('box');
    //documentからboxに変更
    box.onmousemove = function(e) {
    x = e.clientX;
    y = e.clientY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

<p id="zx"></p>
<p id="zy"></p>
<div id="box" style="position:absolute;top:100px;left:200px; 
width:200px;height:200px;background-color:red;"></div>

</body>
</html>

イベントの範囲をdocumentからid="box"上だけにしました。ということは基点はboxの一番左上、つまりposition:absolute;top:100px; left:200px;の部分で、

X座標: 0

Y座標: 0

と表示されるのかなと思ったら実際は、

X座標: 200

Y座標: 100

と表示されたではありませんか!



よく考えれば当然だったのですが…。つまりclientX/Yプロパティというのは、ブラウザ描写部分の左上を基点にして、イベント範囲内の座標を取得していることになるようです。

ブラウザ描写部分、というのは、えーつまりブックマークやツールバーでなく、ウェブページを閲覧する部分。

ちなみにこれはページ全体での座標ではありません。わかりにくいのですが、ページをスクロールしても描写部分左上が基点だ、ということになるみたい。上記のソースをbrタグでスクロールできるようにしてみれば分かりやすいでしょう。


layerX/Yプロパティ

現在のレイヤー上における相対的な水平・垂直座標を返すとのこと。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  var box = document.getElementById('box');
  document.onmousemove = function(e) {
    //layerX/Yプロパティ
    x = e.layerX;
    y = e.layerY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

<p id="zx"></p>
<p id="zy"></p>
<div id="box" style="position:absolute;top:100px;left:200px; width:200px;height:200px;background-color:red;"></div>

</body>
</html>

これは試してみたほうが早いと思うんですが。

この場合、イベント範囲はドキュメント上になっていますので、ブラウザ描写部分の左上が基点となっています。適当に移動させても、そこが基点になってることが分かります。

ではid="box"の左上に、つまり、position:absolute;top:100px; left:200px;の部分にカーソルを置くと、

X座標: 0

Y座標: 0

と表示されるではありませんか!



基点がボックスの左上へと変わりました。おそらくエレメントごとに基点が変わる、ということなんでしょうが、もう少し具体的に確かめてみましょう。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  var box = document.getElementById('box');
  document.onmousemove = function(e) {
    x = e.layerX;
    y = e.layerY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

<p id="zx"></p>
<p id="zy"></p>
<div id="box" style="position:absolute;top:100px;left:200px; width:200px;height:200px;background-color:red;"></div>

//positionプロパティ無し
<div id="box1" style="width:200px;height:200px;background-color:green;"></div>

//img画像。大きさ指定のみ
<img id="img" src="img.png"width="200" height="200"/>

</body>
</html>

追加したのは、positionを指定していないボックスと、直接大きさを指定しているイメージ画像です。結果として、2つとも基点は変わりませんでした。ブラウザ描写部分の左上が基点となっています。

つまるところ、position指定していると基点が変わるようです。それからインライン要素のタグでも試してみましたが、position指定すれば一緒です。

今度はdocumentをid="box"へ変えてみます。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  //id="box"のエレメントを取得
  var box = document.getElementById('box');
  //documentからboxに範囲変更
  box.onmousemove = function(e) {
    x = e.layerX;
    y = e.layerY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

<p id="zx"></p>
<p id="zy"></p>

<div id="box" style="position:absolute;top:100px;left:200px; width:200px;height:200px;background-color:red;"></div>

</body>
</html>

結果、ボックス上の左上を基点に、その大きさ分だけ座標が表示され、ボックス外では特に何も表示されませんでした。当然ですね。イベントの影響の範囲がボックス指定になっているのでこうなります。


layerX/Yプロパティはpositionプロパティを指定したエレメントの左上が基点になるようです。ただ、値がstaticだと基点は変わりませんのでご注意。

それからページ左上が基点ということのようで、たとえばスクロールしても座標はページ左上を基点に取得します。これがclientX/Yプロパティだと、スクロールすると常に基点がブラウザ描写部分の左上になっており、ここに違いがあるようですね。


event.pageX/Yプロパティ

イベントのページ上における相対的な水平・垂直座標を返すとのこと。

これはなんとなくわかるような気がしますがとりあえずやってみます。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  var box = document.getElementById('box');
  document.onmousemove = function(e) {
    //pageX/Yプロパティ
    x = e.pageX;
    y = e.pageY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

<p id="zx" style="position:fixed"></p>
<p id="zy" style="position:fixed"></p>
<div id="box" style="position:absolute;top:100px;left:200px; width:200px;height:200px;background-color:red;"></div>
<br>
</body>
</html>

普通に座標を取得しているように見えます。clientX/Yプロパティと変わりが無いように思いました。またボックスにマウスを移動しても基点は変わりません。

今度はスクロールできるようにして確かめてみます。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  var box = document.getElementById('box');
  document.onmousemove = function(e) {
    x = e.pageX;
    y = e.pageY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

//スクロールしても分かるようにfixedに
<p id="zx" style="position:fixed"></p>
<p id="zy" style="position:fixed"></p>
//height:800pxに
<div id="box" style="position:absolute;top:100px;left:200px;
width:200px;height:800px;background-color:red;"></div>
</html>

スクロールしても基点が変わらず、ページ下まで座標を取得することができました。

ちなみにイベント範囲をdocumentからboxに変えてみましたが、基点はページ左上で変わりありません。


event.screenX/Yプロパティ

イベントのスクリーン上における水平・垂直位置を返すとのこと。


これももうなんとなく予想がつきますが。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<script type="text/javascript">

onload = function() {
  var x;
  var y;
  var box = document.getElementById('box');
  document.onmousemove = function(e) {
    x = e.screenX;
    y = e.screenY;
    document.getElementById('zx').innerHTML = "X座標:" + x;
    document.getElementById('zy').innerHTML = "Y座標:" + y;
  }
}

</script>
<title>座標テスト</title>
</head>
<body>

<p id="zx" style="position:fixed"></p>
<p id="zy" style="position:fixed"></p>
<div id="box" style="position:absolute;top:100px;left:200px;width:200px;height:800px;background-color:red;"></div>
</html>

ブラウザの描写部分関係なく、スクリーン全体の座標を取得することができます。つまりパソコンの画面そのものの左上が基点ということですね。ブラウザの大きさは関係ないので、たとえばブラウザのウィンドウを小さくしてみたらよくわかります。


まとめ

長いことやりましたが。

4種類の座標を取得するプロパティがありましたが(firefoxのみで)、それらを分けてみると絶対の座標と相対の座標プロパティがあるようです。


絶対の座標

基点が画面上から動かない。

  • clientX/Yプロパティ

ブラウザの描写部分左上が基点となる。専門用語ではクライアントウィンドウって部分の座標。イベントの範囲をエレメントにしても基点は変わらない。


  • screenX/Yプロパティ

スクリーン全体(パソコンの画面全体)で、左上が基点。エレメント上でも基点は変わらないし、ウィンドウを小さくしても関係ない。


相対の座標

基点がページ左上でスクロールしても変わらない。


  • layerX/Yプロパティ

ウェブページの左上が基点。座標上にpositionプロパティを指定されたボックスなどがあれば、基点はボックスの左上になる。ただしstaticのみ基点はページ左上のまま。


  • pageX/Yプロパティ

ウェブページの左上が基点で、positionプロパティを指定されたエレメントがあったとしても関係ない。



ということで。ここにIEがまざってくると結局面倒なことになりかねないわけですが、個人的に使いやすそうなのはpageX/Yプロパティだと思いました。逆にウェブページ上でscreenX/Yプロパティはおそらく使いそうにないでしょうね。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/sandai/20091105/p1