Giter Club home page Giter Club logo

svg-pan-zoom's Introduction

svg-pan-zoom logo

svg-pan-zoom library

Simple pan/zoom solution for SVGs in HTML. It adds events listeners for mouse scroll, double-click and pan, plus it optionally offers:

  • JavaScript API for control of pan and zoom behavior
  • onPan and onZoom event handlers
  • On-screen zoom controls

It works cross-browser and supports both inline SVGs and SVGs in HTML object or embed elements.

If you're looking for version 2.3.x you can find it in v2.3.x branch

Support

Bugs and Issues

If you found a bug or have a suggestion first check if there is a similar open or closed issue. If there are none then create a new one.

When opening a new issue please provide a reproducible example:

  • Share it so we can get directly to the problem. You can use this starter jsfiddle setup to provide your example. Or upload your own jsfiddle.net (or any other live) example.
  • Mention your library version (located in library file in header)
  • Mention your browser name, version and operating system
  • Mention any other important for debug details

Solved Bugs and Implemented Features

If you solved a bug or implemented a feature that may be useful for others then you're welcome to create a pull request.

Questions, How To's, Need Help

If you have any other type of questions, problems, your code is not working or you want to critique the library - you can use StackOverflow. Just tag your question with svgpanzoom.

Contributions/Pull Requests

Best way to contribute is to create a pull request. In order to create a pull request:

  • Fork this repository
  • Clone repository fork (created in previous step) locally (on your machine)
  • Ensure that you have nodejs and npm installed locally
  • In console:
    • cd into project folder
    • Run npm install
    • Run npm install -g gulp if you don't have it already installed globally
    • Running gulp will listen for source files changes (in src folder) and will automatically build distribution files
    • Running gulp compile will compile source files
    • Running gulp check will check syntax and automatically fix some errors
    • Running gulp test will run tests
    • Running gulp build will prepare the project for a new release
  • Implement the change using gulp or gulp compile
  • After change is done test it with gulp check and gulp test
  • Commit only meaningful changes. Do not commit distribution files (dist folder). Distribution files are built only before a release
  • Push your changes into your fork
  • Create a pull request

Demos

Pan and zoom the SVG tiger on github pages:

How To Use

Reference the svg-pan-zoom.js file from your HTML document. Then call the init method:

var panZoomTiger = svgPanZoom('#demo-tiger');
// or
var svgElement = document.querySelector('#demo-tiger')
var panZoomTiger = svgPanZoom(svgElement)

First argument to function should be a CSS selector of SVG element or a DOM Element.

If you want to override the defaults, you can optionally specify one or more arguments:

svgPanZoom('#demo-tiger', {
  viewportSelector: '.svg-pan-zoom_viewport'
, panEnabled: true
, controlIconsEnabled: false
, zoomEnabled: true
, dblClickZoomEnabled: true
, mouseWheelZoomEnabled: true
, preventMouseEventsDefault: true
, zoomScaleSensitivity: 0.2
, minZoom: 0.5
, maxZoom: 10
, fit: true
, contain: false
, center: true
, refreshRate: 'auto'
, beforeZoom: function(){}
, onZoom: function(){}
, beforePan: function(){}
, onPan: function(){}
, onUpdatedCTM: function(){}
, customEventsHandler: {}
, eventsListenerElement: null
});

