posicion mover mostrar event div coordenadas coordenada con javascript canvas

javascript - mover - ¿Cómo obtengo las coordenadas de un clic del mouse en un elemento del lienzo?



mover un div con el mouse javascript (19)

Aquí hay algunas modificaciones de la solución anterior de Ryan Artecona.

function myGetPxStyle(e,p) { var r=window.getComputedStyle?window.getComputedStyle(e,null)[p]:""; return parseFloat(r); } function myGetClick=function(ev) { // {x:ev.layerX,y:ev.layerY} doesn''t work when zooming with mac chrome 27 // {x:ev.clientX,y:ev.clientY} not supported by mac firefox 21 // document.body.scrollLeft and document.body.scrollTop seem required when scrolling on iPad // html is not an offsetParent of body but can have non null offsetX or offsetY (case of wordpress 3.5.1 admin pages for instance) // html.offsetX and html.offsetY don''t work with mac firefox 21 var offsetX=0,offsetY=0,e=this,x,y; var htmls=document.getElementsByTagName("html"),html=(htmls?htmls[0]:0); do { offsetX+=e.offsetLeft-e.scrollLeft; offsetY+=e.offsetTop-e.scrollTop; } while (e=e.offsetParent); if (html) { offsetX+=myGetPxStyle(html,"marginLeft"); offsetY+=myGetPxStyle(html,"marginTop"); } x=ev.pageX-offsetX-document.body.scrollLeft; y=ev.pageY-offsetY-document.body.scrollTop; return {x:x,y:y}; }

¿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 x e y del clic (con relación al elemento de lienzo)?

No se requiere compatibilidad con el navegador heredado, Safari, Opera y Firefox lo harán.


Aquí hay un tutorial muy bonito-

http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/

<canvas id="myCanvas" width="578" height="200"></canvas> <script> function writeMessage(canvas, message) { var context = canvas.getContext(''2d''); context.clearRect(0, 0, canvas.width, canvas.height); context.font = ''18pt Calibri''; context.fillStyle = ''black''; context.fillText(message, 10, 25); } function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: evt.clientX - rect.left, y: evt.clientY - rect.top }; } var canvas = document.getElementById(''myCanvas''); var context = canvas.getContext(''2d''); canvas.addEventListener(''mousemove'', function(evt) { var mousePos = getMousePos(canvas, evt); var message = ''Mouse position: '' + mousePos.x + '','' + mousePos.y; writeMessage(canvas, message); }, false);

¡espero que esto ayude!


Aquí hay una pequeña modificación a la respuesta de Ryan Artecona para los lienzos con un ancho variable (%):

HTMLCanvasElement.prototype.relMouseCoords = function (event) { var totalOffsetX = 0; var totalOffsetY = 0; var canvasX = 0; var canvasY = 0; var currentElement = this; do { totalOffsetX += currentElement.offsetLeft; totalOffsetY += currentElement.offsetTop; } while (currentElement = currentElement.offsetParent) canvasX = event.pageX - totalOffsetX; canvasY = event.pageY - totalOffsetY; // Fix for variable canvas width canvasX = Math.round( canvasX * (this.width / this.offsetWidth) ); canvasY = Math.round( canvasY * (this.height / this.offsetHeight) ); return {x:canvasX, y:canvasY} }


Consulte la demostración en http://jsbin.com/ApuJOSA/1/edit?html,output .

function mousePositionOnCanvas(e) { var el=e.target, c=el; var scaleX = c.width/c.offsetWidth || 1; var scaleY = c.height/c.offsetHeight || 1; if (!isNaN(e.offsetX)) return { x:e.offsetX*scaleX, y:e.offsetY*scaleY }; var x=e.pageX, y=e.pageY; do { x -= el.offsetLeft; y -= el.offsetTop; el = el.offsetParent; } while (el); return { x: x*scaleX, y: y*scaleY }; }


De acuerdo con el nuevo Quirksmode los métodos clientX y clientY son compatibles con todos los principales navegadores. Entonces, aquí va: el buen código de trabajo que funciona en un div de desplazamiento en una página con barras de desplazamiento:

function getCursorPosition(canvas, event) { var x, y; canoffset = $(canvas).offset(); x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft - Math.floor(canoffset.left); y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop - Math.floor(canoffset.top) + 1; return [x,y]; }

Esto también requiere jQuery para $(canvas).offset() .


El navegador moderno ahora maneja esto por ti. Chrome, IE9 y Firefox admiten el offsetX / Y así, 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 no lo hicieron no existen previamente. Por lo tanto, para la compatibilidad con navegadores ligeramente más antiguos, puede utilizar:

function getRelativeCoords(event) { return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY }; }



Hice una demostración completa que funciona en todos los navegadores con el código fuente completo de la solución de este problema: Coordenadas de un clic del mouse en Canvas en Javascript . Para probar la demostración, copie el código y péguelo en un editor de texto. Luego guárdelo como example.html y, finalmente, abra el archivo con un navegador.


