SVGPan: a Javascript SVG (Viewer) Pan/Zoom/Drag library
Some time ago the need for a browser-compatible vectorial language pushed me to consider the SVG markup language (I won’t say anything about Internet Explorer – it’s just unsupported there). The language itself is great, but, as a beginner, I was so disappointed about the fact that on the Internet I couldn’t find ANY library ready to use for panning and zooming features that I had to write one from scratch.
The SVGPan library features:
- Panning (pan à la Google maps) (click on the white background and pan)
- Zooming (using the mouse wheel)
- Element dragging (click on a drawing element and drag it somewhere else)
- Combinations of the above like zooming while dragging
The resulting javascript library is published here, in the hope that someone can find it useful. The library itself is very small and easy to use; and it’s licensed under the BSD license. You can try a demo here
No SVG support at all!
You can also open the demo in a new page and download the SVGPan library here.
The library itself requires a root group to be identified by the id viewport, which confines the SVGPan library effects, and the import of the javascript code as well. For example, to adapt the tiger drawing, it was necessary to add the following:
<script xlink:href="SVGPan.js"/> <g id="viewport" transform="translate(200,200)">...
You may also try another SVG example (triple integral, from Wikipedia).
Zeng Xiaohui has provided a patch to support the mouse wheel on Safari/Chrome and fixed the browser scrollbar issue as well. Both patches have been merged into the latest version of SVGPan.
The source of this project is now hosted on Google Code, so there you can find the latest version.
If you found this code useful please consider donating!


Andrea, thank you so much for building this! Such an obvious yet sorely lacking bit of functionality.
One issue: If the SVG is not initially scaled exactly 100%, then zooming does not work properly. If the initial scale is 100% then the opposite happens, and scroll zooming only increases the zoom.
In my case the SVG is the width of the browser window. I use a fixed viewBox but dynamic 100% width. So my SVG almost never starts at scale=1.0.
Do you have any idea how to work around this?
I will keep puttering about, and if I find a solution I’ll post it here.
Thanks again for this library,
-dan
Hello Dan,
give a look at the latest trunk version in the svn repository at svgpan.googlecode.com: it may fix the issue you’re experiencing! Let me know.
Regards,
Andrea
I checked out your current 1.2.2. It does zoom correctly now when the initial zoom is not 1.0. But there’s a new problem: since you remove the viewBox element from the node, when I resize the page the image gets cropped wrong because the viewBox is missing.
I had been trying another approach: store the initial CTM as “CTMonload” and then instead of starting all transformations with:
g.getCTM()
I’d start them with
g.getCTM().multiply(CTMonload.inverse()
that is, start by normalizing to 100%, then applying the transformation. I haven’t gotten it totally working but I think it’s an OK approach. What do you think?
drop me a line at dan dot moran at the usual gmail and I can give you a link to the page I’m working on. Then you can easily see the problem with removing the viewBox.
Hi Andrea,
I got something working for my situation. I have a world map that should take 100% of the browser width, but I have a viewbox=”0 0 1200 600″. The problem I faced is that resizing the browser window resizes the element just fine, but does not resize the element.
My solution was to add this onresize() handler. When the document is initialized I set initWidth and initHeight to the width and height of the viewbox (though in fact I cheated and hardcoded the viewbox values)
There’s a minor bug in my solution. When you resize the browser window, any pan/zoom you have done is reset.
function handleResize(evt){
var svgDoc = evt.target;
var g = getRoot(svgDoc);
/* BUG: on window resize, the scale is reset to 1.0 */
var scalex = g.parentElement.width.baseVal.value / initWidth;
var scaley = g.parentElement.height.baseVal.value / initHeight;
var k = root.createSVGMatrix().scale(scalex).multiply(g.getCTM().inverse());
setCTM(g, g.getCTM().multiply(k));
}
cheers,
dan
Hi Andrea,
this is great, but I can only get it to work when opening the svg by itself. If I load the SVG using the JQuery SVG plugin, I get this error when trying to zoom or pan. (I have created a group with id=”viewport”)
Uncaught TypeError: Object # has no method ‘createSVGPoint’
getEventPointSVGPan.js:133
handleMouseDownSVGPan.js:257
(anonymous function)8:1
onmousedown
Have you tried using your library with Jquery SVG?
thanks
Hello this is really helpful!
i am not a programmer but working on a small fashion project.
i can manage to get the library to work with one svg object.
but in my project i have 413 different svg objects in the same page!
the question is can i make each of the objects independability draggable?
thoguh i don’t need zooming
give me some hints please
Hola!
I’m using graphviz with ‘tooltip’ entries to generate svg with objects like the following, using a xlink:title. Unfortunately, while SVGPan works very nicely without the xlinks, it fails completely with them.
foo
foo
pelucon, I was able to just use the basic jQuery $.append to add an embed tag to the DOM and it seems to work perfectly. Would that work for you?
andrea,
Does the script tag have to be inside the SVG tag? I was hoping to have your library referenced outside the actual SVG because I’ll be dealing with dynamically generated SVG images that I need this functionality on.
Maybe there’s a clean way to modify the SVG with JS to add the script at the same time I am appending the embed tag to the DOM?
Thanks for sharing such a great library!
– Danny
Ciao Andrea,
This is a nice and very useful piece of work…
I am working on a project for a commercial client and would like to incorporate SVGPan.js into a rather specialized application which has no mouse, but only a very limited input device. We require simple zoom and pan driven by a simple JS function call into your library, rather than the current event handler methodology.
My question is this: Would you be interested in working with me, for pay, to make these modifications to the SVGPan.js for our specific use?
Thanks, and best regards,
Gary
I’ve adapted svgpan as a jQuery plugin. This lets you apply the features to arbitrary in-page SVG data.
https://github.com/talos/jquery-svgpan/
http://talos.github.com/jquery-svgpan/demo.html
The main use case is for visualizations from SVG generators like d3:
http://mbostock.github.com/d3/
Thanks for putting this together!
How can this be adapted if you have multiple group/viewpoints.
My SVG will have nested SVGs, some of which are images, we need to be able to manually drag these images individually.
If I have multiple SVGs in with group/viewpoints only the first one found moves, what I could do with is a way the select the required SVG on mouseDown.
Hi Andrea,
Do you know if this will work if the element is contained in an HTML file? Does not look like it, as of yet…
Regards,
Corey.