If any arguments are specified, they must have the following value types:

  • 'viewportSelector' can be querySelector string or SVGElement.
  • 'panEnabled' must be true or false. Default is true.
  • 'controlIconsEnabled' must be true or false. Default is false.
  • 'zoomEnabled' must be true or false. Default is true.
  • 'dblClickZoomEnabled' must be true or false. Default is true.
  • 'mouseWheelZoomEnabled' must be true or false. Default is true.
  • 'preventMouseEventsDefault' must be true or false. Default is true.
  • 'zoomScaleSensitivity' must be a scalar. Default is 0.2.
  • 'minZoom' must be a scalar. Default is 0.5.
  • 'maxZoom' must be a scalar. Default is 10.
  • 'fit' must be true or false. Default is true.
  • 'contain' must be true or false. Default is false.
  • 'center' must be true or false. Default is true.
  • 'refreshRate' must be a number or 'auto'
  • 'beforeZoom' must be a callback function to be called before zoom changes.
  • 'onZoom' must be a callback function to be called when zoom changes.
  • 'beforePan' must be a callback function to be called before pan changes.
  • 'onPan' must be a callback function to be called when pan changes.
  • 'customEventsHandler' must be an object with init and destroy arguments as functions.
  • 'eventsListenerElement' must be an SVGElement or null.

beforeZoom will be called with 2 float attributes: oldZoom and newZoom. If beforeZoom will return false then zooming will be halted.

onZoom callbacks will be called with one float attribute representing new zoom scale.

beforePan will be called with 2 attributes:

  • oldPan
  • newPan

Each of these objects has two attributes (x and y) representing current pan (on X and Y axes).

If beforePan will return false or an object {x: true, y: true} then panning will be halted. If you want to prevent panning only on one axis then return an object of type {x: true, y: false}. You can alter panning on X and Y axes by providing alternative values through return {x: 10, y: 20}.

Caution! If you alter panning by returning custom values {x: 10, y: 20} it will update only current pan step. If panning is done by mouse/touch you have to take in account that next pan step (after the one that you altered) will be performed with values that do not consider altered values (as they even did not existed).

onPan callback will be called with one attribute: newPan.

Caution! Calling zoom or pan API methods from inside of beforeZoom, onZoom, beforePan and onPan callbacks may lead to infinite loop.

onUpdatedCTM will get called after the CTM will get updated. That happens asynchronously from pan and zoom events.

panEnabled and zoomEnabled are related only to user interaction. If any of this options are disabled - you still can zoom and pan via API.

fit takes precedence over contain. So if you set fit: true then contain's value doesn't matter.

Embedding remote files

If you're embedding a remote file like this

<embed type="image/svg+xml" src="/path/to/my/file.svg" />
<object type="image/svg+xml" data="/path/to/my/file.svg">Your browser does not support SVG</object>

or you're rendering the SVG after the page loads then you'll have to call svgPanZoom library after your SVG is loaded.

One way to do so is by listening to load event:

<embed type="image/svg+xml" src="/path/to/my/file.svg" id="my-embed"/>

<script>
document.getElementById('my-embed').addEventListener('load', function(){
  // Will get called after embed element was loaded
  svgPanZoom(document.getElementById('my-embed'));
})
</script>

Using a custom viewport

You may want to use a custom viewport if you have more layers in your SVG but you want to pan-zoom only one of them.

By default if:

  • There is just one top-level graphical element of type SVGGElement (<g>)
  • SVGGElement has no transform attribute
  • There is no other SVGGElement with class name svg-pan-zoom_viewport

then the top-level graphical element will be used as viewport.

To specify which layer (SVGGElement) should be pan-zoomed set the svg-pan-zoom_viewport class name to that element: <g class="svg-pan-zoom_viewport"></g>.

Do not set any transform attributes to that element. It will make the library misbehave. If you need transform attribute for viewport better create a nested group element and set transforms to that element:

<g class="svg-pan-zoom_viewport">
  <g transform="matrix(1,0,0,1,0,0);"></g>
</g>

You can specify your own viewport selector by altering viewportSelector config value:

svgPanZoom('#demo-tiger', {
  viewportSelector: '.svg-pan-zoom_viewport'
});
// or
var viewportGroupElement = document.getElementById('demo-tiger').querySelector('.svg-pan-zoom_viewport');
svgPanZoom('#demo-tiger', {
  viewportSelector: viewportGroupElement
});

Listening for pan/zoom events on a child SVG element

If you want to listen for user interaction events from a child SVG element then use eventsListenerElement option. An example is available in demo/layers.html.

