over onmouse eventos ejemplo div javascript svg

javascript - eventos - onmouseover css



PosiciĆ³n del mouse dentro de SVG autoescalado (3)

Tengo problemas relacionados con la posición del cursor del mouse dentro de mi documento SVG. Me gustaría diseñar un potenciómetro que siga al cursor cuando se lo arrastre, utilizando JavaScript en una página HTML.

Intenté evt.clientX / Y y evt.screenX / Y pero como mi SVG está en autoescala , las coordenadas dentro de mi SVG son diferentes. He estado buscando una respuesta por varios días, pero no encontré ninguna solución (ya sea conocer mi factor de reescritura SVG en tiempo real o tener una función para la ubicación del mouse en el sistema de coordenadas SVG).

La rotación seguirá una regla simple:

if (evt.screenX <xc)

ang = Math.atan ((evt.screenY - yc) / (evt.screenX - xc)) * 360 / (2 * Math.PI) - 90;
if (evt.screenX> xc)
ang = Math.atan ((evt.screenY - yc) / (evt.screenX - xc)) * 360 / (2 * Math.PI) + 90;

Con (xc; yc) como centro de rotación y reemplazando todo evt.screenX / Y por las coordenadas del mouse dentro de mi SVG.


@Phrogz: Gracias por su maravilloso ejemplo y aprendí de eso. He cambiado un poco como a continuación para que sea un poco fácil. Como pienso que al igual que manejamos eventos de mouse en core java también podemos manejarlo de la misma manera aquí, así que intenté mi camino en tu ejemplo.

He eliminado la función "rotarElemento" ya que creo que es un poco difícil y encuentro un sustituto si lo hace.

Vea el siguiente código:

var svg=document.getElementById("svg1"); var pt=svg.createSVGPoint(); var end_small=document.getElementById("end_small"); var line=document.getElementById("line1"); end_small.addEventListener(''mousemove'', function(evt) { var loc=getCursor(evt); end_small.setAttribute("cx",loc.x); end_small.setAttribute("cy",loc.y); loc = getCursor(evt); // will get each x,y for mouse move line.setAttribute(''x2'',loc.x); // apply it as end points of line line.setAttribute(''y2'',loc.y); // apply it as end points of line }, false); function getCursor(evt) { pt.x=evt.clientX; pt.y=evt.clientY; return pt.matrixTransform(svg.getScreenCTM().inverse()); }

Entonces, lo que he hecho es que acabo de agregar listener solo a un círculo pequeño, no a un SVG completo y cada vez que el mouse se movió cerca de ti obtendré x, y de la función getCursor() como se indicó anteriormente y daré x, y como x2, y2 de mi línea, eso no se traduce y no gira. Debes mover tu mouse hacia un círculo y luego moverlo lentamente y si tu mouse deja el círculo, la línea no se moverá, ya que acabamos de agregar el oyente solo en un pequeño círculo a la derecha.


Obtener la correcta coordenada del mouse svg es complicado. En primer lugar, una forma común es usar el clienteX y el clienteY de la propiedad del evento y restarlo con getBoundingClientRect () y clientLeft respectivamente clientTop.

svg.addEventListener(''click'', event => { let bound = svg.getBoundingClientRect(); let x = event.clientX - bound.left - svg.clientLeft - paddingLeft; let y = event.clientY - bound.top - svg.clientTop - paddingTop; }

Pero , si el svg tiene una información de estilo de relleno mayor que cero, la coordenada está cambiando. Entonces esta información también debe ser substraída:

let paddingLeft = parseFloat(style[''padding-left''].replace(''px'', '''')); let paddingTop = parseFloat(style[''padding-top''].replace(''px'', '''')); let x = event.clientX - bound.left - svg.clientLeft - paddingLeft; let y = event.clientY - bound.top - svg.clientTop - paddingTop;

Y no es tan agradable pensar que, en algunos navegadores, la propiedad de frontera también cambie la coordenada, y en otros no. Descubrí que el cambio tiene lugar si la xey de la propiedad del evento no está disponible.

if(event.x === undefined) { x -= parseFloat(style[''border-left-width''].replace(''px'', '''')); y -= parseFloat(style[''border-top-width''].replace(''px'', '''')); }

Después de esta transformación, la coordenada xey puede salir de límite, eso debería arreglarse. Pero eso no es lo que piensas.

let width = svg.width.baseVal.value; let height = svg.height.baseVal.value; if(x < 0 || y < 0 || x >= width || y >= height) { return; }

Esta solución puede usarse para hacer clic, mousemove, mousedown, ... y así sucesivamente. Puede acceder a una demostración en vivo aquí: https://codepen.io/martinwantke/pen/xpGpZB


Vea este código, que no solo muestra cómo transformar el espacio de la pantalla al espacio SVG global, sino también cómo transformar un punto del espacio SVG en el espacio transformado de un elemento:
http://phrogz.net/svg/drag_under_transformation.xhtml

En breve:

// Find your root SVG element var svg = document.querySelector(''svg''); // Create an SVGPoint for future math var pt = svg.createSVGPoint(); // Get point in global SVG space function cursorPoint(evt){ pt.x = evt.clientX; pt.y = evt.clientY; return pt.matrixTransform(svg.getScreenCTM().inverse()); } svg.addEventListener(''mousemove'',function(evt){ var loc = cursorPoint(evt); // Use loc.x and loc.y here },false);

Editar : He creado una muestra adaptada a sus necesidades (aunque solo en el espacio SVG global):
http://phrogz.net/svg/rotate-to-point-at-cursor.svg

Agrega el siguiente método a lo anterior:

function rotateElement(el,originX,originY,towardsX,towardsY){ var angle = Math.atan2(towardsY-originY,towardsX-originX); var degrees = angle*180/Math.PI + 90; el.setAttribute( ''transform'', ''translate(''+originX+'',''+originY+'') '' + ''rotate(''+degrees+'') '' + ''translate(''+(-originX)+'',''+(-originY)+'')'' ); }