Posterior a de esta larga selección de información resolvimos este dilema que presentan muchos lectores. Te ofrecemos la respuesta y esperamos resultarte de gran apoyo.
Solución:
El escenario simple 1: 1
Para situaciones en las que el elemento de lienzo es 1: 1 en comparación con el tamaño del mapa de bits, puede obtener las posiciones del mouse mediante este fragmento:
function getMousePos(canvas, evt)
var rect = canvas.getBoundingClientRect();
return
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
;
Simplemente llámelo desde su evento con el evento y el lienzo como argumentos. Devuelve un objeto con xey para las posiciones del mouse.
Como la posición del mouse que está obteniendo es relativa a la ventana del cliente, tendrá que restar la posición del elemento de lienzo para convertirlo en relación con el elemento en sí.
Ejemplo de integración en su código:
//put this outside the event loop..
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
function draw(evt)
var pos = getMousePos(canvas, evt);
context.fillStyle = "#000000";
context.fillRect (pos.x, pos.y, 4, 4);
Nota: los bordes y el relleno afectarán la posición si se aplican directamente al elemento del lienzo, por lo que deben tenerse en cuenta a través de getComputedStyle()
– o aplique esos estilos a un div padre en su lugar.
Cuando el elemento y el mapa de bits son de diferentes tamaños
Cuando existe la situación de tener el elemento en un tamaño diferente al del mapa de bits en sí, por ejemplo, el elemento se escala usando CSS o hay una relación de aspecto de píxeles, etc., tendrá que abordar esto.
Ejemplo:
function getMousePos(canvas, evt)
var rect = canvas.getBoundingClientRect(), // abs. size of element
scaleX = canvas.width / rect.width, // relationship bitmap vs. element for X
scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y
return
x: (evt.clientX - rect.left) * scaleX, // scale mouse coordinates after they have
y: (evt.clientY - rect.top) * scaleY // been adjusted to be relative to element
Con transformaciones aplicadas al contexto (escala, rotación, etc.)
Luego está el caso más complicado en el que ha aplicado transformación al contexto, como rotación, sesgo / corte, escala, traslación, etc. Para solucionar esto, puede calcular la matriz inversa de la matriz actual.
Los navegadores más nuevos le permiten leer la matriz actual a través de la currentTransform
propiedad y Firefox (alfa actual) incluso proporcionan una matriz invertida a través de la mozCurrentTransformInverted
. Firefox sin embargo, a través de mozCurrentTransform
, devolverá una matriz y no DOMMatrix
como debería. Ni Chrome, cuando se habilita a través de indicadores experimentales, devolverá un DOMMatrix
pero un SVGMatrix
.
En la mayoría de los casos, sin embargo, tendrá que implementar una solución matricial personalizada propia (como mi propia solución aquí – proyecto gratuito / MIT) hasta que obtenga soporte completo.
Cuando finalmente haya obtenido la matriz, independientemente de la ruta que tome para obtener una, deberá invertirla y aplicarla a las coordenadas de su mouse. Luego, las coordenadas se pasan al lienzo, que usará su matriz para convertirlo en el lugar donde se encuentre en ese momento.
De esta manera, el punto estará en la posición correcta con respecto al mouse. También aquí debe ajustar las coordenadas (antes de aplicarles la matriz inversa) para que sean relativas al elemento.
Un ejemplo que solo muestra los pasos de la matriz.
function draw(evt)
var pos = getMousePos(canvas, evt); // get adjusted coordinates as above
var imatrix = matrix.inverse(); // get inverted matrix somehow
pos = imatrix.applyToPoint(pos.x, pos.y); // apply to adjusted coordinate
context.fillStyle = "#000000";
context.fillRect(pos.x-1, pos.y-1, 2, 2);
Un ejemplo de uso currentTransform
cuando se implemente sería:
var pos = getMousePos(canvas, e); // get adjusted coordinates as above
var matrix = ctx.currentTransform; // W3C (future)
var imatrix = matrix.invertSelf(); // invert
// apply to point:
var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e;
var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f;
Actualizar Hice una solución gratuita (MIT) para incrustar todos estos pasos en un solo objeto fácil de usar que se puede encontrar aquí y también se ocupa de algunas otras cosas esenciales que la mayoría ignora.
Puede obtener las posiciones del mouse usando este fragmento:
function getMousePos(canvas, evt)
var rect = canvas.getBoundingClientRect();
return
x: (evt.clientX - rect.left) / (rect.right - rect.left) * canvas.width,
y: (evt.clientY - rect.top) / (rect.bottom - rect.top) * canvas.height
;
Este código tiene en cuenta tanto el cambio de coordenadas al espacio del lienzo (evt.clientX - rect.left
) y escalado cuando el tamaño lógico del lienzo difiere del tamaño de su estilo (/ (rect.right - rect.left) * canvas.width
ver: Ancho y alto del lienzo en HTML5).
Ejemplo: http://jsfiddle.net/sierawski/4xezb7nL/
Fuente: comentario de jerryj sobre http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
Necesitas obtener la posición del mouse relativo al lienzo
Para hacer eso, necesita conocer la posición X / Y del lienzo en la página.
Esto se llama “desplazamiento” del lienzo, y aquí se explica cómo obtener el desplazamiento. (Estoy usando jQuery para simplificar la compatibilidad entre navegadores, pero si desea usar javascript sin formato, un Google rápido lo obtendrá también).
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
Luego, en el controlador de su mouse, puede obtener el mouse X / Y de esta manera:
function handleMouseDown(e)
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
Aquí hay un código ilustrativo y un violín que muestra cómo realizar un seguimiento exitoso de los eventos del mouse en el lienzo:
http://jsfiddle.net/m1erickson/WB7Zu/
Move, press and release the mouse
Down
Move
Up
Out
Si tienes alguna sospecha o disposición de innovar nuestro tutorial eres capaz de realizar una glosa y con gusto lo interpretaremos.