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.
Getting the correct svg mouse coordinate is tricky. First of all, a common way is to use the clientX and clientY of the event property an substract it with getBoundingClientRect() and clientLeft respectively clientTop.
But, if the svg has a padding style information greater then zero, the coordinate is shifting. So this information must be also substract:
And the not so nice think is, that in some browsers the border property also shift the coordinate, and in other not. I found out, that the shift takes place if the x and y of the event property is not available.
After this transformation the x and y coordinate can out of bound, that should be fix. But that not the think.
This solution can use for click, mousemove, mousedown, ... and so on. You can reach a live demo here: https://codepen.io/martinwantke/pen/xpGpZB
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:
http://phrogz.net/svg/drag_under_transformation.xhtml
In short:
Edit: I've created a sample tailored to your needs (albeit only in global SVG space):
http://phrogz.net/svg/rotate-to-point-at-cursor.svg
It adds the following method to the above:
@Phrogz: Thanks for your wonderful example and I learned from that. I have changed some of it like below to make it a bit easy right. As I thinking that like we handle mouse events in core java we can also handle same way here so I tried my way in your example.
I have removed "rotateElement" function as I think that it is some difficult and i find a substitute if it.
See below code:
So what I have done is I have just added listener only to small circle not whole SVG and everytime when mouse moved by you I will get
x, y
fromgetCursor()
function as stated above and I will give thisx, y
asx2, y2
of my line thats it does not translate and does not rotate. You must move your mouse to to circle and then slowly move and if your mouse leave circle then line will not move as we have just added listener only on small circle right.