Riwall Riwall - 1 year ago 78
Javascript Question

Mouse position inside autoscaled SVG

I am experiencing troubles concerning the position of mouse cursor inside my SVG document. I'd like to design a potentiometer that will follow the cursor when dragged, using JavaScript in an HTML page.

I tried evt.clientX/Y and evt.screenX/Y but as my SVG is in autoscale, coordinates inside my SVG are different. I have been searching for an answer for days now but I couldn't find any solution (either knowing my SVG rescaling factor in real time or have a function for mouse location in SVG coordinates system).

The rotation will follow a simple rule:

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;

With (xc;yc) as center of rotation and replacing all evt.screenX/Y by the coordinates of the mouse inside my SVG.

Answer Source

See this code, which not only shows how to transform from screen space to global SVG space, but also how to transform a point from SVG space into the transformed space of an element:

In short:

// 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());

  var loc = cursorPoint(evt);
  // Use loc.x and loc.y here

Edit: I've created a sample tailored to your needs (albeit only in global SVG space):

It adds the following method to the above:

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