javascriptjquerysvgsvgpanzoom

How to get X,Y coordinates from path element inside SVG?


Here is a fiddle of what actually have. https://jsfiddle.net/Lofdujwr/

I'm using a library for zoom and pan an SVG svgpanzoom. I have a button when clicked it zooms on spain for example, so I put the coordinates in:

   $("#spain").on("click", function() {
        panZoom.zoomAtPoint(12, {x: 188, y: 185});
    });

The problem is when I resize the page that coordinates doens't work anymore I need to recalculate them, I have found a function that might work but I don't know how to use it:

var s = instance.getSizes()
var p = instance.getPan()
var relativeX = s.width / 2 / (p.x + s.viewBox.width * s.realZoom)

// After resize
var s = instance.getSizes()
var p = instance.getPan()
var x = (s.width / 2 / relativeX) - s.viewBox.width * s.realZoom
instance.pan({x: x, y: 0})

function post

And another question, is it possible to get coordinates from a path ID inside the svg for example?

EDIT: Seems like I have to calculate the actual X and Y viewport from my svg and then recalculate it giving my point (x:188, y: 185) on 0.0 viewport, anyone know any example I can see?


Solution

  • To answer the actual question:

    The plugin you are using is controlling the transforms by changing the matrix of g.svg-pan-zoom_viewport and not the viewBox of the svg.

    In your function cursorPoint() you keep transforming the mouse-coordinates referring to the svg, yet you discard the underlying transformation on g.svg-pan-zoom_viewport. That is the reason why you are getting different coordinates while the svg is either resized or moved (=transformed).

    If you refer the coordinates to the g.svg-pan-zoom_viewport instead, you will get consistent results.

    function cursorPoint(evt){
        pt.x = evt.clientX; pt.y = evt.clientY;
        //return pt.matrixTransform(svg.getScreenCTM().inverse());
    
        var tGroup = document.querySelector('.svg-pan-zoom_viewport');
        return pt.matrixTransform(tGroup.getScreenCTM().inverse());
    }
    

    Another way would be to change the viewBox of the svg instead of using the groups matrix. Yet since your plugin works that way, you should go with it.

    Update

    I played around with that linked plugin a bit and for me the function zoomAtPoint() is doing something wrong. Let us assume Spain in the linked fiddle is at 165:165. Now to constantly zoom to that location correctly you need to reset it before:

    panZoom.reset();
    panZoom.zoomAtPoint(6, {x: 165, y: 165});
    

    Else the function either does nothing or zooms somewhere else.

    Now to get the coordinates of "argentinia" and zoom to it:

    panZoom.reset();
    
    //REM: Apparently the values need some time to adjust after reset() is called, yet is seems to have no callback.
    window.setTimeout(function(){
        var tViewport = document.querySelector('g.svg-pan-zoom_viewport');
        var tMatrix = tViewport.transform.baseVal.getItem(0).matrix;
        var tBBox = document.querySelector('#argentina').getBBox();
        var tPoint = {x: (tBBox.x + tBBox.width / 2) * tMatrix.a + tMatrix.e, y: (tBBox.y + tBBox.height / 2) * tMatrix.d + tMatrix.f}
    
        //REM: Approximate values, I leave the exact calculation up to you.
        panZoom.zoomAtPoint(6, tPoint);
    }, 500)
    

    Working fiddle with example buttons: https://jsfiddle.net/04Lg9ruj/