SkillAgentSearch skills...

Panzoom

A library for panning and zooming elements using CSS transforms :mag:

Install / Use

/learn @timmywil/Panzoom
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Panzoom

Examples


Panzoom is a small library (~3.7kb gzipped) to add panning and zooming functionality to an element. Rather than using absolute positioning or setting width and height, Panzoom uses CSS transforms to take advantage of hardware/GPU acceleration in the browser, which means the element can be anything: an image, a video, an iframe, a canvas, text, WHATEVER.

For common support questions, see the FAQ.

Browser support

Here is a list of currently supported browsers.

Mobile support

iOS, Android, and Windows Mobile are supported.

Panzoom includes support for touch gestures and even supports pinch gestures for zooming. It is perfectly suited for both mobile and desktop browsers. It uses pointer events by default wherever supported.

SVG support

Panzoom supports panning and zooming SVG elements directly.

In IE11, CSS animations/transitions do not work on SVG elements, at least for the transform style. They do work in other browsers.

One could implement transitions manually in IE11 using the setTransform option and integrating a tweening library for javascript animations (such as tween.js).

Installing

With npm:

$ npm install --save @panzoom/panzoom

With yarn:

$ yarn add @panzoom/panzoom

Panzoom uses UMD and can be loaded a lot of ways.

With ES6 imports:

import Panzoom from '@panzoom/panzoom'

With commonjs or browserify:

const Panzoom = require('@panzoom/panzoom')

With an AMD loader in an anonymous module:

define(['@panzoom/panzoom'], function (Panzoom) {
  const elem = document.getElementById('panzoom-element')
  Panzoom(elem)
})

With a script tag:

<script src="/js/panzoom.js"></script>

With a script tag from a CDN:

<script src="https://unpkg.com/@panzoom/panzoom@4.6.1/dist/panzoom.min.js"></script>

Usage

const elem = document.getElementById('panzoom-element')
const panzoom = Panzoom(elem, {
  maxScale: 5
})
panzoom.pan(10, 10)
panzoom.zoom(2, { animate: true })

// Panning and pinch zooming are bound automatically (unless disablePan is true).
// There are several available methods for zooming
// that can be bound on button clicks or mousewheel.
button.addEventListener('click', panzoom.zoomIn)
elem.parentElement.addEventListener('wheel', panzoom.zoomWithWheel)

FAQ

1. What is transform-origin and why is it added to the panzoom element?

  • The transform-origin is the origin from which transforms are applied. Panzoom ensures the defaults are set to what it expects to calculate focal point zooming.
  • HTML elements default to '50% 50%'.
  • SVG elements default to '0 0'.

2. I am using Panzoom with an <object> tag and it's not working. What's wrong?

Object elements can eat up events, making it so they never reach Panzoom. To fix this, disable pointer events (pointer-events: none) on the <object> tag and call Panzoom using a wrapper.

3. My links aren't working! How do I enable an anchor within a panzoom element?

Add class options.excludeClass (default is "panzoom-exclude") to whatever element you want to be clickable. Panzoom will check for this class before handling the event. Alternatively, add a reference to the element to the exclude option, or call event.stopImmediatePropagation() in an event handler on the clickable element.

A note on the async nature of Panzoom

In some cases, setting one thing and then setting another synchronously will not work as intended.

For instance, the following usually works fine.

const panzoom = Panzoom(elem)
panzoom.zoom(2)
panzoom.pan(100, 100)

However, you might find that the things start breaking when the contain option is set.

This is due to the fact that in order for Panzoom to retrieve proper dimensions, the scale needs to be painted.

If you find that things aren't looking quite right, try the following instead...

panzoom.zoom(2)
setTimeout(() => panzoom.pan(100, 100))

4. I'm using Panzoom with SVG text elements and am seeing some weird text resizing. How do I fix this?

Add text-rendering="geometricPrecision" to your <text> elements.

<text text-rendering="geometricPrecision" x="40" y="120">Hello World</text>

5. I'm using Panzoom on a canvas element that renders a PDF. How do I avoid the PDF getting blurry when scaled?

See this stackoverflow question


Documentation

Panzoom()

Panzoom(elem, options?): [PanzoomObject](#PanzoomObject)

Defined in: panzoom.ts:60

Parameters

elem

HTMLElement | SVGElement

options?

[PanzoomGlobalOptions](#PanzoomGlobalOptions)

Returns

[PanzoomObject](#PanzoomObject)

PanzoomOptions

Includes MiscOptions, PanOptions, and ZoomOptions

PanzoomGlobalOptions

Identical to PanzoomOptions, but excludes the force option.

MiscOptions

These options can be passed to Panzoom(), as well as any pan or zoom function. One exception is force, which can only be passed to methods like pan() or zoom(), but not Panzoom() or setOptions() as it should not be set globally.

Defined in: types.ts:19

Indexable

[key: string]: any

Pass through any options like data

Properties

animate?

optional animate: boolean (Default: false)

Defined in: types.ts:21

Whether to animate transitions


canvas?

optional canvas: boolean (Default: false)

Defined in: types.ts:32

This option treats the Panzoom element's parent as a canvas. Effectively, Panzoom binds the down handler to the parent instead of the Panzoom element, so that pointer events anywhere on the "canvas" moves its children. See issue #472.

Note: setting this option to true also changes where the cursor style is applied (i.e. the parent).


duration?

optional duration: number (Default: 200)

Defined in: types.ts:34

Duration of the transition (ms)


easing?

optional easing: string (Default: "ease-in-out")

Defined in: types.ts:36

CSS Easing used for transitions


exclude?

optional exclude: Element[] (Default: [])

Defined in: types.ts:43

Add elements to this array that should be excluded from Panzoom handling. Ancestors of event targets are also checked. e.g. links and buttons that should not propagate the click event.


excludeClass?

optional excludeClass: string (Default: "panzoom-exclude")

Defined in: types.ts:50

Add this class to any element within the Panzoom element that you want to exclude from Panzoom handling. That element's children will also be excluded. e.g. links and buttons that should not propagate the click event.


force?

optional force: boolean

Defined in: types.ts:67

The force option can only be passed directly to zoom and pan methods. It is not a global option and will be ignored if passed to Panzoom() or setOptions().

force should be used sparingly to temporarily override and ignore options such as disablePan, disableZoom, and panOnlyWhenZoomed.

// Overrides disablePan and panOnlyWhenZoomed
panzoom.pan(50, 100, { force: true })
// Overrides disableZoom
panzoom.zoom(1, { force: true })

handleStartEvent()?

optional handleStartEvent: (event) => void (Default: **(e: Event) => {

e.preventDefault()
e.stopPropagation()

}**)

Defined in: types.ts:92

On the first pointer event, when panning starts, the default Panzoom behavior is to call event.preventDefault() and event.stopPropagation() on that event. The former is almost certainly a necessity; the latter enables Panzoom elements within Panzoom elements.

But there are some cases where the default is not the desired behavior. Set this option to override that behavior.

// Only call preventDefault()
Panzoom(elem, {
  handleStartEvent: (event) => {
    event.preventDefault()
  }
})
// Do nothing.
// This can change dragging behavior on mobile.
Panzoom(elem, {
  handleStartEvent: () => {}
})

Parameters

event

Event

Returns

void


noBind?

optional noBind: boolean

Defined in: types.ts:96

Skip binding the default Panzoom event listeners


origin?

optional origin: string

Defined in: types.ts:110

Change this at your own risk. The `

View on GitHub
GitHub Stars2.4k
CategoryDevelopment
Updated18h ago
Forks420

Languages

TypeScript

Security Score

100/100

Audited on Mar 30, 2026

No findings