How to get the click coordinates relative to SVG element holding the onclick listener?

Tolokoban's solution has the limitation that it doesn't work if your viewBox deviates from the default, that is if it is different from viewBox="0 0 width height". A better solution that also takes viewBox into account is this:

var pt = svg.createSVGPoint();  // Created once for document

function alert_coords(evt) {
    pt.x = evt.clientX;
    pt.y = evt.clientY;

    // The cursor point, translated into svg coordinates
    var cursorpt =  pt.matrixTransform(svg.getScreenCTM().inverse());
    console.log("(" + cursorpt.x + ", " + cursorpt.y + ")");
}

(Credit goes to Smerk, who posted the code)

If the viewBox is not set or set to the default, this script will return the same values as Tolokoban's script. But if you have an SVG like <svg width="100px" height="100" viewBox="0 0 200 200">, only this version will give you the correct results.


Try to use getBoundingClientRect(): http://jsfiddle.net/fLo4uatw/

function clicked(evt){
    var e = evt.target;
    var dim = e.getBoundingClientRect();
    var x = evt.clientX - dim.left;
    var y = evt.clientY - dim.top;
    alert("x: "+x+" y:"+y);
}  

The proposed solutions are great, but they won't work in all scenarios.

The OP's post is titled

How to get the click coordinates relative to SVG element holding the onclick listener?

So if you put the onclick listener onto your root svg element, whenever you click on any of its child elements, getBoundingClientRect will give you the child's Rect and you won't get the click coordinates relative to the root svg.

This was my case as I needed the coordinates relative to the root at all times, and the solution that worked for me was to use e.target.farthestViewportElement. Here's an excerpt from my (JSX) code:

const onClickSvg = e => {
  const { farthestViewportElement: svgRoot } = e.target;
  const dim = svgRoot.getBoundingClientRect();
  const x = e.clientX - dim.left;
  const y = e.clientY - dim.top;
  console.log(`x: ${x}, y: ${y}`);
};

<svg onClick={onClickSvg}>...</svg>

Adding notes after many researchs (and fails!).

For a css translated svg, to get the coordinates of a clicked point for drawing.

In my case, using a mouse wheel event to translateX, so the actual rendering depends of the screen size and of the actual translated value.

I recommend for your use case to make a little drawing like the following, it will help a lot for figuring out what's going on.

Svg translateX click point

Let's say my svg has for id: shoke To get the total computed width, in pixels:

shoke.getBoundingClientRect()["width"]

Need to know the actual translateX value. (From the right, so it is a negative number, on this case)

shoke.style.transform.substr(11).slice(0,-3)

Note that it return a string and not an integer, so:

+shoke.style.transform.substr(11).slice(0,-3)

Now to get the coordinates of the mouse, related to the pixel x0 of the screen.

let pt = document.querySelector('svg').createSVGPoint();
pt.matrixTransform(shoke.getScreenCTM().inverse())["x"]

So, at the end, to obtain the precise x point:

svg_width - (svg_width + translated) + from_pixel x0 of the screen_click

Is something like this:

shoke.getBoundingClientRect()["width"]  - (shoke.getBoundingClientRect()["width"] + +shoke.style.transform.substr(11).slice(0,-3)) + pt.matrixTransform(shoke.getScreenCTM().inverse())["x"]