CyberAlby
CyberAlby

Reputation: 23

Svg viewbox doesn't return correct mouse points with nested svg in Firefox

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

Answers (1)

Robert Longson
Robert Longson

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

Related Questions