Use with browserify

To use with browserify, follow these steps:

  • Add the package as node module npm install --save bumbu/svg-pan-zoom
  • Require svg-pan-zoom in your source file svgPanZoom = require('svg-pan-zoom')
  • Use in the same way as you would do with global svgPanZoom: instance = svgPanZoom('#demo-tiger')

Use with Require.js (or other AMD libraries)

An example of how to load library using Require.js is available in demo/require.html

Custom events support

You may want to add custom events support (for example double tap or pinch).

It is possible by setting customEventsHandler configuration option. customEventsHandler should be an object with following attributes:

  • haltEventListeners: array of strings
  • init: function
  • destroy: function

haltEventListeners specifies which default event listeners should be disabled (in order to avoid conflicts as svg-pan-zoom by default supports panning using touch events).

init is a function that is called when svg-pan-zoom is initialized. An object is passed into this function. Passed object has following attributes:

  • svgElement - SVGSVGElement
  • instance - svg-pan-zoom public API instance

destroy is a function called upon svg-pan-zoom destroy

An example of how to use it together with Hammer.js:

var options = {
  zoomEnabled: true
, controlIconsEnabled: true
, customEventsHandler: {
    // Halt all touch events
    haltEventListeners: ['touchstart', 'touchend', 'touchmove', 'touchleave', 'touchcancel']

    // Init custom events handler
  , init: function(options) {
      // Init Hammer
      this.hammer = Hammer(options.svgElement)

      // Handle double tap
      this.hammer.on('doubletap', function(ev){
        options.instance.zoomIn()
      })
    }

    // Destroy custom events handler
  , destroy: function(){
      this.hammer.destroy()
    }
  }
}

svgPanZoom('#mobile-svg', options);

You may find an example that adds support for Hammer.js pan, pinch and doubletap in demo/mobile.html

Keep content visible/Limit pan

You may want to keep SVG content visible by not allowing panning over SVG borders.

To do so you may prevent or alter panning from beforePan callback. For more details take a look at demo/limit-pan.html example.

Public API

When you call svgPanZoom method it returns an object with following methods:

  • enablePan
  • disablePan
  • isPanEnabled
  • pan
  • panBy
  • getPan
  • setBeforePan
  • setOnPan
  • enableZoom
  • disableZoom
  • isZoomEnabled
  • enableControlIcons
  • disableControlIcons
  • isControlIconsEnabled
  • enableDblClickZoom
  • disableDblClickZoom
  • isDblClickZoomEnabled
  • enableMouseWheelZoom
  • disableMouseWheelZoom
  • isMouseWheelZoomEnabled
  • setZoomScaleSensitivity
  • setMinZoom
  • setMaxZoom
  • setBeforeZoom
  • setOnZoom
  • zoom
  • zoomBy
  • zoomAtPoint
  • zoomAtPointBy
  • zoomIn
  • zoomOut
  • setOnUpdatedCTM
  • getZoom
  • resetZoom
  • resetPan
  • reset
  • fit
  • contain
  • center
  • updateBBox
  • resize
  • getSizes
  • destroy

To programmatically pan, call the pan method with vector as first argument:

// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

// Pan to rendered point x = 50, y = 50
panZoomTiger.pan({x: 50, y: 50})

// Pan by x = 50, y = 50 of rendered pixels
panZoomTiger.panBy({x: 50, y: 50})

To programmatically zoom, you can use the zoom method to specify your desired scale value:

// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

// Set zoom level to 2
panZoomTiger.zoom(2)

// Zoom by 130%
panZoomTiger.zoomBy(1.3)

// Set zoom level to 2 at point
panZoomTiger.zoomAtPoint(2, {x: 50, y: 50})

// Zoom by 130% at given point
panZoomTiger.zoomAtPointBy(1.3, {x: 50, y: 50})

