基本的には、長方形がキャンバス上のどこにあるかを追跡してから、キャンバス自体にイベントリスナーを設定します。そこから、クリックイベントの座標を取得し、すべての四角形を調べて「衝突」をテストできます。
これを行う例を次に示します。 http://jsfiddle.net/9WWqG/2/
html:
<canvas id="myCanvas" width="300" height="150">
</canvas>
javascript:
// get canvas element.
var elem = document.getElementById('myCanvas');
function collides(rects, x, y) {
var isCollision = false;
for (var i = 0, len = rects.length; i < len; i++) {
var left = rects[i].x, right = rects[i].x+rects[i].w;
var top = rects[i].y, bottom = rects[i].y+rects[i].h;
if (right >= x
&& left <= x
&& bottom >= y
&& top <= y) {
isCollision = rects[i];
}
}
return isCollision;
}
// check if context exist
if (elem && elem.getContext) {
// list of rectangles to render
var rects = [{x: 0, y: 0, w: 50, h: 50},
{x: 75, y: 0, w: 50, h: 50}];
// get context
var context = elem.getContext('2d');
if (context) {
for (var i = 0, len = rects.length; i < len; i++) {
context.fillRect(rects[i].x, rects[i].y, rects[i].w, rects[i].h);
}
}
// listener, using W3C style for example
elem.addEventListener('click', function(e) {
console.log('click: ' + e.offsetX + '/' + e.offsetY);
var rect = collides(rects, e.offsetX, e.offsetY);
if (rect) {
console.log('collision: ' + rect.x + '/' + rect.y);
} else {
console.log('no collision');
}
}, false);
}
これは古い質問ですが、投稿時にかつて困難だったことがはるかに簡単になりました。
キャンバスに描かれたオブジェクトの位置を追跡し、マウス操作の複雑な処理をすべて処理する多くのライブラリがあります。 EaselJS 、 KineticJS 、 Paper.js または Fabric.js およびこれを参照してください キャンバスライブラリの比較 詳細については。
また、別のアプローチを採用し、 Raphaël および gRaphaël を使用して、キャンバスの代わりにSVGおよびVMLを使用し、IE6でも機能するソリューションを作成することもできます。
ラファエルを使用するように変更した例は、次のようになります。
var r = Raphael(0, 0, 300, 150);
r.rect(0, 0, 50, 50)
.attr({fill: "#000"})
.click(function () {
alert('first rectangle clicked');
});
r.rect(75, 0, 50, 50)
.attr({fill: "#000"})
.click(function () {
alert('second rectangle clicked');
});
[〜#〜] demo [〜#〜] を参照してください。
[〜#〜] art [〜#〜] を使用することもできます。これは、HTML5キャンバス用の保持モードのベクター描画APIです。詳細は をご覧ください) 詳細については。
私は、offsetX/offsetYの代わりにclientX、clientYを使用してこれをMozillaで機能させる方法を見つけました。
また、キャンバスがinnerHeight
を超えて拡張され、スクロールを使用する場合は、window.pageYOffset
をe.clientY
に追加します。キャンバスが幅を超えている場合も同様です。
別の例は私のgithubにあります: https://github.com/michaelBenin/fi-test
これを説明する別のリンクを次に示します。 http://eli.thegreenplace.net/2010/02/13/finding-out-the-mouse-click-position-on-a-canvas-with-javascript/
キャンバスで複数の長方形をサポートし、そのクリックイベントを処理する場合は、以下の関数を使用してください
<canvas id="myCanvas" width="1125" height="668" style="border: 3px solid #ccc; margin:0;padding:0;" />
var elem = document.getElementById('myCanvas'),
elemLeft = elem.offsetLeft,
elemTop = elem.offsetTop,
context = elem.getContext('2d'),
elements = [];
// Add event listener for `click` events.
elem.addEventListener('click', function (event) {
// var leftWidth = $("#leftPane").css("width")
// var x = event.pageX - (elemLeft + parseInt(leftWidth) + 220),
// y = event.pageY - (elemTop + 15);
var x = event.pageX - elemLeft,
y = event.pageY - elemTop;
elements.forEach(function (element) {
if (y > element.top && y < element.top + element.height && x > element.left && x < element.left + element.width) {
alert(element.text);
}
});
}, false);
// Set the value content (x,y) axis
var x = 15, y = 20, maxWidth = elem.getAttribute("width"),
maxHeight = elem.getAttribute("height"), type = 'TL',
width = 50, height = 60, text = "", topy = 0, leftx = 0;
for (i = 1; i <= 15; i++) {
y = 10;
for (j = 1; j <= 6; j++) {
width = 50, height = 60
switch (j) {
case 1:
type = 'TL'; // Trailer
height = 60;
width = 85;
text = i + 'E';
break;
case 2:
type = 'DR'; // Door
height = 35;
width = 85;
text = i;
break;
case 3:
type = 'FL'; // Floor
height = 30;
width = 40;
break;
case 4:
type = 'FL'; // Floor
height = 30;
width = 40;
y -= 10;
break;
case 5:
type = 'DR'; // Door
height = 35;
width = 85;
text = i*10 + 1;
y = topy;
break;
case 6:
type = 'TL'; // Trailer
height = 60;
width = 85;
text = i + 'F';
y += 5;
break;
}
topy = y;
leftx = x;
if (type == 'FL') {
for (k = 1; k <= 12; k++) {
elements.Push({
colour: '#05EFFF',
width: width,
height: height,
top: topy,
left: leftx,
text: k,
textColour: '#fff',
type: type
});
if (k % 2 == 0) {
topy = y + elements[j - 1].height + 5;
leftx = x;
y = topy;
}
else {
topy = y;
leftx = x + elements[j - 1].width + 5;
}
}
x = leftx;
y = topy;
}
else {
elements.Push({
colour: '#05EFFF',
width: width,
height: height,
top: y,
left: x,
text: text,
textColour: '#fff',
type: type
});
}
//get the y axis for next content
y = y + elements[j-1].height + 6
if (y >= maxHeight - elements[j-1].height) {
break;
}
}
//get the x axis for next content
x = x + elements[0].width + 15
if (x >= maxWidth - elements[0].width) {
break;
}
}
// Render elements.
elements.forEach(function (element) {
context.font = "14pt Arial";
context.strokeStyle = "#000";
context.rect(element.left, element.top, element.width, element.height);
if (element.type == 'FL') {
context.fillText(element.text, element.left + element.width / 4, element.top + element.height / 1.5);
}
else {
context.fillText(element.text, element.left + element.width / 2.5, element.top + element.height / 1.5);
}
context.lineWidth = 1;
context.stroke()
});
これを行う例を次に示します。 http://jsfiddle.net/BmeKr/1291/
キャンバスで複数の長方形をサポートし、そのクリックイベントを処理する場合は、以下の関数を使用してください。
function collides(myRect, x, y) {
var isCollision = false;
for (var i = 0, len = myRect.length; i < len; i++) {
var left = myRect[i].x, right = myRect[i].x+myRect[i].w;
var top = myRect[i].y, bottom = myRect[i].y+myRect[i].h;
if ((left + right) >= x
&& left <= x
&& (top +bottom) >= y
&& top <= y) {
isCollision = json.Major[i];
}
}
}
return isCollision;
}