npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@alphanull/zoomer

v1.0.0

Published

Zoomer is a lightweight, dependency-free, physics-based pan/zoom/rotate library for the browser designed to feel like native iOS interaction.

Downloads

31

Readme

License Version JSDoc npm package minimized gzipped size

Zoomer

Zoomer is a lightweight, dependency-free physics engine for ultra-smooth pan, zoom, and rotate interactions in the browser. Designed to bring a polished, iOS-like tactile feel to any web element, it features natural inertia, elastic boundaries (rubber-banding), and precision pivot tracking.

Why Zoomer?

Most pan-and-zoom libraries feel mechanical. Zoomer is built with a custom physics engine to make interactions feel alive and organic. Whether you're building an image gallery, a map viewer, or a complex workspace, Zoomer provides the high-end haptics users expect from modern touch interfaces.

Demo

To see Zoomer in action, hop over to: https://alphanull.github.io/Zoomer/

Features

  • Direct Manipulation: Naturally pan, zoom, and rotate using multi-touch gestures or mouse, including mousewheel support.
  • iOS-style Physics: Built-in inertia, friction, and elastic rubber-band resistance at boundaries.
  • Precision Pivot Tracking: Zooming and rotating always happen around the center of the gesture, keeping your focus point stable.
  • Mousewheel Precision: Smooth, cursor-centered zooming with automatic pivot adjustment.
  • Intelligent Fitting: Built-in contain and cover strategies to perfectly align elements within their containers, with optional autoMinScale to prevent zooming below the fit scale.
  • SVG Lossless Zoom Support: Crisp, pixel-perfect SVG rendering at any zoom level. Automatically optimized for inline SVG, <img> SVG, and CSS background SVG. No pixelation, even at extreme zoom levels.
  • Smart GPU Acceleration: Selective GPU layer creation - will-change is only set during active interaction, saving resources when idle. Perfect for complex SVGs on mobile devices.
  • High Performance: Optimized with a layout cache and ResizeObserver to eliminate layout thrashing. Zero CPU usage when idle.
  • Highly Customizable: Fine-tune every aspect with 20+ options - from physics parameters (friction, stiffness, elasticity) to interaction modes (pan axes, touch behavior) and lifecycle callbacks.
  • Zero Dependencies: Pure Vanilla JS, lightweight, and ready to drop into any project.

Installation

via NPM

npm install @alphanull/zoomer

via CDN

Download latest version from jsDelivr Download latest version from unpkg

Initialization

Zoomer can be used as ES6 module (recommended) but also via require in NodeJS or with direct access to a global variable:

ES6

import Zoomer from '@alphanull/zoomer';

CommonJS

const Zoomer = require('@alphanull/zoomer');

Global Variable

<script src="path/to/Zoomer.min.cjs"></script>
const Zoomer = window.Zoomer;

Usage

const element = document.querySelector('.my-element');
const container = document.querySelector('.container'); // container defines boundaries

const zoomer = new Zoomer(element, {
  container: container,
  fitContainer: 'contain',
  boundsEnabled: true,
  minScale: 1,
  maxScale: 4
});

zoomer.applyTransform({ x: 0, y: 0, scale: 2, rotation: 45 });

Configuration Options

