web-dev-qa-db-ja.com

onclickリスナーを保持するSVG要素に関連するクリック座標を取得する方法は?

イベントをトリガーする要素に対するクリック座標(xおよびy)を計算できませんでした。私はオンラインで簡単な例を見つけていません。

HTMLページに単純なsvg(100px左マージン)があります。 groupリスナーが接続されたonclick(30px 30pxに変換)が含まれています。そしてそのgroupには、幅と高さが50ピクセルのrectがあります。

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>
26
oabarca

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);
}  
29
Tolokoban

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が設定されていないか、デフォルトに設定されている場合、このスクリプトはTolokobanのスクリプトと同じ値を返します。ただし、<svg width="100px" height="100" viewBox="0 0 200 200">のようなSVGがある場合、このバージョンのみが正しい結果を提供します。

47
Alexander Jank

多くの研究の後にメモを追加する(そして失敗する!)。

css変換されたsvgの場合、クリックして描画するポイントの座標を取得します。

私の場合、translateXにマウスホイールイベントを使用しているため、実際のレンダリングは画面サイズと実際の変換値に依存します。

ユースケースでは、次のような小さな図面を作成することをお勧めします。これは、何が起こっているかを把握するのに大いに役立ちます。

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"]
0
NVRM