Zoom is relative to initial SVG internal zoom level. If your SVG was fit at the beginning (option fit: true) and thus zoomed in or out to fit available space - initial scale will be 1 anyway.

Or you can use the zoomIn or zoomOut methods:

// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

panZoomTiger.zoomIn()
panZoomTiger.zoomOut()
panZoomTiger.resetZoom()

If you want faster or slower zooming, you can override the default zoom increment with the setZoomScaleSensitivity method.

To programmatically enable/disable pan or zoom:

// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

panZoomTiger.enablePan();
panZoomTiger.disablePan();

panZoomTiger.enableZoom();
panZoomTiger.disableZoom();

To fit and center (you may try contain instead of fit):

// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

panZoomTiger.fit();
panZoomTiger.center();

If you want to fit and center your SVG after its container resize:

// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

panZoomTiger.resize(); // update SVG cached size and controls positions
panZoomTiger.fit();
panZoomTiger.center();

If you update SVG (viewport) contents so its border box (virtual box that contains all elements) changes, you have to call updateBBox:

var panZoomTiger = svgPanZoom('#demo-tiger');
panZoomTiger.fit();

// Update SVG rectangle width
document.getElementById('demo-tiger').querySelector('rect').setAttribute('width', 200)

// fit does not work right anymore as viewport bounding box changed
panZoomTiger.fit();

panZoomTiger.updateBBox(); // Update viewport bounding box
panZoomTiger.fit(); // fit works as expected

If you need more data about SVG you can call getSizes. It will return an object that will contain:

  • width - SVG cached width
  • height - SVG cached height
  • realZoom - a and d attributes of transform matrix applied over viewport
  • viewBox - an object containing cached sizes of viewport boxder box
    • width
    • height
    • x - x offset
    • y - y offset

Destroy SvgPanZoom instance:

// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

panZoomTiger.destroy();
delete panZoomTiger;

How to test

Before committing you should check your code style by running gulp check.

If you made a change then first build the library. Open ./tests/index.html in your browser. All tests should pass.

If you have PhantomJS installed then you can run gulp test.

Common Issues & FAQ

SVG height is broken

Because the library removes viewBox attribute from the SVG element - you may experience that the height of your SVG changed (usually to 150px). In order to fix that you have to add height to the SVG or object/embed.

Calling library methods throw errors when SVG is hidden

This library does not support working with SVGs that are hidden as some browsers detach child documents from the DOM when those are hidden. See #279 for more details.

Performance issues on initialization

If performance is bad only on initialization of the library, then consider wrapping all SVG's child elements into a <g> beforehand. This way the library will not have to create it and move all children into it (which is the root cause of the issue). See #146 comment.

Performance issues while panning/zooming

Most often those are caused by big SVG files. And in those cases it's browsers not being able to handle those SVGs fast enough. See #277 for more details.

How to limit zooming/panning

For zooming there is minZoom and maxZoom zoom config options.

For panning and custom zoom experiences take a look at limit-pan example.

How to add animations

Currently there're 2 ways of doing animation: via CSS or programatically - see #101 for more details.

Errors for object/embed or dynamically loaded SVGs

You have to ensure that the SVG is loaded and available in DOM before initializing the library.

Check dymanic-load demo.

Supported Browsers

  • Chrome
  • Firefox
  • Safari
  • Opera
  • Internet Explorer 9+ (works badly if viewBox attribute is set)

CDN

You can use jsdelivr as a CDN. It supports automatic pulling from NPM and GitHub.

For example use https://cdn.jsdelivr.net/npm/[email protected]/dist/svg-pan-zoom.min.js to load version 3.5.0.

For more usage examples check jsdelivr usage.

Related Work

This library used the SVGPan library as a starting point. SVGPan is intended for use with the SVG 'script' element, whereas svg-pan-zoom is intended for use with the HTML 'script' element.

Wrapper Libraries (feel free to add to this -- pull requests welcome!)

License

The code from the SVGPan library is licensed under the following BSD license:

