シンプルな 1:1 シナリオ
キャンバス要素がビットマップ サイズと比較して 1:1 である状況では、次のスニペットを使用してマウスの位置を取得できます。
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
イベントとキャンバスを引数としてイベントから呼び出すだけです。マウス位置の x と y を持つオブジェクトを返します。
取得しているマウスの位置はクライアント ウィンドウに相対的であるため、canvas 要素の位置を差し引いて要素自体に相対的に変換する必要があります。
コードへの統合の例:
//put this outside the event loop..
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
function draw(evt) {
var pos = getMousePos(canvas, evt);
context.fillStyle = "#000000";
context.fillRect (pos.x, pos.y, 4, 4);
}
注: 境界線とパディングは、canvas 要素に直接適用すると位置に影響するため、これらを考慮する必要がありますgetComputedStyle()
。または、これらのスタイルを代わりに親 div に適用します。
エレメントとビットマップのサイズが異なる場合
要素のサイズがビットマップ自体とは異なる場合、たとえば、要素が CSS を使用してスケーリングされている場合や、ピクセルの縦横比がある場合など、これに対処する必要があります。
例:
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect(), // abs. size of element
scaleX = canvas.width / rect.width, // relationship bitmap vs. element for X
scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y
return {
x: (evt.clientX - rect.left) * scaleX, // scale mouse coordinates after they have
y: (evt.clientY - rect.top) * scaleY // been adjusted to be relative to element
}
}
コンテキストに変換を適用 (スケール、回転など)
次に、回転、傾斜/せん断、スケール、平行移動などのコンテキストに変換を適用した、より複雑なケースがあります。これに対処するには、現在の行列の逆行列を計算できます。
新しいブラウザでは、プロパティを介して現在の行列を読み取ることができ、currentTransform
Firefox (現在のアルファ版) では、mozCurrentTransformInverted
. ただし、Firefox は、 を介しmozCurrentTransform
て Array を返しますが、そうではありませんDOMMatrix
。どちらの Chrome も、実験的なフラグを介して有効にすると、a を返しますDOMMatrix
が、SVGMatrix
.
ただし、ほとんどの場合、完全なサポートが得られるまで、独自のカスタム マトリックス ソリューションを実装する必要があります (ここでは、私自身のソリューション- フリー/MIT プロジェクトなど)。
マトリックスを取得するためのパスに関係なく、最終的にマトリックスを取得したら、それを反転してマウス座標に適用する必要があります。座標はキャンバスに渡され、キャンバスはそのマトリックスを使用して、現在の場所に戻すように変換します。
このようにして、ポイントはマウスに対して正しい位置になります。また、ここでは、(逆行列をそれらに適用する前に) 要素に対して相対的になるように座標を調整する必要があります。
マトリックスステップのみを示す例
function draw(evt) {
var pos = getMousePos(canvas, evt); // get adjusted coordinates as above
var imatrix = matrix.inverse(); // get inverted matrix somehow
pos = imatrix.applyToPoint(pos.x, pos.y); // apply to adjusted coordinate
context.fillStyle = "#000000";
context.fillRect(pos.x-1, pos.y-1, 2, 2);
}
currentTransform
実装時の使用例は次のとおりです。
var pos = getMousePos(canvas, e); // get adjusted coordinates as above
var matrix = ctx.currentTransform; // W3C (future)
var imatrix = matrix.invertSelf(); // invert
// apply to point:
var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e;
var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f;
更新私はこれらすべてのステップを単一の使いやすいオブジェクトに埋め込むための無料のソリューション (MIT) を作成しました。