tag style from div attribute javascript canvas html5-canvas mouse-position

javascript - style - Posición real del mouse en el lienzo



html title attribute style (5)

El escenario simple 1: 1

Para situaciones en las que el elemento canvas es 1: 1 en comparación con el tamaño del mapa de bits, puede obtener las posiciones del mouse con este fragmento:

function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: evt.clientX - rect.left, y: evt.clientY - rect.top }; }

Solo llámalo desde tu evento con el evento y 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, deberá restar la posición del elemento canvas para convertirlo en relación con el elemento en sí.

Ejemplo de integración en tu 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); }

Violín con modificaciones

Nota: los bordes y el relleno afectarán la posición si se aplica directamente al elemento de lienzo, por lo que estos deben considerarse a través de getComputedStyle() o, en su lugar, debe aplicar esos estilos a un div principal.

Cuando Element y Bitmap son de diferentes tamaños

Cuando existe la situación de tener el elemento en un tamaño diferente que el mapa de bits en sí, por ejemplo, el elemento se escala mediante 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 } }

Fiddle usando escala

Con transformaciones aplicadas al contexto (escala, rotación, etc.)

Luego está el caso más complicado en el que ha aplicado la transformación al contexto, como rotación, sesgo / corte, escala, traslación, etc. Para resolver 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 propiedad currentTransform y Firefox (alfa actual) incluso proporcionan una matriz invertida a través de mozCurrentTransformInverted . Sin embargo, Firefox, a través de mozCurrentTransform , devolverá una matriz y no DOMMatrix como debería. Ni Chrome, cuando se habilita mediante indicadores experimentales, devolverá una DOMMatrix sino una SVGMatrix .

Sin embargo, en la mayoría de los casos tendrá que implementar una solución de matriz personalizada (como mi propia solución here - proyecto libre / 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. Las coordenadas se pasan luego al lienzo, que usará su matriz para convertirlo a donde sea que esté en este momento.

De esta forma, el punto estará en la posición correcta relativa al mouse. También aquí necesita 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); }

Ejemplo de uso de la solución vinculada anteriormente (reemplace con la solución de navegador nativo cuando sea más compatible).

Un ejemplo de uso de 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;

Actualización: Hice una solución gratuita (MIT) para incorporar todos estos pasos en un solo objeto fácil de usar que se puede encontrar here y también se ocupa de algunos otros aspectos esenciales que la mayoría ignora.

Intento dibujar con el mouse sobre un lienzo HTML5, pero la única forma en que parece funcionar bien es si el lienzo está en la posición 0,0 (esquina superior izquierda) si cambio la posición del lienzo, por alguna razón no dibuja como debería. Aquí está mi código.

function createImageOnCanvas(imageId){ document.getElementById("imgCanvas").style.display = "block"; document.getElementById("images").style.overflowY= "hidden"; var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); var img = new Image(300,300); img.src = document.getElementById(imageId).src; context.drawImage(img, (0),(0)); } function draw(e){ var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); posx = e.clientX; posy = e.clientY; context.fillStyle = "#000000"; context.fillRect (posx, posy, 4, 4); }

La parte HTML

<body> <div id="images"> </div> <canvas onmousemove="draw(event)" style="margin:0;padding:0;" id="imgCanvas" class="canvasView" width="250" height="250"></canvas>

He leído que hay una manera de crear una función simple en JavaScript para obtener la posición correcta, pero no tengo idea de cómo hacerlo.


La forma más fácil de calcular la posición correcta para mover el mouse o el mouse en un evento canvas es usar esta pequeña ecuación:

canvas.addEventListener(''click'', event => { let bound = canvas.getBoundingClientRect(); let x = event.clientX - bound.left - canvas.clientLeft; let y = event.clientY - bound.top - canvas.clientTop; context.fillRect(x, y, 16, 16); });

Si el lienzo tiene relleno-left o relleno-top , reste xey a través de:

x -= parseFloat(style[''padding-left''].replace(''px''));
y -= parseFloat(style[''padding-top''].replace(''px''));


Necesita obtener la posición del mouse relativa al lienzo

Para hacerlo, 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 quieres usar JavaScript sin formato, Google también lo obtendrá).

var canvasOffset=$("#canvas").offset(); var offsetX=canvasOffset.left; var offsetY=canvasOffset.top;

Luego, en su controlador de 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 violín que muestra cómo seguir con éxito los eventos del mouse en el lienzo:

http://jsfiddle.net/m1erickson/WB7Zu/

<!doctype html> <html> <head> <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> <style> body{ background-color: ivory; } canvas{border:1px solid red;} </style> <script> $(function(){ var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var canvasOffset=$("#canvas").offset(); var offsetX=canvasOffset.left; var offsetY=canvasOffset.top; function handleMouseDown(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#downlog").html("Down: "+ mouseX + " / " + mouseY); // Put your mousedown stuff here } function handleMouseUp(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#uplog").html("Up: "+ mouseX + " / " + mouseY); // Put your mouseup stuff here } function handleMouseOut(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#outlog").html("Out: "+ mouseX + " / " + mouseY); // Put your mouseOut stuff here } function handleMouseMove(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#movelog").html("Move: "+ mouseX + " / " + mouseY); // Put your mousemove stuff here } $("#canvas").mousedown(function(e){handleMouseDown(e);}); $("#canvas").mousemove(function(e){handleMouseMove(e);}); $("#canvas").mouseup(function(e){handleMouseUp(e);}); $("#canvas").mouseout(function(e){handleMouseOut(e);}); }); // end $(function(){}); </script> </head> <body> <p>Move, press and release the mouse</p> <p id="downlog">Down</p> <p id="movelog">Move</p> <p id="uplog">Up</p> <p id="outlog">Out</p> <canvas id="canvas" width=300 height=300></canvas> </body> </html>


Puedes obtener las posiciones del mouse con 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 ) como el escalado cuando el tamaño lógico del lienzo difiere del tamaño del estilo ( / (rect.right - rect.left) * canvas.width ver: Ancho del lienzo y altura en HTML5 ).

Ejemplo: http://jsfiddle.net/sierawski/4xezb7nL/

Fuente: jerryj comentario en http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/