javascriptanimationsvgpanzoom

animating svg pan when manually setting pan.x and pan.y


I have a dynamically generated svg image that I am using Ariutta's svg-pan-zoom plugin with. When I double click an svg image, I set pan.x = centerOfScreenX, and pan.y = centerOfScreenY to center the image in the middle of the screen. ie:

$('.svg').dblclick(function(){
    zoom.pan({'x':centerOfScreenX, 'y':centerOfScreenY });
});

Currently this causes the image to just suddenly move to the center of the screen. Is there a way I can animate this change in pan position so that the image doubleclicked moves along a path to the center of the screen instead?


Bumbu suggested two solution paths (see answers below), and I have taken a stab at the first. My attempt did not work however, and I do not know why.

// centerOfScreenX and centerOfScreenY are the correct values that pan.x and  
// pan.y should have to center the svg in the middle of the screen 

// xInterval and yInterval break the distance between the current pan     
// position and the desired pan position into 10 steps

var xInterval = (centerOfScreenX - pan.x)/10;
var yInterval = (centerOfScreenY - pan.y)/10;

while( pan.x !== centerOfScreenX && pan.y !== centerOfScreenY ){
    if(pan.x !== centerOfScreenX){
        pan({'x': pan.x + xInterval })
    }
    if(pan.y !== centerofScreenY){
        pan({'y': pan.y + yInterval })
    }
}

When I try to run this code, the window freezes and I can no longer interact with my app, unless i close the window and reload it. My guess is that I am somehow triggering an infinite loop.


Solution

  • Currently there is no solution to do animation in an easy way. There is a similar question (about animating zoom). The answer from there (adjusted to this one) is:

    Currently such functionality is not supported. You could do it in 2 ways:

    • Use a twin library (or write you own function) and just call pan in small iterations multiple times. This may be slow but it is what many libraries do when implementing animation (eg. jQuery).
    • Use SVG animateTransform element. It seems to be the right way. But it needs some work to get it done.

    You can actually try to implement second solution by listening to zoom events, canceling them and adding animateTransform manually to the SVG. When your animation is done, call zoom again but this time don't cancel it (necessary to update library inner state).

    There is an ongoing discussion about next version of library that would be more extensible. This would allow to write plugins. Animation is one of the candidates. But it will take some time (few months) to do this.

    If you'll be able to find a temporary solution - share it here or on github and we'll be happy to update the library or integrate it in next version.

    Edit

    I added a simple example how this kind of animation can be implemented. You can find it in demo/simple-animation.html

    I used a simple interval there. A more advanced version should take into account how much time passed since last interval call and send the right amount for pan. But even like this it works very well.

    The library internally uses requestAnimationFrame so you can call panBy even every millisecond and it shouldn't block the browser.