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.
This is wonderful – exactly what’s needed to make SVG useful for data visualisation. Thanks a lot.
Andrea,
In 1.2.2, I had a problem where SVGPan.js was applying its transform to the <svg> element instead of the <g id=”viewport”> element. Here is the change I made which solved the problem. I sort-of think it’s a good safe thing to add.
-setupHandlers(root);+if (window.addEventListener) { // W3C standard
+ window.addEventListener('load', setupHandlers, false); // NB **not** 'onload'
+} else if (window.attachEvent) { // Microsoft
+ window.attachEvent('onload', setupHandlers);
+}
and
-function setupHandlers(root){+function setupHandlers(){
since ‘root’ is a global variable already set to document.documentElement earlier.
Is it possible to use your script with matrix3D for the best performance? I know you can use translate3d in css to use the GPU and accelarate the performance.
Thank You!
David
Hello, We are developing a 2d floor plan viewer using SVG and we struggle implementing multi-touch pan and zoom that work properly… anyone can help at developing this for us as a freelance please let me know.
We are using webkit-transform.. an exemple of what we are trying to do: http://vps1.alpha-vision.com/svg/vps/dave/vps3/tabletzoompandave.html
jonathan.brosseau@alpha-vision.com
two other exemple of what we tried…
http://vps1.alpha-vision.com/svg/vps/dave/vps3/tabletzoompanhugo.html
http://vps1.alpha-vision.com/svg/vps/dave/vps3/tabletzoompancenter.html
Thank you, I’ll give it a try! Anyway feel free to submit bugs/patches on svgpan.google.com. (PS: if you are willing to develop svgpan I can give add you as committer on googlecode).
Hey Andrea, Great script, thank you. I’m having some problems with it though – see issue 16. I am willing to come up with a fix but really need some help as where to start. I think the translation from my nested SVG elements isn’t being accounted for properly.
It’d be nice if the zoom speed changed based on how far you were zoomed in. That is, an exponential scale. You could do zoom factor = base ^ “scroll wheel clicks from origin” (where you’d probably need to fudge around with base to find a good value).
Hi Andrea,
thanks for your work.
As an extension I would like to have a method which centers a given element.
My use case is the following:
- I have a graph (created by graphviz)
- when clicking on a transition I want the target node to be displayed in the center of the screen
Perhaps you have a simple solution for this.
Best regards
Achim
I and also my buddies ended up analyzing the good tricks on your web
page and so immediately got an awful feeling I had not
thanked the web blog owner for those tips. All of the ladies came as a result warmed to study all of them and now
have very much been taking advantage of them.
I appreciate you for being indeed considerate as well
as for going for this sort of remarkable issues most people are really desperate to know about.
Our own sincere apologies for not expressing gratitude to sooner.
This looks like it would be great!!! Thank you for your efforts!!!
We have a complex svg file that has multiple g tags. If I try to use this js in our svg, I get:
TypeError: matrix is null
[Break On This Error]
…matrix.a + “,” + matrix.b + “,” + matrix.c + “,” + matrix.d + “,” + matrix.e + “…
SVGPan.js (line 145)
Can you help?
Can you provide a test case please?
Very good post. I absolutely appreciate this website.
Stick with it!
Here is a pretty small test case:
http://nick.thepinc.com/view.html
Thanks!
Greate post. Keep writing such kind of information on your page.
Im really impressed by your blog.
Hey there, You have performed an incredible job.
I will certainly digg it and individually recommend to my friends.
I’m sure they’ll be benefited from this site.
Hello there, There’s no doubt that your web site could possibly be having internet browser compatibility issues. When I take a look at your site in Safari, it looks fine however, when opening in I.E., it’s got some overlapping issues.
I simply wanted to give you a quick heads up!
Other than that, great website!
Hello, everything is going sound here and ofcourse every one is sharing information, that’s genuinely fine, keep up writing.
Real informative and great anatomical structure of articles,
now that’s user genial (:.
I rarely comment, but I looked at a few of the remarks on this page SVGPan:
And, if you are posting at additional online sites, I’d
a Javascript SVG (Viewer) Pan/Zoom/Drag library |
cyberz.org. I actually do have a few questions for you if it’s allright. Is it just me or does it look like like some of the responses appear as if they are written by brain dead folks?
like to follow you. Could you list of every one of all your social pages
like your twitter feed, Facebook page or linkedin profile?
excellent work
I was looking for such thing
Pan, Zoom, Identify the selected object, …
Rotate, Edit, this seems to request a big knowladge about javascript
thanks for sharing !!!
Hi,
I’ve found svgPan fantastic, but I’m just wondering if the difficulties with IE8 were ever fixed? I’ve run in to the same issue as Matock i.e.
Expected identifier, string or number line 98, column 1.
Any help would be greatly appreciated!
Thanks in advance,
John
I thought this particular script had been the coolest aspect ever.
By default, SVG image using SVGPan is set to the center of the webpage horizontally and vertically.
How can I manually set the position of svg image? Which a part of code I can modify to meet my requirement?
Thanks in advance.
Anyway, Your library is so cool!
Very nice design and wonderful subject matter, nothing else
we need : D.