イベント座標 と イベントエレメント座標

イベント発生座標の取り方は、[ 初心者 ] - [ イベント ]で簡単に説明してあります。

実際にこの座標を使う場合はブラウザ画面内の座標が欲しいケースよりもドキュメント上(スクロール部分も含む)での座標が欲しい時なども多く、 その場合はちょっとコツというか注意が必要です。
また、カーソルの直接座標ではなくそのイベントが発生したエレメントの座標がが欲しい時もあります。
難しくは無いのですが、注意する事も含めて載せておきます。

カーソル座標


■基本
IE、Netscape系共通
(event).clientX、(event).clientY、(event).screenX、(event).screenY

clientX、clientY は ブラウザの現在のドキュメント表示ウィンドウの中での
左からの位置(X)、上からの位置(Y)
です。スクロールしていても、コンテンツの長さや幅とは関係なく、『表示枠(ウィンドウ)』の中での位置です。左上の角の隅が clientX =0、clientY = 0 の位置。

screenX、screenY は ビジターのモニターでの 左からの位置(X)、上からの位置(Y) です。モニターの左上の角の隅が screenX =0、screen = 0 の位置。

これらのプロパティの値は数値型(number)の数字となります。
単位は値にはありませんがpx(ピクセル)です。

他にも別用途の座標プロパティがIE、Netscape系両方にそれぞれあります。

マウスカーソルの位置を常に追いかけて行く場合などに onmousemove イベントでイベントを発生させて現在のカーソル位置を把握する方法として使ったりします。 またクリックポイントと利用したり補助説明の表示や、サブツールの表示などレイヤーをマウスカーソルの近くに表示させる時などですね。

サンプルソース:
document.onclick = function(e){
var evt = window.event || e;
alert(evt.clientX);
alert(evt.clientY);
}

さて、特殊なサービスなどスクロールをオフ、強制リサイズにしてるウィンドウならコレで良いのですが、 現実的にそのイベントの発生場所に何かを表示させたりする場合は、 ウィンドウ内のポイントだけでなくドキュメントの上からの位置、左からの位置が必要になります。 この場合は scrollTop、scrollLeftを加味して現実的なドキュメント上の座標を割り出す必要があります。 実際にスクロールを強制オフにしていたり、ウィンドウを強制リサイズさせてる場合外は、 ビジターがどのウィンドウサイズで見てるかわからないので必ずこのスクロール幅を取るようにしておきます。

■現実的な座標取得
スクロール幅 + ウィンドウ内座標 がドキュメント上の座標になります。
サンプルソース:
document.onclick = function(e){
var evt = window.event || e;
var D1 = document;
var Left= evt.clientX +(D.body.scrollLeft||D.documentElement.scrollLeft)+'px';
var Top= evt.clientY +(D.body.scrollTop||D.documentElement.scrollTop)+'px';
}
この例ではクリックが発生した時のドキュメント上のカーソル座標がLeft、Topにはいります。 何かを表示させる場合position:absoluteのエレメントの style.top、style.leftをこの値にすれば良いわけです。

さて、ココで注意しないといけないのが
document.body.scrollTop || document.documentElement.scrollTop
document.body.scrollLeft || document.documentElement.scrollLeft
つまりdocument.body と document.documentElementの
どちらか理解できる方を取るようにしておく事。
(理解できない方は0が戻るのでfalse扱い)
私がテスト(OS:WindowsXP)した結果では

DOCTYPEが
HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"
HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"
IE6IE7Netscape7Firefox2Safari3Opera9
body 00A0AA
documentElement AA0A0A
(※ A は scrollTop、scrollLeftの値を正しく返す)
この場合は、新しいブラウザなら documentElementの方だけでも良さそうですが、 Safariが駄目なのでやはり両方から取れるようにしておく必要があります。

DOCTYPEが 無い場合 (テスト用コーディングなど)
IE6IE7Netscape7Firefox2Safari3Opera9
body AAAAAA
documentElement 00000A
(※ A は scrollTop、scrollLeftの値を正しく返す)
この場合は document.body の方を使えば全てに通用します。
が、公開ページであればDOCTYPEをつけるべきですので、テスト時のみですね。

DOCTYPEがXHTMLの場合
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
IE6IE7Netscape7Firefox2Safari3Opera9
body A0A0AA
documentElement 0A0A0A
(※ A は scrollTop、scrollLeftの値を正しく返す)
やはりこの場合も両方から取れるようにしておく必要があります。

サンプル紹介や有名なJSライブラリツールなどでも、この両方から取る事を前提にしてないケースもあります。 DOCTYPEとブラウザとの関係で色々変ってくるので、常に両方を見て取るようにしておく方がトラブルが起きにくくなると思います。

サンプル

エレメント座標


サブメニューを表示したり、何らかをレイアウトにあわせてオーバーラップさせる時には カーソルの位置ではなく、そのイベントが発生したエレメントの位置(左上)を取りたい場合があります。 サブメニューもカーソルの位置でちまちま動くよりは、いつもゞ場所にすっきり出したいですしね。
こういう時にはイベント発生座標ではなく、イベント発生エレメントを特定して そのレイアウト上の位置を取り出す必要があります。(完全固定レイアウトなら不要)

例を簡単に書くと
document.onclick = function(e){ //※1
var el = window.event? event.srcElement : e.target; //※2
if(el.id == 'AAA'){ //※3
var elm = el, X=0, Y=0; //※4
while(elm){ //※5
X += elm.offsetLeft;
Y += elm.offsetTop;
elm = elm.offsetParent; //※ルートの親
}
}
と、こんな感じになります。
解説
※1 ドキュメント全体のクリックを監視
※2 イベント発生エレメントを取得
※3 そのエレメントのIDが 'AAA' なら位置取得
※4 エレメントelを別の捨て変数elmに代入。XとYの数値を0で定義。
※5 while内は、そのエレメントから親エレメントまでのオフセットを取りX、Yに加算。 次に変数elmに親エレメントを代入。 これを親が居なくなるまで、つまりBODYエレメントにぶつかるまで繰り返すと、 ウィンドウでのオフセット位置が取れます。

状況に応じてイベントや、位置を取りたいエレメントのクラス名マッチに変えたりして 自分が欲しいエレメントの位置を取ります。
これでXとYにそのエレメントのドキュメント上の座標が入ります。 座標はエレメントの左上角を指しますので、あとはエレメントのoffsetWidth、offsetHeightなどを取れば 左に合わせる、下にあわせるなど自由自在です。

ちょっとスクリプトの流れの方法論が違いますが
こちらにサンプルがあります。

こんな感じで、イベント座標を取ったりイベント発生場所のエレメントの座標を取って便利に使います。 位置が取れると言うのは動的レイアウトなどの仕掛けをする時にはとても大事です。 頑張って自分で0から書いてみてください。




専用ページから申し込むと
So-netより高い3万円CB

案ずるより産むが易し
使ってみれば疑問も解決

XREA+ (plus) 206円/月
( お試し7日間 )

CORE SERVER 428円/月
( お試し15日間 )

ロリポップ 270円/月
( お試し期間10日間 )

ヘテムル 1620円/月
( お試し期間15日間 )

さくら 129円/月
( お試し期間2週間 )

無駄な高額ドメイン管理料金払ってませんか?

バリュードメイン
ムームードメイン

2010年で第二世代携帯がサービス終了。ソフトバンクに乗り換えて安くなった人が7割以上います!