Copyright 2009-2010 Andrea Leofreddi <[email protected]>. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of
     conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list
     of conditions and the following disclaimer in the documentation and/or other materials
     provided with the distribution.

THIS SOFTWARE IS PROVIDED BY Andrea Leofreddi "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Andrea Leofreddi OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

* The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of Andrea Leofreddi.

The code from the updates and changes to SVGPan are licensed under the same BSD license, with the copyright for the code from each change held by the author of that code.

svg-pan-zoom's People

Contributors

aleofreddi avatar alexanderpico avatar ariutta avatar brunonocetti avatar bumbu avatar caioertai avatar dependabot[bot] avatar dlants avatar elcferreira avatar frencil avatar hassanshaikley avatar ionicabizau avatar jci-jnewell avatar jeremyvignelles avatar jlecordier avatar jvasile avatar kevinlaw91 avatar ksimard avatar kubohiroya avatar kyranjamie avatar mangowi avatar oller avatar pizzaisdavid avatar risingson avatar rush avatar timmh avatar tonygentilcore avatar vprus avatar yanick avatar yimiprod avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svg-pan-zoom's Issues

Panning while zooming

If a user starts zooming and then concurrently starts panning, the minZoom setting is ignored.

Uncaught errors thrown by events targeting children of a <foreignObject> element

I'm working on a project which requires text wrapping and the approach I'm taking here is to embed an XHTML document inside a <foreignObject> element, as below.

<g>
  <polygon points="..."></polygon>
  <foreignObject>
    <body>
      <p>Blah blah, lorem ipsum something</p>
    </body>
  </foreignObject>
</g>

Now this renders just fine, panning is functional etc. but errors are thrown by events targeting anything inside the <foreignObject> element as neither evt.target.ownerSVGElement or evt.target.correspondingElement.ownerSVGElement are defined for these elements.

I've hacked in a "fix" which walks up the document tree until they are defined, but I doubt (in my limited experience with SVG/XML) that's a valid approach for much outside of a narrow use case so there's no pull request here.

<use [...] /> is cut off

When I use symbols and uses to decrease the size of an svg because I use the same element multiple times I get some issues with svg-pan-zoom:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/2000/svg">
<defs>
  <symbol id="my_id">
    <circle r="10" />
  </symbol>
</defs>
<g>
  <use xlink:href="#my_id"/>
</g>
<g transform="scale(1.5)">
  <use xlink:href="#my_id" x="2000" y="1000" />
</g>

When I use this svg on a screen that has not a height of 100px and a width of 2000px the second element is not visible.
In my actual project I have paths that are displayed until the screen ends, but when I pan the svg up the path is cut off.

can't find getCTM definition

I first called svgPanZoom to a svg element, it succeeded, and then, i imported another svg element in the same page(hide the first svg element with no refreshing the page) and called the svgPanZoom with the new svg element, but the code got error on:

var newCTM = this.viewport.getCTM()

After the second call, the newCTM is null, and i can't find the definition of getCTM method.

BTW, the code of svgPanZoom.js in the example in the multi-svg is different from the code in the dist folder. I used the svgPanZoom.js in the dist folder.

Could u plz help me solve this problem? thanks

D'ont zoom with DblClick

In src/svg-pan-zoom.js line 348 change:

this.zoomScaleSensitivity
by
this.options.zoomScaleSensitivity

Remove drag posibility

It seems that dragging is working wrong. Also it seems to be an unnecessary feature.
Should it be removed?

Add "viewport" g element if it is not present

It would be nice if the library added a "viewport" g element if it didn't exist in the target SVG. This behavior could be enabled by default but optionally disabled:

svgPanZoom.init({
  addViewport:false // default is true
})

Improve viewbox selection/creation

As per this discussion:

  • Allow specifying either an id or a class for selecting a group (g element) as a viewport. If such element was found - add to it default class name (.svg-pan-zoom_viewport)
  • If there is no selector specified we can look for a g element that contains everything except defs. If such element is found - add to it default class name and use is as viewport
  • If there is no such element than we create a new g element, set to it default class name, and append all SVG children elements.