No estoy seguro de cuál es el punto de todas estas respuestas que recorren los elementos principales y hacen todo tipo de cosas extrañas .

El método HTMLElement.getBoundingClientRect está diseñado para manejar la posición real de la pantalla de cualquier elemento. Esto incluye el desplazamiento, por lo que no se necesitan elementos como scrollTop :

(desde MDN) La cantidad de desplazamiento que se ha realizado en el área de la ventana gráfica (o en cualquier otro elemento desplazable ) se tiene en cuenta al calcular el rectángulo delimitador

Imagen normal

El enfoque más simple ya fue publicado aquí. Esto es correcto siempre que no haya reglas de CSS salvajes .

Manipulación de lienzo estirado / imagen.

Cuando el ancho de píxeles de la imagen no coincide con el ancho de CSS, deberá aplicar cierta proporción en los valores de píxeles:

/* Returns pixel coordinates according to the pixel that''s under the mouse cursor**/ HTMLCanvasElement.prototype.relativeCoords = function(event) { var x,y; //This is the current screen rectangle of canvas var rect = this.getBoundingClientRect(); var top = rect.top; var bottom = rect.bottom; var left = rect.left; var right = rect.right; //Recalculate mouse offsets to relative offsets x = event.clientX - left; y = event.clientY - top; //Also recalculate offsets of canvas is stretched var width = right - left; //I use this to reduce number of calculations for images that have normal size if(this.width!=width) { var height = bottom - top; //changes coordinates by ratio x = x*(this.width/width); y = y*(this.height/height); } //Return as an array return [x,y]; }

Mientras el lienzo no tenga borde, funciona para imágenes estiradas (jsFiddle) .

Manejo de bordes CSS

Si el lienzo tiene borde grueso, las cosas se complican un poco . Literalmente necesitarás restar el borde del rectángulo delimitador. Esto se puede hacer usando .getComputedStyle . Esta respuesta describe el proceso .

La función entonces crece un poco:

/* Returns pixel coordinates according to the pixel that''s under the mouse cursor**/ HTMLCanvasElement.prototype.relativeCoords = function(event) { var x,y; //This is the current screen rectangle of canvas var rect = this.getBoundingClientRect(); var top = rect.top; var bottom = rect.bottom; var left = rect.left; var right = rect.right; //Subtract border size // Get computed style var styling=getComputedStyle(this,null); // Turn the border widths in integers var topBorder=parseInt(styling.getPropertyValue(''border-top-width''),10); var rightBorder=parseInt(styling.getPropertyValue(''border-right-width''),10); var bottomBorder=parseInt(styling.getPropertyValue(''border-bottom-width''),10); var leftBorder=parseInt(styling.getPropertyValue(''border-left-width''),10); //Subtract border from rectangle left+=leftBorder; right-=rightBorder; top+=topBorder; bottom-=bottomBorder; //Proceed as usual ... }

No puedo pensar en nada que pueda confundir esta función final. Véase a sí mismo en JsFiddle .

Notas

Si no te gusta modificar los prototype nativos, simplemente cambia la función y llámala con (canvas, event) (y reemplaza this con canvas ).


Oye, esto está en dojo, solo porque es lo que ya tenía el código para un proyecto.

Debería ser bastante obvio cómo convertirlo de nuevo a JavaScript de dojo vanilla.

function onMouseClick(e) { var x = e.clientX; var y = e.clientY; } var canvas = dojo.byId(canvasId); dojo.connect(canvas,"click",onMouseClick);

Espero que ayude.


Primero, como han dicho otros, necesita una función para obtener la posición del elemento de lienzo . Aquí hay un método que es un poco más elegante que algunos de los otros en esta página (IMHO). Puedes pasarle cualquier elemento y obtener su posición en el documento:

function findPos(obj) { var curleft = 0, curtop = 0; if (obj.offsetParent) { do { curleft += obj.offsetLeft; curtop += obj.offsetTop; } while (obj = obj.offsetParent); return { x: curleft, y: curtop }; } return undefined; }

Ahora calcule la posición actual del cursor relativa a eso:

$(''#canvas'').mousemove(function(e) { var pos = findPos(this); var x = e.pageX - pos.x; var y = e.pageY - pos.y; var coordinateDisplay = "x=" + x + ", y=" + y; writeCoordinateDisplay(coordinateDisplay); });

Observe que he separado la función findPos genérica del código de manejo de eventos. ( Como debería ser . Deberíamos intentar mantener nuestras funciones para una tarea cada una).

Los valores de offsetLeft y offsetTop son relativos a offsetParent , lo que podría ser un nodo div contenedor (o cualquier otra cosa, para el caso). Cuando no hay ningún elemento que envuelva el canvas , son relativos al body , por lo que no hay desplazamiento que restar. Es por esto que necesitamos determinar la posición del lienzo antes de poder hacer cualquier otra cosa.

De manera similar, e.pageX y e.pageY dan la posición del cursor relativa al documento. Es por eso que restamos el desplazamiento del lienzo de esos valores para llegar a la posición verdadera.

Una alternativa para los elementos posicionados es usar directamente los valores de e.layerX y e.layerY . Esto es menos confiable que el método anterior por dos razones:

  1. Estos valores también son relativos a todo el documento cuando el evento no tiene lugar dentro de un elemento posicionado
  2. No forman parte de ninguna norma.

Recomiendo este enlace: http://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html

<style type="text/css"> #canvas{background-color: #000;} </style> <script type="text/javascript"> document.addEventListener("DOMContentLoaded", init, false); function init() { var canvas = document.getElementById("canvas"); canvas.addEventListener("mousedown", getPosition, false); } function getPosition(event) { var x = new Number(); var y = new Number(); var canvas = document.getElementById("canvas"); if (event.x != undefined && event.y != undefined) { x = event.x; y = event.y; } else // Firefox method to get the position { x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; } x -= canvas.offsetLeft; y -= canvas.offsetTop; alert("x: " + x + " y: " + y); } </script>


Si le gusta la simplicidad pero aún desea la funcionalidad de navegador cruzado, 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) { var rect = canvas.getBoundingClientRect(); var x = event.clientX - rect.left; var y = event.clientY - rect.top; console.log("x: " + x + " y: " + y); }


Tenga cuidado al hacer la conversión de coordenadas; hay varios valores que no son de navegador cruzado devueltos en un evento de clic. El uso de clientX y clientY por sí solo no es suficiente si la ventana del navegador está desplazada (verificada en Firefox 3.5 y Chrome 3.0).

Este artículo sobre el modo de peculiaridades proporciona una función más correcta que puede usar pageX o pageY o una combinación de clientX con document.body.scrollLeft y clientY con document.body.scrollTop para calcular la coordenada de clic relativa al origen del documento.

ACTUALIZACIÓN: Además, offsetLeft y offsetTop son relativos al tamaño acolchado del elemento, no al tamaño interior. Un lienzo con el relleno: estilo aplicado no informará la parte superior izquierda de su región de contenido como offsetLeft. Hay varias soluciones a este problema; El más simple puede ser borrar todos los estilos de borde, relleno, etc. en el lienzo mismo y, en su lugar, aplicarlos a un cuadro que contenga el lienzo.


ThreeJS r77

var x = event.offsetX == undefined ? event.layerX : event.offsetX; var y = event.offsetY == undefined ? event.layerY : event.offsetY; mouse2D.x = ( x / renderer.domElement.width ) * 2 - 1; mouse2D.y = - ( y / renderer.domElement.height ) * 2 + 1;

Después de probar muchas soluciones. Esto funcionó para mí. Podría ayudar a alguien más por lo tanto publicar. Lo tengo desde here


Usando jQuery en 2016, para obtener las coordenadas de clic relativas al lienzo, hago:

$(canvas).click(function(jqEvent) { var coords = { x: jqEvent.pageX - $(canvas).offset().left, y: jqEvent.pageY - $(canvas).offset().top }; });

Esto funciona ya que tanto el offset de lienzo () como jqEvent.pageX / Y son relativos al documento independientemente de la posición de desplazamiento.

Tenga en cuenta que si se escala el lienzo, estas coordenadas no son las mismas que las coordenadas lógicas del lienzo. Para conseguirlos, también harías:

var logicalCoords = { x: coords.x * (canvas.width / $(canvas).width()), y: coords.y * (canvas.height / $(canvas).height()) }


Usted podría simplemente hacer:

var canvas = yourCanvasElement; var mouseX = (event.clientX - (canvas.offsetLeft - canvas.scrollLeft)) - 2; var mouseY = (event.clientY - (canvas.offsetTop - canvas.scrollTop)) - 2;

Esto le dará la posición exacta del puntero del ratón.


Actualización (5/5/16): la respuesta de los patriques debería usarse en su lugar, ya que es más simple y más confiable.

Dado que el lienzo no siempre tiene un estilo relativo a toda la página, el 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 elemento div que contiene el lienzo con una position: relative estilo position: relative aplicado. Para tener en cuenta esto, debe recorrer la cadena de offsetParent s, comenzando con el propio elemento de 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 las cosas convenientes para obtener las coordenadas del mouse en relación con un elemento de 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 los navegadores antiguos que ya no son necesarios, ya que las propiedades clientX y clientY funcionan en todos los navegadores actuales. Es posible que desee revisar Patriques Answer para obtener una solución más simple y reciente.

Respuesta original:
Como se describe en un artículo que encontré en aquel entonces pero 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í.