| Option | Default | Description | |----------------------|------------|---------------------------------------------------------------------------| | initialX | 0 | Initial horizontal translation. | | initialY | 0 | Initial vertical translation. | | initialScale | 1 | Initial scale factor. | | initialRotation | 0 | Initial rotation in degrees. | | minScale | 0.5 | Minimum allowed scale factor. | | maxScale | 2 | Maximum allowed scale factor. | | friction | 0.1 | Friction factor (0 to 1). Higher values stop faster. | | springStiffness | 0.2 | Strength of the bounce-back effect. | | resistance | 0.8 | Resistance at boundaries (0 to 1). 1 = hard limit. | | maxElasticity | 100 | Max pixels the element can stretch beyond limits. | | physicsEnabled | true | Enable/disable inertia and spring-back. | | panEnabled | 'on' | Panning mode: 'on', 'off', 'xAxis', or 'yAxis'. | | panMultiTouchOnly | false | If true, panning with single touch is disabled (allows normal scrolling on touch devices). | | zoomEnabled | true | Enable/disable zooming (touch & wheel). | | rotationEnabled | true | Enable/disable rotation (touch). | | keyboardEnabled | true | Enable/disable keyboard controls (arrows, +/-). | | doubleTapEnabled | true | Enable/disable double tap to toggle zoom. | | wheelModifier | 'none' | Modifier key for wheel zoom: 'none', 'alt', 'control', or 'meta'. | | wheelRotationModifier | 'alt' | Modifier key for wheel rotation: 'none', 'alt', 'control', 'meta', or 'shift'. | | container | null | DOM element used for boundaries and initial fitting. | | boundsEnabled | false | If true, the element will be contained within the container. | | fitContainer | 'none' | Initial scaling strategy: 'none', 'cover', or 'contain'. | | autoMinScale | false | If true, prevents zooming below fitScale when fitContainer is set. | | onRender | null | Custom render function: (state, element) => void. | | onUpdate | null | Callback for state updates: (state) => void. | | onInteractionStart | null | Triggered when user starts interaction. | | onInteractionEnd | null | Triggered when user stops interaction. |

Public API

| Method | Arguments | Description | |------------------|-----------------------------------------|-----------------------------------------------------------------| | reset | immediate: boolean | Resets the element to its initial state. | | applyTransform | transform: object, immediate: boolean | Programmatically sets X, Y, Scale, and/or Rotation. | | updateLayout | applyFit: boolean | Re-calculates layout. Set true to re-apply container fitting. | | destroy | - | Removes all listeners and stops the update loop. |

Arguments

  • immediate (boolean): If true, the element jumps to the new state instantly. If false (default), the transition is handled by the physics engine for a smooth "homing" effect.
  • transform (object): A partial state object. You only need to provide the properties you want to change:
    • x (number): Target horizontal translation.
    • y (number): Target vertical translation.
    • scale (number): Target scale factor.
    • rotation (number): Target rotation in degrees.

Zoomer State

The state object (accessible via zoomer.state or in callbacks) contains the current transformation and velocity:

| Property | Type | Description | |----------------|-----------|----------------------------------------------------------| | x | number | Current horizontal translation in pixels. | | y | number | Current vertical translation in pixels. | | scale | number | Current scale factor. | | rotation | number | Current rotation in degrees. | | pivotX | number | Last zoom/rotation pivot X (local coordinates). | | pivotY | number | Last zoom/rotation pivot Y (local coordinates). | | vx | number | Current velocity on the X axis. | | vy | number | Current velocity on the Y axis. | | vs | number | Current scale velocity. | | vr | number | Current rotation velocity in degrees/frame. | | isInteracting | boolean | Whether a user interaction is currently in progress. |

Development

# Install dependencies
npm install
# Build the minified library
npm run build
# Run tests
npm run test
# Generate docs
npm run doc
# Run the demo
npm run demo

Docs

For more detailed docs, see JSDoc Documentation

Browser Support

Zoomer supports all major browsers on all platforms (i.e. macOS, iOS, Windows, Android & Linux) released since ~2019-2020 and later, including Chrome (v79+), Firefox (v75+) and Safari (v13+).

SVG Rendering

Zoomer includes optimizations for crisp SVG rendering at high zoom levels:

  • Chrome/Safari: Perfect sharp rendering for all SVG types (inline SVG, <img> SVG, CSS background SVG)
  • Firefox:
    • Inline SVG: Sharp rendering (best quality)
    • ⚠️ <img> SVG: Improved but may show blur at high zoom
    • ⚠️ CSS background SVG: Improved but may show stronger blur at high zoom

For the best rendering quality across all browsers, inline SVG is recommended. The library automatically detects SVG elements and applies appropriate rendering optimizations.

License

MIT

Copyright © 2025-present Frank Kudermann @ alphanull.de