This may improve performance in some cases. Also in the end there will always be a group (g element) with a known class name.

Before and after zoom/pan callbacks

Zooming

Right now zooming most often involves not only zooming but also panning (ex. to keep the visible part centered). Should we also trigger the pan callback when a zoom involves panning?

Callbacks timing

beforeZoom, beforPan, onZoom and onPan are triggered always when there is a request for zoom or pan. But sometimes a request for zoom does nothing (ex. if SVG is zoomed at max value then requesting to zoom it even more will do nothing).

Maybe we should change this behaviour so that these callbacks will be triggered only before and after an actual change?

My concern about this is that if we'll trigger beforeZoom and beforePan only when there are changes it means that we already did the computation of new viewport attributes. But someone may use before callbacks to alter the state of plugin so that computation of new viewport attributes will give different results. On the other side this is a bad behaviour and it is better to do such things after the event occured.

So most probably I'll change callbacks timing so that they'll fire only then an actual change will occur.

@ariutta what do you think about these 2 questions?

JSHint

@bumbu, I've been using semicolons and you've been omitting them.

Can you create a .jshintrc file with whichever options you prefer, e.g. asi: true? I'll follow that so we're consistent.

Mouse focus indicator

@samadlotia suggested having a visual indicator of mouse focus state. This would be useful for the user to know whether the mouse is in the state required for doing pan/zoom.

zoom origin

Hi,

Any chance you will be fixing the // TODO zoom origin isn't center of screen items in zoomIn() and zoomOut() anytime soon?

Otherwise a lovely script!

thanks!

disable zooming with the mouse wheel

Is it possible to disable zooming with the mouse wheel and keep only the zoom control by buttons?

I've seen that can disable double click for zoom but not the wheel

Image resets on first mouse in

When the mouse first enters the SVG container the image resets to the top-left origin and 1x zoom, regardless of how it was initially displayed. This behaviour can be seen on the tiger demo where the image fits the container when the page loads but resets on mouse in.

Is it possible to have the correct initial zoom and position calculated so that the image doesn't suddenly move and re-zoom on mouse in?

Add 'beforePan' option

Thanks a lot for a great library!

I have a huge svg with lots of embedded images (via <pattern><image xlink:href...>).

Pan/Zoom performance is really bad with images, but disabling on beforeZoom and re-enabling onZoom (after a timeout) solves that problem. However for pan the beforePan option is missing :(

@ariutta could you possibly add the beforePan option, similar to beforeZoom?

Furthermore it would be interesting to know more about the moment that onZoom/onPan fires: is it just at the end of the mouse gesture, or does it fire for every single zoom-/pan-step?

pan/zoomAtPoint

Hi,

lovely tool it is, however I have a problem. I do not understand how to put pan/zoomAtPoint to use.
Regardless what numbers I enter I always end up in the left uppermost corner. Do you have any ideas on that? How can I get in contact to send you over Code?

Cheers and thanks in advance!
Ernst

double click zoom

Was double click zoom intended for desktop use? I don't feel like double click zoom is a natural desktop interaction... (I've only seen it used in google maps)

Problem: It is annoying when it's unintentionally triggered.

