答案 0 :(得分:23)
你基本上必须跟踪画布上矩形的位置,然后在画布上设置一个事件监听器。从那里你可以获取click事件的坐标并浏览所有矩形来测试'碰撞'。
以下是这样做的示例: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);
}
答案 1 :(得分:13)
这是一个古老的问题,但在发布时曾经很难做到的事情现在变得容易了。
有许多库可以跟踪在画布上绘制的对象的位置,并处理处理鼠标交互的所有复杂性。见EaselJS, KineticJS, Paper.js或 Fabric.js以及comparison of canvas libraries以获取更多信息。
您也可以采用不同的方法和使用方法 Raphaël和gRaphaël 有一个使用SVG和VML而不是画布的解决方案,甚至可以在IE6上运行。
您的示例更改为使用Raphaël将如下所示:
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 - 有关详情,请参阅this answer。
答案 2 :(得分:2)
我找到了一种方法,可以使用 clientX,clientY 代替offsetX / offsetY在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/
答案 3 :(得分:0)
如果你想在画布上支持多个矩形并处理它的点击事件,请使用下面的功能......由Matt King给出的修改逻辑。
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;
}
答案 4 :(得分:0)
如果您想在画布中支持多个矩形并处理其点击事件,请使用以下功能
<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/