Obtener clic evento de cada rectángulo dentro del canvas?

No sé cómo registrar el evento click en cada rectángulo.

aquí está la muestra:

http://jsfiddle.net/9WWqG/1/

Básicamente va a tener que rastrear dónde están sus rectangularjs en el canvas, luego configure un detector de eventos en el canvas en sí. Desde allí, puede tomar las coordenadas del evento click y recorrer todos sus rectangularjs para comprobar si hay “colisiones”.

Aquí hay un ejemplo de hacer justamente eso: http://jsfiddle.net/9WWqG/2/

html:

  

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); } 

Esta es una vieja pregunta, pero lo que antes era difícil de hacer cuando se publicó ahora es mucho más fácil.

Hay muchas bibliotecas que realizan un seguimiento de la posición de los objetos que se dibujaron en el canvas y manejan todas las complejidades del manejo de las interacciones del mouse. Consulte EaselJS , KineticJS , Paper.js o Fabric.js y esta comparación de las bibliotecas de canvas para obtener más información.

También puede tomar un enfoque diferente y usar Raphaël y gRaphaël para tener una solución que use SVG y VML en lugar de canvas y funcione incluso en IE6.

Su ejemplo cambió para usar Raphaël se vería así:

 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'); }); 

Ver DEMO .

Actualización 2015

También puede usar ART , una API de dibujo vectorial de modo retenido para canvass HTML5. Consulte esta respuesta para obtener más información.

Encontré una manera de hacer que esto funcione en mozilla usando clientX, clientY en lugar de offsetX / offsetY.

Además, si su canvas se extiende más allá de la innerHeight , y utiliza el desplazamiento, agregue window.pageYOffset al e.clientY . Continúa de la misma manera, si su canvas se extiende más allá del ancho.

Otro ejemplo es en mi github: https://github.com/michaelBenin/fi-test

Aquí hay otro enlace que explica esto: http://eli.thegreenplace.net/2010/02/13/finding-out-the-mouse-click-position-on-a-canvas-with-javascript/

Utilice la función siguiente si desea admitir más de un rectángulo en el canvas y manejar su evento de clic ….. lógica modificada dada por 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; } 

Utilice la función siguiente si desea admitir más de un rectángulo en el canvas y gestionar su evento de clic

  
  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() }); 

Aquí hay un ejemplo de hacer justamente eso: http://jsfiddle.net/BmeKr/1291/