Solutions:

  1. Add an option to disable double click zoom completely
  2. Better mobile detection (if it's only intended to be a mobile feature)

Pan, Zoom and Fullscreen controls

In the init method, we need the argument parameters specifying whether to include controls for panning, zooming and toggling fullscreen mode.

The controls would look something like the ones in this diagram, but they would be SVG elements that would be added to the target SVG if the user specified "true" for the arguments displayPanControl, displayZoomControl and displayFullScreenControl. The user would call something like this:

svgPanZoom.init({
  'selector': '#my-svg', // optional selector. If left blank, svg-pan-zoom will look for the first SVG document in your HTML document.
  'panEnabled': true, // optional. values must be true or false. default is true.
  'displayPanControl': true, // optional. values must be true or false. default is true.
  'zoomEnabled': true, // optional. values must be true or false. default is true.
  'displayZoomControl': true, // optional. values must be true or false. default is true.
  'minZoom': 0.5, // optional. values must be scalar. default is 0.5.
  'maxZoom': 10, // optional. values must be scalar. default is 10.
  'zoomScaleSensitivity': 0.2, // optional. values must be scalar. default is 0.2.
  'displayFullScreenControl': true, // optional. values must be true or false. default is true.
  'dragEnabled': false, // optional. values must be true or false. default is false.
  'onZoom': function(scale) { ... }  // optional. Callback function when zoom changes.
});

This call would be handled by the init method. This feature would also require adding code to actually create and append the control elements to the SVG document.

The fullscreen control would work with the library screenfull.js.

Controls in Firefox

If you check out "inline-viewbox-zoomed.html" in the demos directory, you'll see that the controls don't show up.

Component resizing in Firefox

I use an inline SVG, encapsulated into a

tag, to control its size. It lppks like that:

<div width="100%">
 <svg></svg>
</div>

The pan and zoom function works great in both Safari and Chrome, but when I am using Firefox, when I try to zoom/pan, the whole component shrinks to a 5th of its initial size. The svg inside the component stays the same, the resizing affects only the component.

Any idea why?

Missing documented methods: destroy and reset

Hello, first of all I've started to use this plugin in the past days, and I'm impressed by the fact that actually it "just works". This cannot be said about most of the pulgins nowadays.

I have some issues though when it came to digging deeper. The documentation mentions two methods: destroy and reset, with their self-explanatory behaviour. However, when I try to call them, both of them seem to be undefined. Were they deprecated because of something? If yes, what should I use as an alternative?

I need the reset function to reset the zoom and pan before sending the SVG to the server to export to image. And I need the destroy because the SVG is removed and recreated after AJAX calls multiple times according to user refinements. I wanted to call destroy to properly handle this scenario, because else I guess the handelrs are saying attached, denying the removed stuff from being GC-d. Correct me if I'm wrong.

svg.setAttribute overwrites current style attribute

Many of my svg drawings are the style="background-color: rgb(0, 0, 0);"

In setupHandlers function:
//Needed for Internet Explorer, otherwise the viewport overflows.
if (svg.parentNode !== null) {
svg.setAttribute('style', 'overflow: hidden');
}

setAttribure overwrites my current svg style attribure.

Its possible to add element "overflow" to style attribute instead of overwrite attribute if style already exist?

Thanks for your great job.

[enhancement] Add missing bower.json.

Hey, maintainer(s) of ariutta/svg-pan-zoom!

We at VersionEye are working hard to keep up the quality of the bower's registry.

We just finished our initial analysis of the quality of the Bower.io registry:

7530 - registered packages, 224 of them doesnt exists anymore;

We analysed 7306 existing packages and 1070 of them don't have bower.json on the master branch ( that's where a Bower client pulls a data ).

Sadly, your library ariutta/svg-pan-zoom is one of them.

Can you spare 15 minutes to help us to make Bower better?

Just add a new file bower.json and change attributes.

{
  "name": "ariutta/svg-pan-zoom",
  "version": "1.0.0",
  "main": "path/to/main.css",
  "description": "please add it",
  "license": "Eclipse",
  "ignore": [
    ".jshintrc",
    "**/*.txt"
  ],
  "dependencies": {
    "<dependency_name>": "<semantic_version>",
    "<dependency_name>": "<Local_folder>",
    "<dependency_name>": "<package>"
  },
  "devDependencies": {
    "<test-framework-name>": "<version>"
  }
}

Read more about bower.json on the official spefication and nodejs semver library has great examples of proper versioning.

NB! Please validate your bower.json with jsonlint before commiting your updates.

