I have a div containing an SVG image of 300x300 px and a viewbox of 1000x1000.
The image describes a blue rectangle on top of a red one.
When I move the mouse a circle is following the mouse position inside the image:
Everything is perfect except that when I apply a transformation changing perspective and rotation, the mouse pointer and circle center are not anymore matching:
Code is here:
$(function() {
$('#image').mousemove(function(event) {
var svg = document.querySelector('svg');
var pt = svg.createSVGPoint();
pt.x = event.clientX;
pt.y = event.clientY;
pt = pt.matrixTransform(svg.getScreenCTM().inverse());
overlay = document.getElementById('overlay');
$('#overlay').html(
"<circle cx='" + pt.x + "' cy='" + pt.y + "' r='50' stroke='#8f00ff' fill='transparent' stroke-width='10' /></svg>"
);
refresh = $("#overlay").html();
$("#overlay").html( refresh )
});
});
function Transform() {
$('#image').css({
transformOrigin: '500px 500px',
transform: 'perspective(100px) rotateX(5deg)'
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='image' tabindex='0' >
<svg id='svgmap' width='300' height='300' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 1000 1000'>
<rect x='0' y='0' width='1000' height='1000' fill='red' />
<rect x='250' y='250' width='500' height='500' stroke='yellow' fill='blue' stroke-width='10' />
<g id='overlay'></g>
</svg>
</div>
<button onclick='Transform()'>Transform</button>
My goal is to preserver matching between the purple circle center and the mouse pointer, even when a transformation is applied to the object.
Is there a way to do it?
In your code #image is a div. In order to make it work you need to apply the transformation to the svg element (#svgmap) and the transformation must be an svg transformation.
$(function() {
$('#svgmap').mousemove(function(event) {
var svg = document.querySelector('svg');
var pt = svg.createSVGPoint();
pt.x = event.clientX;
pt.y = event.clientY;
pt = pt.matrixTransform(svg.getScreenCTM().inverse());
overlay = document.getElementById('overlay');
$('#overlay').html(
"<circle cx='" + pt.x + "' cy='" + pt.y + "' r='50' stroke='#8f00ff' fill='transparent' stroke-width='10' /></svg>"
);
refresh = $("#layer_wafer").html();
$("#layer_wafer").html( refresh )
});
});
function Transform() {
svgmap.setAttributeNS(null,"transform", "skewX(-20) translate(100)");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='image' tabindex='0' >
<svg id='svgmap' width='300' height='300' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 1000 1000' transform="">
<rect x='0' y='0' width='1000' height='1000' fill='red' />
<rect x='250' y='250' width='500' height='500' stroke='yellow' fill='blue' stroke-width='10' />
<g id='overlay'></g>
</svg>
</div>
<button onclick='Transform()'>Transform</button>
I understand that you are needing a 3D css transformation but this (at least for now) doesn't work.
This is an article where you can read more about 3d transforms in svg: https://oreillymedia.github.io/Using_SVG/extras/ch11-3d.html In the article you can read: All the 3D transformation functions described in this section should be considered “future”
I've solved the issue in the ugliest possible way. Simply hiding the mouse cursor over the div.
Ugly. But effective.
$(function() {
$('#image').mousemove(function(event) {
var svg = document.querySelector('svg');
var pt = svg.createSVGPoint();
pt.x = event.clientX;
pt.y = event.clientY;
pt = pt.matrixTransform(svg.getScreenCTM().inverse());
overlay = document.getElementById('overlay');
$('#overlay').html(
"<circle cx='" + pt.x + "' cy='" + pt.y + "' r='50' stroke='#8f00ff' fill='transparent' stroke-width='10' /></svg>"
);
refresh = $("#overlay").html();
$("#overlay").html( refresh )
});
});
function Transform() {
$('#image').css({
transformOrigin: '500px 500px',
transform: 'perspective(100px) rotateX(5deg)'
});
}
div#image {
cursor: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='image' tabindex='0' >
<svg id='svgmap' width='300' height='300' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 1000 1000'>
<rect x='0' y='0' width='1000' height='1000' fill='red' />
<rect x='250' y='250' width='500' height='500' stroke='yellow' fill='blue' stroke-width='10' />
<g id='overlay'></g>
</svg>
</div>
<button onclick='Transform()'>Transform</button>
There's a little bit of optimization that I have to do to reduce the mouse cursor position gap between the DIV over and any other page element, but it's acceptable to me.
Related
I have a usecase where designers supply us with a SVG, and we use certain elements in that SVG to position our dynamically created elements.
In the snippet below I try to overlap the rect#overlayTarget with the div#overlay using getBoundingClientRect: it doesn't take the scaling of the parent element into account, and the elements don't overlap.
The answers from this question is not applicable here as it uses element.offsetLeft and element.offsetTop, which aren't available for SVG: How to compute getBoundingClientRect() without considering transforms?
How do I make the #overlay and #overlayTarget overlap?
const target = document.querySelector("#overlayTarget");
const position = target.getBoundingClientRect();
const overlay = document.querySelector("#overlay");
overlay.style.top = `${position.y}px`;
overlay.style.left = `${position.x}px`;
overlay.style.width = `${position.width}px`;
overlay.style.height = `${position.height}px`;
#overlay {
position: absolute;
background: hotpink;
opacity: 0.3;
width: 100px;
height: 100px;
}
<div id="app" style="transform: scale(0.875);">
Test
<div id="overlay"></div>
<svg xmlns="http://www.w3.org/2000/svg" width="1809" height="826" viewBox="0 0 809 826">
<g
id="Main_overview"
data-name="Main overview"
transform="translate(-49.5 -155)"
>
<g
id="overlayTarget"
data-name="DC-DC converter"
transform="translate(400 512)"
>
<rect
id="Rectangle_29"
data-name="Rectangle 29"
width="74"
height="74"
fill="none"
stroke="#47516c"
stroke-width="2"
/>
</g>
</g>
</svg>
</div>
If you cannot set your overlay element outside of the transformed element, this answer will work, but only for some simple transformations:
translations and
scales with factors > 0
In these cases, the corners of the bounding box aren't moved out of their top/left and bottom/right orientation. Rotations or skews, and most of the 3D transforms won'T work out.
You can then compute the resulting box values for your overlay by transforming the corners of position with the inverse matrix to that set for the #app element. The DOMPoint and DOMMatrix interfaces help with that.
It is important to remember that transform sets an implicit position: relative, so the top and left values of the overlay are not in relation to the viewport.
const app = document.querySelector('#app');
const relative = app.getBoundingClientRect();
const target = document.querySelector("#overlayTarget");
const position = target.getBoundingClientRect();
const matrix = new DOMMatrix(app.style.transform).inverse();
const topleft = new DOMPoint(
position.x - relative.x,
position.y - relative.y
).matrixTransform(matrix);
const bottomright = new DOMPoint(
position.x - relative.x + position.width,
position.y - relative.y + position.height
).matrixTransform(matrix);
const overlay = document.querySelector("#overlay");
overlay.style.top = `${topleft.y}px`;
overlay.style.left = `${topleft.x}px`;
overlay.style.width = `${bottomright.x - topleft.x}px`;
overlay.style.height = `${bottomright.y - topleft.y}px`;
#overlay {
position: absolute;
background: hotpink;
opacity: 0.3;
width: 100px;
height: 100px;
}
<div id="app" style="transform: scale(0.875);">
Test
<div id="overlay"></div>
<svg xmlns="http://www.w3.org/2000/svg" width="1809" height="826" viewBox="0 0 809 826">
<g
id="Main_overview"
data-name="Main overview"
transform="translate(-49.5 -155)"
>
<g
id="overlayTarget"
data-name="DC-DC converter"
transform="translate(400 512)"
>
<rect
id="Rectangle_29"
data-name="Rectangle 29"
width="74"
height="74"
fill="none"
stroke="#47516c"
stroke-width="2"
/>
</g>
</g>
</svg>
</div>
I have a SVG-document that contains a circle. I would like to place an absolutely positioned html-element on top of this circle. The circle contains a cx and cy and there are several transforms on parent elements. How can I translate the position inside the SVG to the coordinate space of the parent html-element (normal pixels)?
The SVG is generated by a program, so I will have little control over it, meaning that I will need a general solution that can handle any number of transforms on parent element.
I'm not using d3 or any similar library, so I'm looking for a way to solve this using plain JavaScript. This is a simplified example of my problem:
<head>
<style>
#box {
background-color: greenyellow;
position: absolute;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div id="root">
<svg width="1274.2554" height="692.35712" id="svg">
<g id="viewport" transform="matrix(0.655937472561484,0,0,0.655937472561484,162.2578890186666,57.23719435833714)">
<g id="layer1" transform="translate(-5.49584,-171.51931)">
<g id="elem" transform="translate(34.862286,232.62127)">
<circle id="center" cx="19.952429" cy="19.90885" style="fill:#ffcc33" r="20"></circle>
</g>
</g>
</g>
</svg>
<div id="box" ></div>
</div>
<script>
function positionBoxAtCenter() {
var box = document.getElementById('box');
var center = document.getElementById(('center'));
// TODO: get x, y from 'center' so that 'box' can be placed on top of center
var x = 0, y = 0;
box.setAttribute('style', 'top: ' + y + 'px; left: ' + x + 'px');
}
</script>
</body>
JSFiddle: https://jsfiddle.net/p9pf56sz/
Using getBoundingClientRect():
var pos = center.getBoundingClientRect();
You can get the center of the circle:
var x = pos.left + pos.width/2, y = pos.top + pos.height/2;
Here is the demo:
function positionBoxAtCenter() {
var box = document.getElementById('box');
var center = document.getElementById(('center'));
var pos = center.getBoundingClientRect();
var x = pos.left + pos.width/2, y = pos.top + pos.height/2;
box.setAttribute('style', 'top: ' + y + 'px; left: ' + x + 'px');
}
positionBoxAtCenter();
#box {
background-color: greenyellow;
position: absolute;
width: 100px;
height: 100px;
}
<body>
<div id="root">
<svg width="1274.2554" height="692.35712" id="svg">
<g id="viewport" transform="matrix(0.655937472561484,0,0,0.655937472561484,162.2578890186666,57.23719435833714)">
<g id="layer1" transform="translate(-5.49584,-171.51931)">
<g id="elem" transform="translate(34.862286,232.62127)">
<circle id="center" cx="19.952429" cy="19.90885" style="fill:#ffcc33" r="20"></circle>
</g>
</g>
</g>
</svg>
<div id="box" ></div>
</div>
</body>
However, as you can see in the demo, you are moving the top/left corner of the rectangle (its origin) to the center of the circle. So, you'll have to calculate the center of the rectangle as well (and subtract its difference to the origin).
I am trying to get a color from an element on my screen after the initial color has been ran through -webkit-filter on the CSS. nd apply that color onto another element.
HTML
<div id="Div1" style="background-color: rgb(166,187,207);"></div>
<br>
<div id="Div2"></div>
CSS
#Div1{
height: 100px;
width: 100px;
-webkit-filter: saturate(5);
}
Javascript
var inDiv1 = document.getElementById("Div1");
var dColorx = inDiv1.style.backgroundColor;
var inDiv2 = document.getElementById("Div2");
inDiv2.innerHTML += '<svg width="400" height="110">'+
'<rect width="300" height="100" '+
'style="fill:'+ dColorx +';'+
'stroke-width:3;stroke:rgb(0,0,0)"></svg>';
I need the rect inside of Div2 to be the same color as Div1 currently.
Div1 default color rgb(166,187,207).
Div1 post filter color rgb(94,199,255). <-- need to get this color
I also used a RGB to HSL converters I've found on stackoverflow, but the colors were off by quite a bit. If I'm not making sense, I do apologize. I've been up all night trying to get this to work.
If anyone can help me it would greatly be appreciated!
Example: http://jsfiddle.net/JfKEL/
Not sure how you would get the colour after applying the filter exactly but you can use the same colour for your svg elements and re-apply the filter. Your svg output will be something like this:
<svg width="400" height="110">
<filter id="saturate">
<feColorMatrix in="SourceGraphic" type="saturate" values="5" />
</filter>
<g filter="url(#saturate)">
<rect width="300" height="100" '+ 'style="fill:'+ dColorx + '; stroke-width:3;stroke:rgb(0,0,0)">
</g>
</svg>
Working jsFiddle
With the help of the functions from this post you should be able to achieve what you want using the following:
var inDiv1 = document.getElementById("Div1");
var dColorx = inDiv1.style.backgroundColor.replace(/[^0-9$,]/g, '').split(',');
var hsl= rgbToHsl(dColorx[0], dColorx[1], dColorx[2]);
hsl[1] = hsl[1] * 5;
var rgb = hslToRgb(hsl[0], hsl[1], hsl[2]);
var newColor = 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ');'
var inDiv2 = document.getElementById("Div2");
inDiv2.innerHTML += '<svg width="400" height="110">' +
'<rect width="300" height="100" ' +
'style="fill:' + newColor +
';stroke-width:3;stroke:rgb(0,0,0)"></svg>';
Example
jsFiddle: http://jsfiddle.net/az6Ug/
Using Snap.svg library, I want drag on the SVG and get the mouse position. I need the mouse position on the internal matrix, not the browser mouse position.
I have this working with one problem, which is if there is any scroll on the window that the SVG belongs to, the calculated mouse position is offset by the amount of scroll on the scrollbar.
For example, with no scroll then it works fine. Or with 10px of vertical scroll on the scrollbar, the mouse position is calculated as: true position + 10px.
It's the same deal if there's any horizontal scroll: offset by the amount of scroll.
In the jsFiddle, I use a rectangle to show the calculared mouse position while dragging.
As you can see if there's no scroll, then the rectangle stays with the mouse cursor (upper left corner). But with some scroll, the rectangle is offset from the mouse cursor.
Although I'm using the Snap.svg library, I only use this to get the drag event, the mouse calculation is pure Javascript. A possible solution is to subtract the X and Y by the amount of scroll but I think there will be a better way using the SVG's tranform functions.
var S;
var pt;
var svg
var box;
window.onload = function(){
svg = $('#mysvg')[0];
S = Snap(svg);
pt = pt = svg.createSVGPoint(); // create the point
// add the rectangle
box = S.rect(10, 10, 50, 50);
box.attr({ fill : 'red', stroke : 'none' });
S.drag(
function(dx, dy, posX, posY, e){
//onmove
pt.x = posX;
pt.y = posY;
// convert the mouse X and Y so that it's relative to the svg element
var transformed = pt.matrixTransform(svg.getScreenCTM().inverse());
box.attr({ x : transformed.x, y : transformed.y });
},
function(){
//onstart
},
function(){
//onend
}
);
}
Below is an example in Javascript of what I use across all browsers and all viewPorts. It uses svg matrix transforms. The events are attached to each element to be dragged. In the example I've included mouse position readout both for html and svg.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>E - Universal Drag/Drop</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='padding:10px;font-family:arial'>
<center>
<h4>Universal Drag/Drop</h4>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
This example uses matrix transforms, with object methods, not strings. It can seamlessly drag/drop elements that have previously been transformed and reside it different viewPorts. It employs <b>getScreenCTM</b>, <b>createSVGTransform</b> and binds the element to a <b>transform List</b>
</div>
<table>
<tr><td align=left>
Scenerio:<br />
A 400x400 DIV contains an SVG with viewBox=0 0 330 330.<br />
1.) The blue rect element is contained in a <g>.<br />
2.) The <g> element has been transformed.<br />
3.) The maroon rect resides in a different viewPort.<br />
4.) The orange circle has been transformed.<br />
5.) Drag/Drop the circles and rectangles.<br />
</td>
<td align=left>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="100%" height="100%" viewBox="0 0 300 300" onmousemove="svgCursor(evt)">
<circle onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="redCircle" cx="120" cy="180" r="40" fill="red" stroke="black" stroke-width="2" />
<circle onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="orangeCircle" cx="200" cy="200" r="40" fill="orange" stroke="black" stroke-width="2" />
<svg viewBox="0 100 800 800">
<rect onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="maroonRect" x="220" y="250" width="60" height="60" fill="maroon" stroke="black" stroke-width="2" />
</svg>
<g id="myG" >
<rect onmousedown=startDrag(evt) onmousemove=drag(evt) onmouseup=endDrag() id="blueRect" x="220" y="250" width="60" height="60" fill="blue" stroke="black" stroke-width="2" />
</g>
</svg>
</div>
</td>
<td align=left>
<b>HTML Page Values:</b><br />
<input type=text id=htmlMouseXValue size=1 />: mouse X<br />
<input type=text id=htmlMouseYValue size=1 />: mouse Y<br />
<br />
<b>SVG Image Values:</b><br />
<input type=text id=svgXValue size=1 />: svg X<br />
<input type=text id=svgYValue size=1 />: svg Y<br />
</td>
</tr></table>
<br />SVG Source:<br />
<textarea id=svgSourceValue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea>
<br />Javascript:<br />
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea>
</center>
<div id='browserDiv' style='padding:3px;position:absolute;top:5px;left:5px;background-color:gainsboro;'></div>
<script id=myScript>
var TransformRequestObj
var TransList
var DragTarget=null;
var Dragging = false;
var OffsetX = 0;
var OffsetY = 0;
//---mouse down over element---
function startDrag(evt)
{
if(!Dragging) //---prevents dragging conflicts on other draggable elements---
{
DragTarget = evt.target;
//---reference point to its respective viewport--
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements transformed and/or in different(svg) viewports---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());
TransformRequestObj = DragTarget.ownerSVGElement.createSVGTransform()
//---attach new or existing transform to element, init its transform list---
var myTransListAnim=DragTarget.transform
TransList=myTransListAnim.baseVal
OffsetX = Pnt.x
OffsetY = Pnt.y
Dragging=true;
}
}
//---mouse move---
function drag(evt)
{
if(Dragging)
{
var pnt = DragTarget.ownerSVGElement.createSVGPoint();
pnt.x = evt.clientX;
pnt.y = evt.clientY;
//---elements in different(svg) viewports, and/or transformed ---
var sCTM = DragTarget.getScreenCTM();
var Pnt = pnt.matrixTransform(sCTM.inverse());
Pnt.x -= OffsetX;
Pnt.y -= OffsetY;
TransformRequestObj.setTranslate(Pnt.x,Pnt.y)
TransList.appendItem(TransformRequestObj)
TransList.consolidate()
}
}
//--mouse up---
function endDrag()
{
Dragging = false;
svgSourceValue.value=svgDiv.innerHTML
}
//---onload---
function initTransforms()
{
//---place some transforms on the elements---
//--- transform orange circle---
var transformRequestObj=mySVG.createSVGTransform()
var animTransformList=orangeCircle.transform
var transformList=animTransformList.baseVal
//---translate---
transformRequestObj.setTranslate(130,-300)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----scale---
transformRequestObj.setScale(.5,.9)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewY---
transformRequestObj.setSkewY(52)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//--init Transform on myG---
var transformRequestObj=mySVG.createSVGTransform()
var animTransformList=myG.transform
var transformList=animTransformList.baseVal
//---translate---
transformRequestObj.setTranslate(-50,-120)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewX---
transformRequestObj.setSkewX(15)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//----skewY---
transformRequestObj.setSkewY(20)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
//---rotate---
transformRequestObj.setRotate(30,200,200)
transformList.appendItem(transformRequestObj)
transformList.consolidate()
}
document.onmousemove = htmCursor
//---event is the html event object---
function htmCursor(event)
{
var event = event || window.event;
myMouseX=event.clientX;
myMouseY=event.clientY;
myMouseX = myMouseX + document.documentElement.scrollLeft;
myMouseY = myMouseY + document.documentElement.scrollTop;
htmlMouseXValue.value=myMouseX
htmlMouseYValue.value=myMouseY
}
//---evt is the svg event object--
function svgCursor(evt)
{
var rect = svgDiv.getBoundingClientRect();
svgXValue.value=evt.clientX-rect.left
svgYValue.value=evt.clientY-rect.top
}
</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
initTransforms()
svgSourceValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>
</body>
</html>
Maybe you could just use getCTM rather than getScreenCTM, so...
var transformed = pt.matrixTransform(svg.getCTM().inverse());
and I think you may need to adjust with something like
pt.x = posX - S.node.offsetLeft;
pt.y = posY - S.node.offsetTop;
jsfiddle here
Update: as above doesn't work in Firefox, you could take the clientX/Y with the original getScreenCTM, so
pt.x = e.clientX
pt.y = e.clientY;
fiddle here
I'm guessing you need more than just the example here though (in which case you could just use Snaps own drag funcs), so its difficult to tell if this solution will work for other cases you need.
Please see the jsfiddle
sample output:
offset based on svg x:12 y:34
mouse click based on screen x:22 y:38
mouse coord based on svg x:10 y:4
The above sample output is generated when I click on the rectangle on the top-left corner.
As far as I understood, getScreenCTM interface provides the transformation matrix for the element (svg here). I got it as the first line. Second line indicate the mouse coordinate based on the screen coordinate. When I apply the transformation matrix to the mouse click, I expect the point will be translated to svg coordinate. That value is the 3 rd line above. I am not sure that it is correct. The rectangle has a y coordinate 10, and the click event is only availbake within the rectangle. So how could the mouse coord based on svg go below 10??
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HTML><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
</head>
<body>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
<h1>sdsd</h1>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full" height="200">
<g fill="none" stroke="black" stroke-width="1" >
<!-- Draw the axes of the original coordinate system -->
<line x1="0" y1=".5" x2="400" y2=".5" />
<line x1=".5" y1="0" x2=".5" y2="150" />
</g>
<g >
<rect class="drag resize" x="10" y="10" width="100" height="50" fill="#c66" />
</g>
</svg>
<h2 id="op"></h2>
<script type="text/javascript" src="vb.js"></script>
</body>
</html>
var svg = document.getElementsByTagName('svg')[0];
var svgNS = svg.getAttribute('xmlns');
var pt = svg.createSVGPoint();
var el1 = document.getElementsByTagName('rect')[0];
var log_svgcursorPoint,
log_mouseclick,
log_mousecoord;
function svgcursorPoint(evt){
pt.x = evt.clientX; pt.y = evt.clientY;
var a = svg.getScreenCTM();
log_svgcursorPoint = "offset based on svg"+ " x:" + a.e +" y:" + a.f;
var b = a.inverse();
return pt.matrixTransform(b);
};
(function(el){
el.addEventListener('mousedown',function(e){
log_mouseclick = "mouse click based on screen"+ " x:" + e.clientX +" y:" + e.clientY ;
var svgmouse = svgcursorPoint(e);
log_mousecoord = "mouse coord based on svg"+ " x:" + svgmouse.x +" y:" +svgmouse.y;
document.getElementById('op').innerHTML = log_svgcursorPoint + "<br>" + log_mouseclick + "<br>" + log_mousecoord;
},false);
})(el1);
seems like a defect, depending on the browser zoom level. Raised an issue http://code.google.com/p/chromium/issues/detail?id=81995