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

pixi-viewport

v7.0.3

Published

A highly configurable viewport/2D camera designed to work with pixi.js. Features include dragging, pinch-to-zoom, mouse wheel zooming, decelerated dragging, follow target, snap to point, snap to zoom, clamping, bouncing on edges, and move on mouse edges.

Readme

pixi-viewport

A highly configurable viewport/2D camera designed to work with pixi.js.

Features include dragging, pinch-to-zoom, mouse wheel zooming, decelerated dragging, follow target, animate, snap to point, snap to zoom, clamping, bouncing on edges, and move on mouse edges. See the live examples below to try out all of these features.

All features are configurable and removable, so set up the viewport to be exactly what you need.

If pixi-viewport is useful to you, you can sponsor its development on GitHub.

AI-assisted development

Starting in October 2026, Claude (an AI model by Anthropic) assists with editing this code, including code review, bug fixes, and changes to documentation. A maintainer reviews every change before it is released. If you prefer not to use software developed with AI assistance, please take this into account when choosing whether to use pixi-viewport.

v7.0.3

Fixes clamp() with numeric bounds once the bounds fit on screen, for example after zooming out. The view jumped to center on 0..worldWidth instead of on the bounds you passed, so content at negative coordinates couldn't be centered. Underflow (center, or an edge like top-left) now places the bounds you passed. direction: 'all', true bounds and one-sided clamps behave as before.

v7.0.2

Fixes a viewport with no parent, such as one passed straight to renderer.render(viewport). Dragging drifted away from the pointer, the wheel didn't zoom around the pointer, and pinching ran away to an enormous scale, because these measured in the viewport's own coordinates, which change as it moves.

v7.0.1

Fixes loading in Node (server-side rendering, Vitest and other test runners). package.json now has an exports map, so import { Viewport } from 'pixi-viewport' loads the ES module build and shares your copy of pixi.js. Before, Node loaded the UMD build, so that import threw Named export 'Viewport' not found. Deep imports such as pixi-viewport/dist/types keep working. Bundlers aren't affected.

v7.0.0

Tested with pixi.js v8.22. This release fixes many long-standing bugs. Some of those fixes change behavior that apps may rely on, so this is a major version.

Breaking changes:

  • Built-in plugins always run in their default order (drag, pinch, wheel, follow, mouse-edges, edge-scroll, decelerate, animate, bounce, snap-zoom, clamp-zoom, snap, clamp), whatever order you add them in. Previously, each call moved that plugin to the end of a list shared by every viewport, so viewport.clamp().drag() ran drag after clamp. User plugins added with viewport.plugins.add() still go at the end unless you pass an index.
  • clamp() with no options no longer clamps. false for left, right, top, or bottom now means "don't clamp this side" (it was treated as 0).
  • drag-start and drag-end report the pointer's screen position in screen.

New:

  • viewport.edgeScroll() scrolls when the mouse is near the screen edges, with speed in screen pixels per second. It replaces mouseEdges(), which is deprecated but unchanged.
  • drag({ disableOneFingerDrag: true }) ignores one-finger touch drags so the page can scroll.
  • clampZoom({ keepAspectRatio: false }) clamps one axis at a time, for zooming along a single axis.
  • wheel({ trackpadPinch: true, trackpadPinchSpeed: 2.5 }) speeds up trackpad pinch zooming without changing mouse wheel zooming. The default (1) keeps the current speed, which is slow for a pinch.
  • new Viewport({ ignoreWheelFromOtherElements: true }) ignores wheel events that bubble up from other elements, such as HTML overlays.
  • A pixi object inside the viewport can call stopPropagation() on its wheel event to keep the viewport from zooming. With passiveWheel: false, the page doesn't scroll either.
  • getVisibleBounds() takes an optional Rectangle to write into, and the default hit area no longer allocates a new one every frame.
  • The event types (DragEvent, MovedEvent, ZoomedEvent, and others) are exported.
  • A new demo site: a playground with presets and a live code panel, plus examples for embedding a viewport in a scrolling page and for overlays. The API docs are generated with TypeDoc.

Fixed:

  • Clamp now stops deceleration at the edge (no more jitter), and re-clamps when only the screen size changes.
  • follow() works with targets nested in other containers, acceleration no longer exceeds speed, and following a target that gets destroyed stops instead of throwing every frame.
  • Animate's removeOnInterrupt also stops on wheel events.
  • Negative scale (e.g., a y-axis pointing up) no longer breaks input.
  • mouse-edge-start and mouse-edge-end events are emitted, including mouse-edge-end when the plugin is paused or removed while scrolling.
  • snapZoom({ time: 0 }) no longer throws.
  • Touches whose pointerup never arrived (e.g., iOS suspending the page) are cleared when a new gesture starts.
  • Type declarations use .js import extensions (works with moduleResolution: NodeNext) and include JSDoc comments.
  • The UMD build uses the PIXI global.
  • Decelerate and Wheel remove their event listeners when removed.
  • With wheel({ wheelZoom: false }), a plain wheel event the viewport doesn't use no longer stops the page from scrolling (it was blocked whenever passiveWheel was false).