Thank you!

Timo,
twitter: @versioneye
email: [email protected]
VersionEye - no more legacy software!

How can I make a limit on the the pan range?

I mean, my svg is in a div container, and I don't want the svg pan too right or too left which can cause the user see the empty container. Can I make a limit to my svg in the container? Allow it only to move to the right side by 50px e.g.?
Thanks.

Zoom range is affected by the inclusion of <foreignObject>

I've noticed that the zoom range changes when including a <foreignObject> element in the document, but can't figure out why that is. It's restricted in the initializer to [0.05, default] but won't zoom in below a scale of 2.

<foreignObject> has a fixed width/height and x/y position, and doesn't necessarily have to have any child elements present for this to manifest.

This is using the latest release, too.

invalid zoom set to min/max zoom

Do you think it would be better to set zoom requests which go beyond the min/max zoom to just go to min/max zoom? That way it's doing something rather than nothing.

It works fine how it is now, but I just think this would be better.

Throttling solved?

@bumbu, the shadow viewport is really cool! It replaces the throttling I was trying to add here in setCTM(), right? And it avoids the problems my code had when synchronizing the zoom between two different SVGs? If so, I can remove my commented out lines 146, 147 and 164.

fit() raises TypeError in Firefox

This is on Firefox 30.0 using your latest (8f78d35) version:

If I don't put fit: false into init(), Firefox shows the following error in Firebug

TypeError: Value being assigned to SVGMatrix.a is not a finite floating-point value.
http://localhost:8000/svg-pan-zoom.js Line 275

and initialization does not finish.

Updating too fast will not work

Initialising 2 SVGs with fit and center options will work only on second SVG. This is because setCTM is a global method that relies on throttling. So if both SVGs are intilialized one after another (or with a delay smaller than 1/refreshRate) than most probably first SVG will not be adjusted.

This bug affects any use case in which updating CTM multiple times in a row is required (ex. programatically updating zoom then pan).

I see few solutions to this issue:

  • Namespacing throttling function so each event will have it's own throttling. May also require caching changed values or queueing events and executing all of them
  • Removing throttling

Mobile support

This plugin looks great. I tried along with phonegap which is working only with controlIconsEnabled property. Any plan for to support pin & zoom event?

Thank you,
Praveen Jeganathan

Keep SVG content visible when zooming

Right now, it's possible to zoom into a blank area outside the bounding box of the SVG content. The view should never entirely leave the bounding box of the SVG content.

get zoom and set zoom values

Right now getZoom and zoom methods accept and return a and d attributes (x and y scale) of SVGMatrix. So these values reflect inner state of the application.

On the other hand minZoom and maxZoom are relative values. They are relative to initial SVG scale.

For example if minZoom: 0.5:

  • When there is a SVGSVGElement that has option fit: false, no viewBox and transform attributes then application initial scale will be 1. In this case:

    instance.zoom(0.5)
    instance.getZoom() == 0.5
    
    instance.zoom(0.1)
    instance.getZoom() == 0.5
  • If we have an SVG that has an option fit: true and inner viewport is 2 times bigger than SVG size then initial scale of application will be 0.5. In this case minimal real scale will be 0.25 (0.5 / 2):

    instance.zoom(0.5)
    instance.getZoom() == 0.5
    
    instance.zoom(0.1)
    instance.getZoom() == 0.25

The same goes with maxZoom.

This is mostly a magical behaviour for API consumers who doesn't know about application internals. I do see 2 solutions for these:

  1. minZoom and maxZoom should refer to viewport scale
  2. get/set zoom should work with relative values

I would prefer second solution as it will mean that:

  • Application will be initialized and the scale of viewport will be considered as zoom(1)
  • minZoom of 0.5 will mean that you can zoom out at most 2x times
  • maxZoom of 2 will mean that you can zoom in at most 2x times

These change will affect only those applications that mak use of API.

@ariutta what's your opinion on that?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.