Reputation: 23
I've little problem with Firefox v25 when I try to get mouse position. FF don't return correct position when I use 2 svg nested, but in Chrome and IE10 work fine.
This is an example: http://jsfiddle.net/LwZFb/
<div class="position">
<div>client position <span id="clientPosition"></span></div>
<div>svg position <span id="svgPosition"></span></div>
</div>
<svg id="test1" version="1.1" viewBox="0 0 500 500" width="500px" height="500px">
<svg id="testSVG" preserveAspectRatio="none" version="1.1" viewBox="0 0 1000 1000" width="500px" height="500px">
<rect fill="papayaWhip" x="250" y="250" width="500" height="500"/>
<text x="225" y="240">250/250</text>
<text x="725" y="240">750/250</text>
<text x="225" y="775">250/750</text>
<text x="725" y="775">750/750</text>
<rect id="followMe" fill="peachPuff" stroke="crimson" width="20" height="20"/>
</svg>
</svg>
and the js code for to get the position:
var svgElement = document.getElementById('testSVG'),
followRectElement = document.getElementById('followMe'),
clientPositionElement = document.getElementById('clientPosition'),
svgPositionElement = document.getElementById('svgPosition');
window.addEventListener('mousemove', function(mouseEvent) {
var svgPoint = svgElement.createSVGPoint();
svgPoint.x = mouseEvent.clientX;
svgPoint.y = mouseEvent.clientY;
svgPoint = svgPoint.matrixTransform(svgElement.getScreenCTM().inverse());
clientPositionElement.innerHTML = [ mouseEvent.clientX, mouseEvent.clientY ].join('/');
svgPositionElement.innerHTML = [ svgPoint.x, svgPoint.y ].join('/');
followRectElement.setAttribute('x', svgPoint.x - 10);
followRectElement.setAttribute('y', svgPoint.y - 10);
});
Upvotes: 2
Views: 1090
Reputation: 124059
Ahh but Firefox does give the right location, the other browsers and your algorithm are the issue. This is the problem line...
svgPoint = svgPoint.matrixTransform(svgElement.getScreenCTM().inverse());
The svgElement is in a different co-ordinate system to the svgPoint as the svgElement has a viewBox and viewBox transforms only apply to descendants and not to the element itself Unfortunately IE and Chrome don't adhere to the SVG specification here which causes much confusion.
Instead of the above line you could write this instead
svgPoint = svgPoint.matrixTransform(followRectElement.getScreenCTM().inverse());
as the followRectElement is in the co-ordinate system you want, a solution which will work cross browser.
Upvotes: 3