マウスの座標を取得する

 Ajaxではオブジェクトをドラッグしたりオブジェクトサイズを変更したりすることがあります。そのような場合、マウスの座標値を取得するのは重要なことです。しかし、マウス座標の取得はブラウザごとに異なっているのが実情です。以下のスクリプトはInternet Explorer以外でのマウス座標の表示を行うものです。(サンプルを実行する

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>マウス座標表示テスト(IE以外)</title>
<link rel="stylesheet" href="main.css" type="text/css" media="all">
<script type="text/javascript"><!--
window.onmousemove = getMouseXY;
function getMouseXY(evt)
{
x = evt.x;
y = evt.y;
document.getElementById("result1").innerHTML = "(x,y) = "+x + ", "+y;
x = evt.pageX;
y = evt.pageY;
document.getElementById("result2").innerHTML = "(pageX,pageY) = "+x + ", "+y;
x = evt.layerX;
y = evt.layerY;
document.getElementById("result3").innerHTML = "(layerX,layerY) = "+x + ", "+y;
x = evt.clientX;
y = evt.clientY;
document.getElementById("result4").innerHTML = "(clientX,clientY) = "+x + ", "+y;
x = evt.screenX;
y = evt.screenY;
document.getElementById("result5").innerHTML = "(screenX,screenY) = "+x + ", "+y;
x = window.pageXOffset;
y = window.pageYOffset;
document.getElementById("result6").innerHTML = "(pageXOffset,pageYOffset) = "+x + ", "+y;
}
// --></script>
</head>
<body>
<h1>マウス座標表示テスト(IE以外)</h1>
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
<div id="result4"></div>
<div id="result5"></div>
<div id="result6"></div>
<div id="testbox">test box</div>
</body>
</html>

 以下はInternet Explorerで動作するスクリプトです。(サンプルを実行する

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>マウス座標表示テスト(Firefox以外)</title>
<link rel="stylesheet" href="main.css" type="text/css" media="all">
<script type="text/javascript"><!--
window.document.onmousemove = getMouseXY;
function getMouseXY()
{
x = event.x;
y = event.y;
document.getElementById("result1").innerHTML = "(x,y) = "+x + ", "+y;
x = event.pageX;
y = event.pageY;
document.getElementById("result2").innerHTML = "(pageX,pageY) = "+x + ", "+y;
x = event.layerX;
y = event.layerY;
document.getElementById("result3").innerHTML = "(layerX,layerY) = "+x + ", "+y;
x = event.clientX;
y = event.clientY;
document.getElementById("result4").innerHTML = "(clientX,clientY) = "+x + ", "+y;
x = event.screenX;
y = event.screenY;
document.getElementById("result5").innerHTML = "(screenX,screenY) = "+x + ", "+y;
x = window.pageXOffset;
y = window.pageYOffset;
document.getElementById("result6").innerHTML = "(pageXOffset,pageYOffset) = "+x + ", "+y;
x = event.offsetX;
y = event.offsetY;
document.getElementById("result7").innerHTML = "(offsetX,offsetY) = "+x + ", "+y;
}
// --></script>
</head>
<body>
<h1>マウス座標表示テスト(Firefox以外)</h1>
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>
<div id="result4"></div>
<div id="result5"></div>
<div id="result6"></div>
<div id="result7"></div>
<div id="testbox">test box</div>
</body>
</html>

 Internet Explorerではwindow.onmousemoveのようにwindowsオブジェクトにマウスイベントを設定しても動作しません。このため、window.document.onmousemoveのようにdocumentオブジェクトなどwindowオブジェクト以外にイベントハンドラを設定する必要があります。また、イベントオブジェクトの扱いに関してもブラウザごとに異なっています。Firefox以外ではeventオブジェクトによりマウス座標を読み出す事ができます(Safari 2, Operaではeventオブジェクトをサポートしている)。Internet Explorer以外ではイベント発生時に呼び出される関数の引数として渡されます。つまりSafari 2, Operaでは、どちらの方法でもマウス座標を取得できるのに対し、Internet Explorer、Firefoxでは別々に処理する必要があります。
 Internet Explorerかどうかを判別する方法としてユーザーエージェントを調べる方法があります。しかし、OperaなどではユーザーエージェントをInternet Explorerとして設定できるため、実際には正しく判別することができません。また、if (document.all) { IEでの処理 }というようにして調べる方法もありますが、これもOperaなどでは対応しているため正しく判別できません。Operaかどうかを判別するだけであればif (window.opera) { Operaの処理 }として記述できます。しかし、Internet Explorerのみ別処理にしたいため、Internet Explorerにしかないメソッドがあるかどうかでチェックするようにします。Internet Explorerにしかないメソッドは多数ありますが、ここではInternet Explorer 5.5からサポートされているcreatePopupメソッドがあるかどうかで調べます。以下のようにするとInternet Explorerかどうか調べる事ができます。

if (window.createPopup) { IE5.5以降での処理 }

 window.addEventListenerで判別させる方法もありますが、Internet Explorer 7でどうなるか、またサポートされてもイベントオブジェクトが従来のままである可能性を考えるとこのようにしておく方が当面は良さそうです。

 次にイベントオブジェクトで用意されているマウス座標に関するプロパティは多数ありますが、ブラウザごとに対応がまちまちです。また、同じプロパティ名でも得られる結果が異なります。表にまとめると以下のようになります。


Internet ExplorerFirefoxSafariOpera
x,y×
pageX,Y×
layerX,Y××
clientX,Y
screenX,Y
pageXOffset,Y×
offsetX,offsetY×

 モニタ画面上の座標であるscreenX, screenYのみ互換性があり他は、互換性がないことになります。
 Firefox, Safari, OperaでのpageX,YはInternet Explorerのx,yにdocument.body.scrollLeft, document.body.scrollTopを加算したものになります。また、イベントが発生したオブジェクトの左上を基準としたイベント座標はFirefox, Safari, OperaではlayerX, layerYになります。これと同じものはInternet ExplorerではoffsetX, Yとなります。Operaでは動作しないのでInternet Explorerと同じoffsetX, Yになります。この場合にはInternet Explorer, Opera両方に存在するdocument.allを使ってブラウザ判別を行います。
 これらを考慮して、Internet Explorer, Firefox, Safari, Operaで動作するマウス座標を取得するスクリプトは以下のようになります。(サンプルを実行する

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>マウス座標表示テスト</title>
<link rel="stylesheet" href="main.css" type="text/css" media="all">
<script type="text/javascript"><!--
window.document.onmousemove = getMouseXY;
function getMouseXY(evt)
{
// x,yとpageX,Y
if (window.createPopup)
{
x = event.x + document.body.scrollLeft;
y = event.y + document.body.scrollTop;
}else{
x = evt.pageX;
y = evt.pageY;
}
document.getElementById("result1").innerHTML = "(x,y) = "+x + ", "+y;
// offsetX,YとlayerX,Y
if (document.all)
{
cx = event.offsetX;
cy = event.offsetY;
}else{
cx = evt.layerX;
cy = evt.layerY;
}
document.getElementById("result2").innerHTML = "(offsetX,offsetY) = "+cx + ", "+cy;
}
// --></script>
</head>
<body>
<h1>マウス座標表示テスト(共通)</h1>
<div id="result1"></div>
<div id="result2"></div>
<div id="testbox">test box</div>
</body>
</html>

 前々項で説明したドラッグ処理のサンプルでは、イベント発生時にクリック座標とオブジェクト座標の差分を取っていました。これを上記のようにオブジェクト上でのイベント発生時の座標に変更したものが以下のものになります。また、ページがスクロールした場合にInternet Explorerではドラッグ対象のオブジェクトの座標がおかしくなります。これはページのスクロール分を加算していないためです。これも上記のように加算することで正しく動作するようになります。(サンプルを実行する

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=shift_jis">
<title>ドラッグ処理(各ブラウザのイベントに対応したサンプル)</title>
<link rel="stylesheet" href="main.css" type="text/css" media="all">
<script type="text/javascript"><!--
// ドラッグ対象オブジェクト情報
dragObj = new Object();
dragObj.dragFlag = false;
dragObj.offsetX = this.offsetX = 0;
dragObj.mouseX = this.mouseY = 0;
dragObj.target = null;
dragObj.zIndex = 1; // 最初のZ-Index
dragObj.maxLayer = 3; // 最大レイヤー枚数
// イベントハンドラなどを設定
window.onload = function()
{
document.getElementById("mainContents").onmousedown = dragStart;
document.getElementById("mainContents").style.left = "60px";
document.getElementById("mainContents").style.top = "50px";
document.getElementById("mainContents").style.zIndex = 1;
document.getElementById("mainContents2").onmousedown = dragStart;
document.getElementById("mainContents2").style.left = "160px";
document.getElementById("mainContents2").style.top = "150px";
document.getElementById("mainContents2").style.zIndex = 2;
document.getElementById("mainContents3").onmousedown = dragStart;
document.getElementById("mainContents3").style.left = "260px";
document.getElementById("mainContents3").style.top = "260px";
document.getElementById("mainContents3").style.zIndex = 3;
window.document.onmousemove = dragProc;
window.document.onmouseup = dragEnd;
}
// ドラッグ開始処理
function dragStart(evt)
{
if(!window.createPopup)
{
targetElement = evt.target;
}else{
targetElement = event.srcElement;
}
if (document.all)
{
dragObj.offsetX = event.offsetX;
dragObj.offsetY = event.offsetY;
}else{
dragObj.offsetX = evt.layerX;
dragObj.offsetY = evt.layerY;
}
dragObj.dragFlag = true;
dragObj.targetObj = targetElement;
dragObj.zIndex += dragObj.maxLayer;
dragObj.targetObj.style.zIndex = dragObj.zIndex;
return false;
}
// ドラッグ終了処理
function dragEnd()
{
dragObj.dragFlag = false;
}
// ドラッグ中の処理
function dragProc(evt)
{
var mouseX,mouseY;
if (document.all)
{
mouseX = event.x + document.body.scrollLeft;
mouseY = event.y + document.body.scrollTop;
}else{
mouseX = evt.pageX;
mouseY = evt.pageY;
}
if (!dragObj.dragFlag) return;
dragObj.targetObj.style.left = mouseX - dragObj.offsetX;
dragObj.targetObj.style.top = mouseY - dragObj.offsetY;
return false;
}
// --></script>
</head>
<body>
<h1>ドラッグ処理(各ブラウザのイベントに対応したサンプル)</h1>
<div id="mainContents"><br><br>ここをドラッグできます。</div>
<div id="mainContents2"><br><br>ここをドラッグできます。</div>
<div id="mainContents3"><br><br>ここをドラッグできます。</div>
</body>
</html>

 すでに、サンプルとして出ていますが、次項ではページに任意のタグを追加する方法について説明します。

[第五章 14:ページにタグを追加するへ]
[目次へ]

(2006.1.17)