javascript - llamar - ¿Cómo agrego un controlador de eventos onClick simple a un elemento canvas?
llamar funcion javascript html sin evento (6)
Como alternativa a la respuesta de alex:
Podría usar un dibujo SVG en lugar de un dibujo Canvas. Allí puede agregar eventos directamente a los objetos DOM trazados.
ver por ejemplo:
Haciendo clic en un objeto de imagen svg con onclick, evitando el posicionamiento absoluto
Soy un experimentado programador de Java pero estoy viendo cosas de JavaScript / HTML5 por primera vez en aproximadamente una década. Estoy completamente perplejo sobre lo que debería ser la cosa más simple de la historia.
Como ejemplo, solo quería dibujar algo y agregarle un controlador de eventos. Estoy seguro de que estoy haciendo algo estúpido, pero lo he buscado todo y nada de lo que se sugiere (por ejemplo, la respuesta a esta pregunta: agregar propiedad onclick para ingresar con JavaScript ) funciona. Estoy usando Firefox 10.0.1. Mi código sigue. Verá varias líneas comentadas y al final de cada una de ellas encontrará una descripción de qué (o qué no) sucede.
¿Cuál es la sintaxis correcta aquí? ¡Me estoy volviendo loco!
<html>
<body>
<canvas id="myCanvas" width="300" height="150"/>
<script language="JavaScript">
var elem = document.getElementById(''myCanvas'');
// elem.onClick = alert("hello world"); - displays alert without clicking
// elem.onClick = alert(''hello world''); - displays alert without clicking
// elem.onClick = "alert(''hello world!'')"; - does nothing, even with clicking
// elem.onClick = function() { alert(''hello world!''); }; - does nothing
// elem.onClick = function() { alert("hello world!"); }; - does nothing
var context = elem.getContext(''2d'');
context.fillStyle = ''#05EFFF'';
context.fillRect(0, 0, 150, 100);
</script>
</body>
Como otra alternativa barata en un lienzo algo estático, usar un elemento img superpuesto con una definición de mapa de uso es rápido y sucio. Funciona especialmente bien en elementos de lienzo basados en polígonos, como un gráfico circular.
Cuando dibuja un elemento canvas
, simplemente dibuja un mapa de bits en modo inmediato .
Los elementos (formas, líneas, imágenes) que se dibujan no tienen representación además de los píxeles que utilizan y su color.
Por lo tanto, para obtener un evento de clic en un elemento de canvas
(forma), debe capturar los eventos de clic en el elemento HTML de canvas
y usar algunos cálculos para determinar en qué elemento se hizo clic, siempre que esté almacenando el ancho / alto de los elementos y x / y offset
Para agregar un evento de click
a su elemento canvas
, use ...
canvas.addEventListener(''click'', function() { }, false);
Para determinar en qué elemento se hizo 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 x = event.pageX - elemLeft,
y = event.pageY - elemTop;
// Collision detection between clicked offset and element.
elements.forEach(function(element) {
if (y > element.top && y < element.top + element.height
&& x > element.left && x < element.left + element.width) {
alert(''clicked an element'');
}
});
}, false);
// Add element.
elements.push({
colour: ''#05EFFF'',
width: 150,
height: 100,
top: 20,
left: 15
});
// Render elements.
elements.forEach(function(element) {
context.fillStyle = element.colour;
context.fillRect(element.left, element.top, element.width, element.height);
});
jsFiddle .
Este código adjunta un evento de click
al elemento canvas
y luego empuja una forma (llamada element
en mi código) a una matriz de elements
. Puede agregar tantos como desee aquí.
El objetivo de crear una matriz de objetos es que podamos consultar sus propiedades más adelante. Después de que todos los elementos se hayan insertado en la matriz, recorremos y representamos cada uno según sus propiedades.
Cuando se activa el evento click
, el código recorre los elementos y determina si el clic se realizó sobre cualquiera de los elementos en la matriz de elements
. Si es así, activa una alert()
, que podría modificarse fácilmente para hacer algo como eliminar el elemento del arreglo, en cuyo caso necesitaría una función de renderización separada para actualizar el canvas
.
Para completar, ¿por qué tus intentos no funcionaron?
elem.onClick = alert("hello world"); // displays alert without clicking
Esto está asignando el valor de retorno de alert()
a la propiedad onClick
de elem
. Invoca de inmediato la alert()
.
elem.onClick = alert(''hello world''); // displays alert without clicking
En JavaScript, el ''
y "
son semánticamente idénticos, el lexer probablemente usa [''"]
para las comillas.
elem.onClick = "alert(''hello world!'')"; // does nothing, even with clicking
Está asignando una cadena a la propiedad onClick
de elem
.
elem.onClick = function() { alert(''hello world!''); }; // does nothing
JavaScript distingue mayúsculas de minúsculas La propiedad onclick
es el método arcaico de adjuntar controladores de eventos. Solo permite adjuntar un evento con la propiedad y el evento se puede perder al serializar el HTML.
elem.onClick = function() { alert("hello world!"); }; // does nothing
Nuevamente, '' === "
.
Recomiendo el siguiente artículo: Hit Region Detection para Canvas HTML5 y cómo escuchar para hacer clic en Eventos en Canvas Shapes que pasa por varias situaciones.
Sin embargo, no cubre la API addHitRegion
, que debe ser la mejor manera (el uso de funciones matemáticas y / o comparaciones es bastante propenso a errores). Este enfoque se detalla en developer.mozilla
También puede poner elementos DOM, como div
en la parte superior del lienzo que representaría sus elementos de lienzo y se colocará de la misma manera.
Ahora puede adjuntar detectores de eventos a estos divs y ejecutar las acciones necesarias.
La respuesta de Alex es bastante clara, pero cuando se utiliza el contexto de rotación puede ser difícil rastrear las coordenadas x, y, así que he hecho una Demo muestra cómo hacer un seguimiento de eso.
Básicamente estoy usando esta función y le doy el ángulo y la cantidad de distancia recorrida en ese ángel antes de dibujar el objeto.
function rotCor(angle, length){
var cos = Math.cos(angle);
var sin = Math.sin(angle);
var newx = length*cos;
var newy = length*sin;
return {
x : newx,
y : newy
};
}