如何获取相对于持有onclick侦听器的SVG元素的单击坐标?

时间:2015-03-25 16:32:29

标签: javascript html svg

我无法计算相对于触发事件的元素的点击坐标(x和y)。我还没有在网上找到一个简单的例子。

我在HTML页面中有一个简单的svg(左边距为100px)。它包含一个group(已翻译的30px 30px),其中附加了onclick个侦听器。在group内,我有一个宽度和高度均为50像素的rect

点击group元素的任意部分后,我得到一个事件对象,其坐标相对于HTML页面(evt.clientXevt.clientY)。

我需要知道的是用户在group元素(持有onclick监听器的元素)中单击的确切位置。

如何将clientXclientY坐标转换为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>

3 个答案:

答案 0 :(得分:43)

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,posted the code

如果viewBox未设置或设置为默认值,则此脚本将返回与Tolokoban脚本相同的值。但是,如果你有一个像<svg width="100px" height="100" viewBox="0 0 200 200">这样的SVG,只有这个版本会给你正确的结果。

答案 1 :(得分:28)

尝试使用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 :(得分:0)

经过大量研究后添加笔记(失败!)。

对于 css翻译的svg ,获取用于绘制的单击点的坐标。

在我的情况下,使用鼠标滚轮事件来转换X,因此实际渲染取决于屏幕尺寸和实际转换值。

我建议您在用例中绘制如下图所示的内容,这将有助于弄清发生的情况。

Svg translateX click point

假设我的svg的ID为shoke 要获取总的计算宽度(以像素为单位):

shoke.getBoundingClientRect()["width"]

需要知道实际的translateX值。 (在右边,在这种情况下,它是一个负数)

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

请注意,它返回的是字符串而不是整数,所以:

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

现在获取与屏幕像素x0相关的鼠标坐标。

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

因此,最后获得精确的 x 点:

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

是这样的:

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