<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script language="javascript">
function main(){
var canvas = document.getElementById("canvas");
canvas.addEventListener("mousemove", function(e){
if (!e) e = window.event;
var ctx = canvas.getContext("2d");
var x = e.offsetX;
var y = e.offsetY;
ctx.fillRect(x, y, 1, 1);
});
}
</script>
</head>
<body onload="main();">
<div style="width: 800px; height: 600px; -webkit-transform: scale(0.75,0.75); -moz-transform: scale(0.75,0.75)">
<canvas id="canvas" width="400px" height="400px" style="background-color: #cccccc;"></canvas>
</div>
</body>
</html>
上記の迅速で汚い例を考慮してください。キャンバスは、スケール変換が適用されたdivに含まれていることに注意してください。上記のコードは、すべてのWebkitベースのブラウザーで完全に機能します。マウスを移動させながら、キャンバス上にポイントを描画します。残念ながら、FirefoxではイベントモデルがoffsetX/Yプロパティをサポートしていないため、サポートされていません。 (おそらく)event.clientX(firefoxでもサポートされています)から、キャンバスの位置、変換などを考慮して、キャンバスの相対座標にマウス座標を変換するにはどうすればよいですか?ありがとう、ルカ。
LayerX、layerYを試してください
var x = (e.offsetX === undefined) ? e.layerX : e.offsetX;
var y = (e.offsetY === undefined) ? e.layerY : e.offsetY;
JQueryバグトラッカーページ から-ニースポリフィルは次のとおりです。
_var offX = (e.offsetX || e.pageX - $(e.target).offset().left);
_
..ここで、eはjqueryイベントから返されるイベントです。明らかに、プロジェクトにすでにJqueryがある場合のみ、そうでなければ、offset()
を手動で行う必要があります。
残念ながら、解決策はありませんでした。
良い実装を見つけました こちら :
var target = e.target || e.srcElement,
rect = target.getBoundingClientRect(),
offsetX = e.clientX - rect.left,
offsetY = e.clientY - rect.top;
e.offsetX = offsetX;
e.offsetY = offsetY;
残念ながら、offsetXとlayerXは、offsetXが現在の要素内のオフセットであるのとまったく同じではありませんが、layerXはページからのオフセットです。以下は、私が現在これに使用している修正です。
function fixEvent(e) {
if (! e.hasOwnProperty('offsetX')) {
var curleft = curtop = 0;
if (e.offsetParent) {
var obj=e;
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
e.offsetX=e.layerX-curleft;
e.offsetY=e.layerY-curtop;
}
return e;
}
Musaのソリューションにはバグがあります:e.offsetX === 0
およびe.layerX === undefined
...
var x = e.offsetX || e.layerX; // x is now undefined!
より堅牢なバージョンは次のとおりです。
var x = e.hasOwnProperty('offsetX') ? e.offsetX : e.layerX;
var y = e.hasOwnProperty('offsetY') ? e.offsetY : e.layerY;
または、offsetX
が定義されている場合、offsetY
も定義されると想定できるため、
var hasOffset = e.hasOwnProperty('offsetX'),
x = hasOffset ? e.offsetX : e.layerX,
y = hasOffset ? e.offsetY : e.layerY;
offset
は実際にはlayer
に直接変換されません。 offset
プロパティは要素のマージンを考慮しません。以下のコードでこれを説明する必要があります。
function(e) {
var x = e.offsetX, y = e.offsetY;
if(e.hasOwnProperty('layerX')) {
x = e.layerX - e.currentTarget.offsetLeft;
y = e.layerY - e.currentTarget.offsetTop;
}
}
さまざまな理由で、jquery以外のバージョンは完全に機能しません。しかし、あなたの助けを借りて、私はこれを機能させました:
if(!event.hasOwnProperty('offsetX')) {
event.offsetX = event.layerX - event.currentTarget.offsetLeft;
event.offsetY = event.layerY - event.currentTarget.offsetTop;
}
すべての回答がここに投稿されていることがわかりました除く EnotionZとlaz branniganによる最後の2つの回答(以前はそれぞれ0票だった)がdiv内にいくつかの要素が含まれている場合は間違っていました。私の場合、1つのdiv内に複数のキャンバス要素があり、各キャンバスを個別に聞いています。
FireFoxとChromeでは次のようになります。
//inside my mouse events handler:
var anOffsetX = (inEvent.offsetX !== undefined) ? inEvent.offsetX : (inEvent.layerX - inEvent.target.offsetLeft);
var anOffsetY = (inEvent.offsetY !== undefined) ? inEvent.offsetY : (inEvent.layerY - inEvent.target.offsetTop);
おそらく、これは彼の投稿で示されたEnotionZなどのマージンにも機能しますが、私はそれを試していません。
しかし、layerX
、layerY
フィールドがない場合はどうしますか?
var xe=e.offsetX,ye=e.offsetY;
if(!xe){
xe=e.clientX - $(e.target).offset().left;
}
if(!ye){
ye= e.clientY - $(e.target).offset().top;
}
それでも解決策が必要な人がいるなら、これはFirefoxで完璧に動作します:
var x = e.offsetX || e.originalEvent.layerX;
var y = e.offsetY || e.originalEvent.layerY;