Как получить координаты кликов относительно элемента SVG, содержащего прослушиватель onclick?

Мне не удалось вычислить координаты кликов (x и y) относительно элемента, запускающего событие. Я не нашел простой пример онлайн.

У меня есть простой svg (с левым краем 100px) на странице HTML. Он содержит group (переведенный 30px 30px), который имеет приставку onclick. И внутри group у меня есть rect с шириной и высотой 50 пикселей.

После нажатия любой части элемента group я получаю объект события с координатами относительно HTML-страницы (evt.clientX и evt.clientY).

Мне нужно знать, где именно пользователь щелкнул внутри элемента group (элемент, содержащий прослушиватель onclick).

Как преобразовать координаты clientX и clientY в координаты элемента group. Скажем, если я нажму на верхнюю левую часть rect, он должен дать мне x = 0 и y = 0.

Вот что у меня есть:

<!DOCTYPE html>
<html>
    <head>
        <style>
            body{
                background:black;
            }
            svg{
                fill:white;
                background:white;
                position: absolute;
                top:100px;
                left:100px;
            }
            
        </style>
        <script>
            function clicked(evt){
                alert("x: "+evt.clientX+" y:"+evt.clientY);
            }
        </script>
    </head>
    <body>
        <div>
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
                <g transform="translate(30 30)" onclick="clicked(evt)">
                    <rect x="0" y="0" width="50" height="50" fill="red"/>
                </g>
            </svg>      
        </div>
    </body>
</html>

Ответ 1

Попробуйте использовать 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);
}  

Ответ 2

Решение Tolokoban имеет ограничение, что оно не работает, если ваш viewBox отклоняется от значения по умолчанию, то есть, если он отличается от viewBox="0 0 width height". Лучшим решением, которое также учитывает viewBox, является следующее:

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 + ")");
}

(Кредит принадлежит Smerk, отправил код)

Если viewBox не установлен или установлен по умолчанию, этот script возвращает те же значения, что и Tolokoban script. Но если у вас есть SVG, например <svg width="100px" height="100" viewBox="0 0 200 200">, только эта версия даст вам правильные результаты.