Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

svg-pan-zoom pan/zoom to any object

Tags:

javascript

svg

I'm using the svg-pan-zoom code https://github.com/ariutta/svg-pan-zoom to make an svg map of some kind, now it is time to add a feature to pan & zoom to an art component of the svg on a click event. However, I'm not sure how to use the panBy() function to get to a desired svg art item: I tried to use the getBBox() on the group I'm looking to pan to and use that with the panZoomInstance.getPan() and getSizes() information, but my experiments are not working out. I'd like to accomplish the same king of animation as their example (http://ariutta.github.io/svg-pan-zoom/demo/simple-animation.html) but center the viewport to the item.

like image 802
Vasily Hall Avatar asked Oct 19 '25 09:10

Vasily Hall


1 Answers

Against all odds I was able to figure out this part of it!

function customPanByZoomAtEnd(amount, endZoomLevel, animationTime){ // {x: 1, y: 2}
  if(typeof animationTime == "undefined"){
      animationTime =   300; // ms
  }
  var animationStepTime = 15 // one frame per 30 ms
    , animationSteps = animationTime / animationStepTime
    , animationStep = 0
    , intervalID = null
    , stepX = amount.x / animationSteps
    , stepY = amount.y / animationSteps;

  intervalID = setInterval(function(){
    if (animationStep++ < animationSteps) {
      panZoomInstance.panBy({x: stepX, y: stepY})
    } else {
      // Cancel interval
      if(typeof endZoomLevel != "undefined"){
        var viewPort = $(".svg-pan-zoom_viewport")[0];
        viewPort.style.transition = "all " + animationTime / 1000 + "s ease";
        panZoomInstance.zoom(endZoomLevel);
        setTimeout(function(){
            viewPort.style.transition = "none";
            $("svg")[0].style.pointerEvents = "all"; // re-enable the pointer events after auto-panning/zooming.
                    panZoomInstance.enablePan();
                    panZoomInstance.enableZoom();
                    panZoomInstance.enableControlIcons();
                    panZoomInstance.enableDblClickZoom();
                    panZoomInstance.enableMouseWheelZoom();
        }, animationTime + 50);
      }
      clearInterval(intervalID)
    }
  }, animationStepTime)
}

function panToElem(targetElem) {

    var initialSizes = panZoomInstance.getSizes();
    var initialLoc = panZoomInstance.getPan();
    var initialBounds = targetElem.getBoundingClientRect();
    var initialZoom = panZoomInstance.getZoom();
    var initialCX = initialBounds.x + (initialBounds.width / 2);
    var initialCY = initialBounds.y + (initialBounds.height / 2);

    var dX = (initialSizes.width / 2) - initialCX;
    var dY = (initialSizes.height / 2) - initialCY;

  customPanByZoomAtEnd({x: dX, y: dY}, 2, 700);
}

The key was in calculating the difference between the center of the viewport width & height from panZoomInstance.getSizes() and the center of the target element's client bounding rectangle.

Now the issue is trying to make an animated zoom. For now I've made it do a zoom to a specified location with a command at the end of the panning animation and set some css to make the zoom a smooth transition. The css gets removed after some time interval so normal zooming and panning isn't affected. In my attempts to make the zoom a step animation it always appeared to zoom past the intended max point.

like image 72
Vasily Hall Avatar answered Oct 21 '25 22:10

Vasily Hall



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!