Panzoom

repository·main·Indexed 25 days ago

https://github.com/timmywil/panzoom

A lightweight (~3.7kb gzipped) library for adding hardware-accelerated panning and zooming functionality to any HTML or SVG element using CSS transforms. Version 4.6.2 provides programmatic control via a PanzoomObject, customizable transform applications, and support for mousewheel zooming, pinch-to-zoom, and containment restrictions.

Tokens
5.3K
Snippets
13
Records
29
Agent score
80%

What's inside @panzoom/panzoom

  1. Understand the Panzoom event detail object

    main

    Every Panzoom event provides a detail object containing the current transformation state and the triggering event. The properties available in detail are:

    • x: The current x-coordinate.
    • y: The current y-coordinate.
    • scale: The current zoom scale.
    • originalEvent: The original browser event that triggered the panzoom action (e.g., pointerdown, touchstart, or mousedown). This is applicable for events like panzoomstart and panzoomend.
  2. Silence Panzoom events

    main

    You can prevent Panzoom events from firing by setting the silent option to true. This can be done:

    1. Globally during initialization.
    2. Locally by passing { silent: true } to specific method calls like pan(), zoom(), or reset().
  3. Handle async behavior with the `contain` option

    main

    When the contain option is enabled, Panzoom needs to retrieve element dimensions, which requires the scale to be painted. If you attempt to call zoom() and pan() synchronously, the second call might fail or behave unexpectedly. In these cases, use a setTimeout to ensure the scale has been applied before panning.

    // If things aren't looking right when using 'contain':
    panzoom.zoom(2)
    setTimeout(() => panzoom.pan(100, 100))
  4. Listen to Panzoom custom events

    main

    Panzoom emits custom events on the element it is controlling. You can listen to these using the native addEventListener API. The event object passed to the listener contains a detail object with the current state of the element.

    elem.addEventListener('panzoomchange', (event) => {
      console.log(event.detail) // => { x: 0, y: 0, scale: 1 }
    })
  5. Install Panzoom

    main

    You can install Panzoom using npm or yarn. It is a small library (~3.7kb gzipped) that uses CSS transforms for hardware-accelerated panning and zooming of any element (images, videos, iframes, canvas, text, etc.).

    $ npm install --save @panzoom/panzoom
    
    # or
    
    $ yarn add @panzoom/panzoom
  6. Custom event binding with handleDown, handleMove, and handleUp

    main

    If you need to control how events are captured (e.g., to integrate with a specific framework or custom event logic), you can use the handleDown, handleMove, and handleUp methods.

    To avoid double-binding when using these manually, initialize Panzoom with the noBind: true option. Note that handleDown is bound to the Panzoom element, while handleMove and handleUp are typically bound to the document to ensure smooth interaction when the pointer leaves the element.

    const panzoom = Panzoom(elem, { noBind: true })
    
    elem.addEventListener('pointerdown', (event) => {
      console.log(event)
      panzoom.handleDown(event)
    })
    
    document.addEventListener('pointermove', panzoom.handleMove)
    document.addEventListener('pointerup', panzoom.handleUp)
  7. Enable clickable links/anchors within Panzoom

    main

    By default, Panzoom handles events in a way that might prevent links or anchors from working. To make specific elements clickable, you have three options:

    1. Add the class specified in options.excludeClass (the default is "panzoom-exclude") to the element.
    2. Add a reference to the element to the exclude option in the Panzoom configuration.
    3. Call event.stopImmediatePropagation() in an event handler on the clickable element.
  8. Fix SVG text resizing issues

    main

    If you are using Panzoom with SVG <text> elements and encounter weird resizing behavior, add the text-rendering="geometricPrecision" attribute to your text elements.

    <text text-rendering="geometricPrecision" x="40" y="120">Hello World</text>
  9. Customize the transform application with setTransform

    main

    You can override the default transform setter to include additional CSS properties like rotation. The callback receives the element, the current values (scale, x, y), and the options.

    // This example always sets a rotation
    // when setting the scale and translation
    const panzoom = Panzoom(elem, {
      setTransform: (elem, { scale, x, y }) => {
        panzoom.setStyle('transform', `rotate(0.5turn) scale(${scale}) translate(${x}px, ${y}px)`)
      }
    })
  10. Use zoomWithWheel for mousewheel zooming

    main

    The zoomWithWheel method provides a convenient way to implement zooming via the mouse wheel. It should be attached to the element's parent to capture wheel events effectively.

    Note:

    • The focal point adjustment is not affected by the disablePan option.
    • animate is always disabled when using this method.
    • On some devices (like Mac), shift + wheel might be interpreted as horizontal scrolling; Panzoom assumes the user intends to zoom in these cases.
    // Bind to mousewheel
    elem.parentElement.addEventListener('wheel', panzoom.zoomWithWheel)
    
    // Bind to shift+mousewheel
    elem.parentElement.addEventListener('wheel', function (event) {
      if (!event.shiftKey) return
      panzoom.zoomWithWheel(event)
    })
  11. Basic Usage of Panzoom

    main

    To use Panzoom, initialize it by passing an element and an optional configuration object. Panzoom automatically binds panning and pinch-to-zoom gestures (unless disablePan is set to true). You can also manually control zooming via methods like zoomIn or zoomWithWheel.

    const elem = document.getElementById('panzoom-element')
    const panzoom = Panzoom(elem, {
      maxScale: 5
    })
    
    // Manual control
    panzoom.pan(10, 10)
    panzoom.zoom(2, { animate: true })
    
    // Binding to UI elements
    button.addEventListener('click', panzoom.zoomIn)
    elem.parentElement.addEventListener('wheel', panzoom.zoomWithWheel)