¿Cómo obtengo las coordenadas de un clic del mouse en un elemento del lienzo? [duplicar]
¿Cuál es la forma más sencilla de agregar un controlador de eventos de clic a un elemento de lienzo que devolverá las coordenadas xey del clic (en relación con el elemento de lienzo)?
No se requiere compatibilidad con navegadores antiguos; Safari, Opera y Firefox son suficientes.
Si le gusta la simplicidad pero aún desea la funcionalidad entre navegadores, encontré que esta solución funcionó mejor para mí. Esta es una simplificación de la solución de @Aldekein pero sin jQuery .
function getCursorPosition(canvas, event) {
const rect = canvas.getBoundingClientRect()
const x = event.clientX - rect.left
const y = event.clientY - rect.top
console.log("x: " + x + " y: " + y)
}
const canvas = document.querySelector('canvas')
canvas.addEventListener('mousedown', function(e) {
getCursorPosition(canvas, e)
})
Actualización (5/5/16): en su lugar, se debe utilizar la respuesta de Patriques , ya que es más simple y confiable.
Dado que el lienzo no siempre tiene un estilo relativo a toda la página, canvas.offsetLeft/Top
no siempre devuelve lo que necesita. Devolverá el número de píxeles que está desplazado en relación con su elemento offsetParent, que puede ser algo así como un div
elemento que contiene el lienzo con un position: relative
estilo aplicado. Para tener en cuenta esto, debes recorrer la cadena de offsetParent
s, comenzando con el elemento del lienzo. Este código funciona perfectamente para mí, probado en Firefox y Safari, pero debería funcionar para todos.
function relMouseCoords(event){
var totalOffsetX = 0;
var totalOffsetY = 0;
var canvasX = 0;
var canvasY = 0;
var currentElement = this;
do{
totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
}
while(currentElement = currentElement.offsetParent)
canvasX = event.pageX - totalOffsetX;
canvasY = event.pageY - totalOffsetY;
return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
La última línea hace que sea conveniente obtener las coordenadas del mouse en relación con un elemento del lienzo. Todo lo que se necesita para obtener las coordenadas útiles es
coords = canvas.relMouseCoords(event);
canvasX = coords.x;
canvasY = coords.y;
Edición 2018: esta respuesta es bastante antigua y utiliza comprobaciones para navegadores antiguos que ya no son necesarios, ya que las propiedades clientX
y clientY
funcionan en todos los navegadores actuales. Es posible que desee consultar Patriques Answer para obtener una solución más simple y reciente.
Respuesta original:
Como se describe en un artículo que encontré en ese entonces pero que ya no existe:
var x;
var y;
if (e.pageX || e.pageY) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;
Funcionó perfectamente bien para mí.
Los navegadores modernos ahora manejan esto por usted. Chrome, IE9 y Firefox admiten offsetX/Y de esta manera, pasando el evento desde el controlador de clic.
function getRelativeCoords(event) {
return { x: event.offsetX, y: event.offsetY };
}
La mayoría de los navegadores modernos también admiten LayerX/Y, sin embargo, Chrome e IE usan LayerX/Y para el desplazamiento absoluto del clic en la página, incluido el margen, el relleno, etc. En Firefox, LayerX/Y y offsetX/Y son equivalentes, pero el desplazamiento no No existía previamente. Entonces, para compatibilidad con navegadores un poco más antiguos, puedes usar:
function getRelativeCoords(event) {
return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}
Así que este es un tema simple pero un poco más complicado de lo que parece.
En primer lugar, aquí suelen haber preguntas combinadas.
Cómo obtener las coordenadas relativas del mouse del elemento
Cómo obtener las coordenadas del mouse de píxeles del lienzo para 2D Canvas API o WebGL
entonces, respuestas
Cómo obtener las coordenadas relativas del mouse del elemento
Si el elemento es o no un lienzo, las coordenadas relativas del mouse del elemento son las mismas para todos los elementos.
Hay 2 respuestas simples a la pregunta "Cómo obtener las coordenadas relativas del mouse en el lienzo"
Respuesta simple #1 uso offsetX
yoffsetY
canvas.addEventListner('mousemove', (e) => {
const x = e.offsetX;
const y = e.offsetY;
});
Esta respuesta funciona en Chrome, Firefox y Safari. A diferencia de todos los demás valores de eventos offsetX
, offsetY
tenga en cuenta las transformaciones CSS.
El mayor problema con offsetX
y offsetY
es que a partir de 2019/05 no existen en eventos táctiles y, por lo tanto, no se pueden usar con iOS Safari. Existen en eventos de puntero que existen en Chrome y Firefox, pero no en Safari, aunque aparentemente Safari está trabajando en ello .
Otra cuestión es que los acontecimientos deben estar en el propio lienzo. Si los pones sobre algún otro elemento o la ventana no podrás luego elegir el lienzo como punto de referencia.
Respuesta simple #2 uso clientX
, clientY
ycanvas.getBoundingClientRect
Si no le importan las transformaciones CSS, la siguiente respuesta más simple es llamar canvas. getBoundingClientRect()
y restar la izquierda desde clientX
y top
hacia clientY
como en
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
});
Esto funcionará siempre que no haya transformaciones CSS. También funciona con eventos táctiles y también funcionará con Safari iOS.
canvas.addEventListener('touchmove', (e) => {
const rect = canvas. getBoundingClientRect();
const x = e.touches[0].clientX - rect.left;
const y = e.touches[0].clientY - rect.top;
});
Cómo obtener las coordenadas del mouse del píxel del lienzo para la API 2D Canvas
Para esto, debemos tomar los valores que obtuvimos arriba y convertirlos del tamaño en que se muestra el lienzo al número de píxeles en el lienzo mismo.
con canvas.getBoundingClientRect
y clientX
yclientY
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const elementRelativeX = e.clientX - rect.left;
const elementRelativeY = e.clientY - rect.top;
const canvasRelativeX = elementRelativeX * canvas.width / rect.width;
const canvasRelativeY = elementRelativeY * canvas.height / rect.height;
});
o con offsetX
yoffsetY
canvas.addEventListener('mousemove', (e) => {
const elementRelativeX = e.offsetX;
const elementRelativeY = e.offsetY;
const canvasRelativeX = elementRelativeX * canvas.width / canvas.clientWidth;
const canvasRelativeY = elementRelativeY * canvas.height / canvas.clientHeight;
});
Nota: En todos los casos, no agregue relleno ni bordes al lienzo. Hacerlo complicará enormemente el código. En lugar de querer un borde o relleno, rodee el lienzo con algún otro elemento y agregue el relleno o el borde al elemento exterior.
Ejemplo de trabajo usando event.offsetX
,event.offsetY
Mostrar fragmento de código
Ejemplo de trabajo usando canvas.getBoundingClientRect
y event.clientX
yevent.clientY
Mostrar fragmento de código