La posición del ratón en SVG

facebook-svg gplus-svg twitter-svg

Para encontrar la posición del ratón encima del lienzo SVG podemos utilizar la siguiente función :


function oMousePos(svg, evt) {
      var ClientRect = svg.getBoundingClientRect();
                return { //objeto
                x: Math.round(evt.clientX - ClientRect.left),
                y: Math.round(evt.clientY - ClientRect.top)
      }
}

Esta función puede ser útil si el tamaño del lienzo SVG coincide con el tamaño del contenido de este ( viewBox ):

<svg width = "400" height="200" viewBox="0 0 400 200"  >. . . </svg>

El problema es que SVG significa gráficos vectoriales expandibles, y por lo tanto el tamaño del lienzo no coincide casi nunca con el tamaño del contenido.
Imagínese un elemento SVG cuya anchura es igual a la anchura del elemento padre.

<svg width = "100%" viewBox="0 0 400 200"  >. . . </svg>

En una página web adaptativa ( responsive ) el tamaño del elemento SVG varía, pero no su contenido cuya anchura se queda siempre 400 unidades de usuario o píxeles. En este caso necesitamos una manera de detectar la posición del ratón en función de las coordenadas del contenido.

Detectar la posición del ratón

Sin más preámbulos esta es la función que vamos a utilizar para detectar la posición del ratón encima de un lienzo SVG:


function oMousePosSVG(evento) {
      var p = svg.createSVGPoint();
      p.x = evento.clientX;
      p.y = evento.clientY;
      var ctm = svg.getScreenCTM().inverse();
      var p =  p.matrixTransform(ctm);
      return p;
}
La explicación del código:

Primero creamos un nuevo punto SVG:

var point = svg.createSVGPoint();

En JavaScript el método createSVGPoint() crea un nuevo objeto SVGPoint inicializado en el origen ( esquina izquierda arriba ) del lienzo SVG.

var p = svg.createSVGPoint();

Queremos que este punto represente la posición del ratón:

p.x = evento.clientX;
p.y = evento.clientY;

El nuevo punto creado tiene asociado el método matrixTransform() que aplica una matriz de transformación de tipo  2*3 y devuelve el nuevo punto transformado.

p = p.matrixTransform(ctm);

Para obtener la matriz de transformación necesaria ( ctm ) utilizamos el método getScreenCTM()

var ctm = svg.getScreenCTM().inverse();

La función devuelve el nuevo punto transformado:

return p
Un ejemplo básico

En este ejemplo utilizamos el método addEventListener() para registrar el movimiento del ratón ( mousemove ) encima del lienzo SVG. La función oMousePosSVG() detecta la posición del ratón y la saca en pantalla como innerHTML del elemento #salida.

See the Pen La posición del ratón en SVG* by Gabi (@enxaneta) on CodePen.