Html 获取画布内每个矩形的点击事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5014851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
get click event of each rectangle inside canvas?
提问by twesh
I dont know how to register click event on each rectangle.
我不知道如何在每个矩形上注册点击事件。
here is the sample:
这是示例:
回答by Matt King
You're basically going to have to track where your rectangles are on the canvas, then set up an event listener on the canvas itself. From there you can take the coordinates of the click event and go through all your rectangles to test for 'collisions'.
您基本上必须跟踪矩形在画布上的位置,然后在画布本身上设置一个事件侦听器。从那里您可以获取单击事件的坐标并遍历所有矩形以测试“碰撞”。
Here's an example of doing just that: http://jsfiddle.net/9WWqG/2/
这是一个这样做的例子:http: //jsfiddle.net/9WWqG/2/
html:
html:
<canvas id="myCanvas" width="300" height="150">
</canvas>
javascript:
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);
}
回答by rsp
This is an old question but what was once hard to do when it was posted is now much easier.
这是一个古老的问题,但在发布时曾经很难做的事情现在变得容易多了。
There are many libraries that keep track of the position of your objects that were drawn on canvas and handle all of the complexities of handling mouse interactions. See EaselJS, KineticJS, Paper.jsor Fabric.jsand this comparison of canvas librariesfor more.
有许多库可以跟踪在画布上绘制的对象的位置,并处理处理鼠标交互的所有复杂性。有关更多信息,请参阅EaselJS、 KineticJS、 Paper.js或 Fabric.js以及此画布库的比较。
You can also take a different approach and use Rapha?land gRapha?lto have a solution that uses SVG and VML instead of canvas and works even on IE6.
您还可以采用不同的方法并使用 Rapha?l和gRapha?l来获得使用 SVG 和 VML 而不是画布的解决方案,并且甚至可以在 IE6 上工作。
Your example changed to use Rapha?l would look like this:
您的示例更改为使用 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');
});
See DEMO.
见演示。
Update 2015
2015 年更新
You may also be able to use ART, a retained mode vector drawing API for HTML5 canvas - see this answerfor more info.
回答by Michael Benin
I found a way to make this work in mozilla using the clientX,clientYinstead of offsetX/offsetY.
我找到了一种使用clientX,clientY而不是 offsetX/offsetY在 mozilla 中完成这项工作的方法。
Also, if your canvas extends beyond the innerHeight
, and uses the scroll, add the window.pageYOffset
to the e.clientY
. Goes the same way, if your canvas extends beyond the width.
此外,如果您的画布超出innerHeight
,并使用滚动,请将window.pageYOffset
加到e.clientY
. 以同样的方式,如果您的画布超出宽度。
Another example is at my github: https://github.com/michaelBenin/fi-test
另一个例子是在我的 github:https: //github.com/michaelBenin/fi-test
Here is another link that explains this: http://eli.thegreenplace.net/2010/02/13/finding-out-the-mouse-click-position-on-a-canvas-with-javascript/
这是解释这一点的另一个链接:http: //eli.thegreenplace.net/2010/02/13/finding-out-the-mouse-click-position-on-a-canvas-with-javascript/
回答by Siddharth Vaghasia
Please use below function if you want to support more than one rectangle in canvas and handle its click event..... modified logic given by Matt King.
如果您想在画布中支持一个以上的矩形并处理其点击事件,请使用以下函数..... 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;
}
回答by Sheik Jameer S
Please use below function if you want to support more than one rectangle in canvas and handle its click event
如果您想在画布中支持多个矩形并处理其点击事件,请使用以下函数
<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()
});
Here's an example of doing just that: http://jsfiddle.net/BmeKr/1291/
这是一个这样做的例子:http: //jsfiddle.net/BmeKr/1291/