@dash14/svg-pan-zoom

中文文档
4.1.0发布于 2026/10/30BSD-2-ClauseTypeScriptES Module零依赖构建来源已验证近 30 天下载 8.7万

JavaScript library for panning and zooming an SVG image from the mouse, touches and programmatically.

原始使用文档
文档目录24 节
  1. Support
  2. Bugs and Issues
  3. Solved Bugs and Implemented Features
  4. Contributions/Pull Requests
  5. Demos
  6. How To Use
  7. Embedding remote files
  8. Using a custom viewport
  9. Listening for pan/zoom events on a child SVG element
  10. Custom events support
  11. Keep content visible/Limit pan
  12. Public API
  13. How to test
  14. Common Issues & FAQ
  15. SVG height is broken
  16. Calling library methods throw errors when SVG is hidden
  17. Performance issues on initialization
  18. Performance issues while panning/zooming
  19. How to limit zooming/panning
  20. How to add animations
  21. Errors for object / embed or dynamically loaded SVGs
  22. Supported Browsers
  23. Related Work
  24. License

This library was forked from https://github.com/bumbu/svg-pan-zoom for the purpose of using it in v-network-graph.

The following changes have been made from the original:

  • Add support pan and zoom with multi-touch.
  • Export type definitions in typescript.
  • Do not access window and document when exporting the module.
  • Specify {passive: false} explicitly to the event listeners to prevent warnings.
  • Ship only an ES module: no <script> global, AMD or CommonJS build.

It is published to npm as @dash14/svg-pan-zoom:

npm install @dash14/svg-pan-zoom

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.

Support

Bugs and Issues

This fork does not take issues; report problems in v-network-graph's issues with a reproducible example, the library version, and your browser and OS.

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.

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 pnpm installed locally
  • In console:
    • cd into project folder
    • Run pnpm install
    • Running pnpm start will listen for source files changes (in src folder) and will automatically build distribution files
    • Running pnpm run build will build distribution files
    • Running pnpm run format will format the source files
    • Running pnpm test will type-check dist/svg-pan-zoom.d.ts and run the tests in headless Chromium. Install Chromium once with pnpm exec playwright install --only-shell chromium
  • Implement the change using pnpm start or pnpm run build
  • After change is done format it with pnpm run format and test it with pnpm test
  • Commit only meaningful changes, and commit the rebuilt distribution files (dist folder) with them. CI fails when dist differs from what the source builds to
  • Push your changes into your fork
  • Create a pull request

Demos

The examples in demo run from a clone: start pnpm run server and open http://localhost:3001/demo/.

How To Use

Import the package, then call the init method:

import svgPanZoom from '@dash14/svg-pan-zoom';

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 form 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 the element's load event, added before the element can finish loading:

import svgPanZoom from '@dash14/svg-pan-zoom';

var embed = document.createElement('embed');
embed.type = 'image/svg+xml';
embed.src = '/path/to/my/file.svg';
embed.addEventListener('load', function(){
  svgPanZoom(embed);
});
document.body.appendChild(embed);

For an element written in the page's HTML, listen to the window's load event instead, which comes after the element has loaded.

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
});

A viewport that viewportSelector finds keeps its class attribute as it is. A viewport that svg-pan-zoom picks or creates gets the svg-pan-zoom_viewport class, so that a new instance on the same SVG finds it again with the default selector. If you create a new instance on an SVG that already had one with a custom viewportSelector, pass the same viewportSelector again.

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.

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 format your code by running pnpm run format.

The tests run against dist/, so build the library with pnpm run build first. Then run pnpm test, which runs them in headless Chromium; install it once with pnpm exec playwright install --only-shell chromium.

To watch the tests in a browser window while debugging, run pnpm run test:headed. It needs the full Chromium: pnpm exec playwright install chromium.

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 bumbu/svg-pan-zoom#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 bumbu/svg-pan-zoom#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 bumbu/svg-pan-zoom#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 bumbu/svg-pan-zoom#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 dynamic-load demo.

Supported Browsers

Current versions of Chrome, Edge, Firefox and Safari.

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.

版本与发布记录

@dash14/svg-pan-zoom 共发布 11 个版本,首次发布于 2021/10/18;过去 12 个月发布了 5 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.1.0latest2026/10/3012 天前
4.0.12026/10/2319 天前
4.0.02026/10/2219 天前
3.6.102026/10/2021 天前
3.6.10-beta.0next2026/10/1923 天前
3.6.92022/08/114 年前

关于 @dash14/svg-pan-zoom 的常见问题

@dash14/svg-pan-zoom 是什么?

JavaScript library for panning and zooming an SVG image from the mouse, touches and programmatically.

如何安装 @dash14/svg-pan-zoom?

在项目目录运行 npm install @dash14/svg-pan-zoom,或使用 pnpm add / yarn add / bun add。

@dash14/svg-pan-zoom 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dash14/svg-pan-zoom 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@dash14/svg-pan-zoom 可以商用吗?

@dash14/svg-pan-zoom 使用 BSD-2-Clause 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dash14/svg-pan-zoom 的下载量有多少?

根据 npm 官方下载统计,@dash14/svg-pan-zoom 在 2026/10/12 – 2026/11/10 这 30 天内被下载 87,297 次,日均约 2,910 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dash14/svg-pan-zoom 还在维护吗?

最新版本 4.1.0 发布于 2026/10/30(12 天前);至今共发布 11 个版本,其中过去 12 个月发布了 5 个;首次发布于 2021/10/18。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。