Documented without changing behavior: the wheel percent option and the mouseEdges speed option (see their JSDoc).

v6.0.0

Moves pixi-viewport to pixi.js v8+ - sorry for the confusion.

v5.0.2

Moves pixi-viewport to pixi.js v7.2+.

NOTE: there is a breaking change since in pixi.js v7.2 interactive (boolean) was deprecated in favor of eventMode.

v5

Moves pixi-viewport to pixi.js v7 (thanks @cuire!).

NOTE: there is a breaking change since pixi-viewport moved to pixi's new event system. options.interaction is removed and you need pass options.events to the viewport for it to work properly. The events object can be found at pixi's renderer.events or app.renderer.events.

const viewport = new Viewport({ events: renderer.events });

// or
// const viewport = new Viewport({ events: app.renderer.events });

v4.30.0+

This project was migrated to Typescript (thanks @ShukantPal!). All functionality should be the same. The live Example has been updated.

Live Examples

  • Playground: try every plugin, switch between presets (map, edge scrolling, follow, timeline, bounce), and copy the code for your setup.
  • In a scrolling page: embed a viewport in an article without trapping the mouse wheel or one-finger swipes.
  • Overlays: keep HTML panels and scrollable pixi objects from zooming the viewport underneath.

API Documentation

https://viewport.pixijs.io/api/

Simple Example

import * as PIXI from "pixi.js";
import { Viewport } from "pixi-viewport";

// or with require
// const PIXI = require('pixi.js')
// const Viewport = require('pixi-viewport').Viewport

const app = new PIXI.Application();
await app.init({ resizeTo: window });
document.body.appendChild(app.canvas);

// create viewport
const viewport = new Viewport({
  screenWidth: window.innerWidth,
  screenHeight: window.innerHeight,
  worldWidth: 1000,
  worldHeight: 1000,
  events: app.renderer.events, // pixi's EventSystem is required for input to work
});

// add the viewport to the stage
app.stage.addChild(viewport);

// activate plugins
viewport.drag().pinch().wheel().decelerate();

// add a red box
const sprite = viewport.addChild(new PIXI.Sprite(PIXI.Texture.WHITE));
sprite.tint = 0xff0000;
sprite.width = sprite.height = 100;
sprite.position.set(100, 100);

Installation

npm i pixi-viewport

or

pnpm add pixi-viewport

or

yarn add pixi-viewport

or grab the latest release and use it:

<script src="/directory-to-file/pixi.min.js"></script>
<script src="/directory-to-file/pixi_viewport.umd.cjs"></script>
<script>
  const viewport = new pixi_viewport.Viewport(options);
</script>

The UMD build expects pixi.js to be loaded first as the global PIXI. For ES modules, use pixi_viewport.js with an import map that resolves pixi.js.

Migration from pixi-viewport v3 to v4

Viewport needs to be imported or required as follows:

import { Viewport } from "pixi-viewport";

// or

const Viewport = require("pixi-viewport").Viewport;

Plugins have been moved to their own object:

// viewport.pausePlugin('drag')
viewport.plugins.pause("drag");

// viewport.resumePlugin('drag')
viewport.plugins.resume("drag");

// viewport.removePlugin('drag')
viewport.plugins.remove("drag");

// viewport.userPlugin('name', plugin, index)
viewport.plugins.add("name", plugin, index);

Tests

Tests use Vitest with jsdom.

  1. Clone repository
  2. pnpm install
  3. pnpm test (or pnpm test:watch to rerun on changes)
  4. pnpm coverage (for a coverage report)

Development Recipe

This project uses pnpm (the version is pinned in package.json's packageManager field).

  1. clone repository
  2. pnpm install
  3. pnpm dev
  4. open browser to http://localhost:5173 (the playground; the example pages are linked from its header)
  5. pnpm run docs (builds the demo site and API docs into docs/dist; pnpm docs:serve to preview)

PRs are more than welcome!

Other Libraries

If you liked pixi-viewport, please try my other open source libraries:

  • pixi-scrollbox - pixi.js scrollbox: a masked box that can scroll vertically or horizontally with scrollbars (uses pixi-viewport)
  • pixi-ease - pixi.js animation library using easing functions
  • intersects - a simple collection of 2d collision/intersects functions. Supports points, circles, lines, axis-aligned boxes, and polygons

license

MIT License (c) 2024 YOPEY YOPEY LLC by David Figatner ([email protected])