chartjs-plugin-zoom
Zoom and pan plugin for Chart.js, adding drag, wheel, and pinch gesture navigation to any chart.
Repository Health
Technical Analysis
chartjs-plugin-zoom is the official interaction plugin for Chart.js, adding zoom and pan behavior to any chart type without extra rendering. It plugs directly into the Chart.js plugin lifecycle (start/beforeUpdate/beforeDraw/stop hooks), listening for mouse wheel, click-and-drag, and Hammer.js-powered pinch gestures, then rewrites the affected scale’s min/max and calls chart.update() to redraw.
Because it targets the Chart.js scale API instead of a fixed chart type, it works across linear, logarithmic, category, and time scales, and exposes a small imperative API (chart.zoom(), chart.pan(), chart.resetZoom(), chart.getZoomLevel()) alongside declarative plugin options for wiring zoom/pan into dashboards, monitoring UIs, and any chart where users need to inspect a narrow slice of a larger dataset.
What You Get
- Mouse wheel zoom with configurable speed and modifier-key gating
- Drag-to-zoom rectangle selection with customizable border/background styling
- Pinch-to-zoom and touch panning via Hammer.js gesture recognition
- Programmatic pan/zoom API (chart.pan(), chart.zoom(), chart.zoomScale(), chart.resetZoom())
- Per-axis zoom/pan limits (min, max, minRange) to bound how far a user can navigate
- Lifecycle callbacks (onZoom, onZoomComplete, onZoomStart, onZoomRejected, onPan, onPanComplete) for hooking into every stage of an interaction
Common Use Cases
- Exploring dense time-series data (metrics, stock prices, sensor logs) by zooming into a narrow time window
- Letting dashboard users drag-select a region of interest on a chart to inspect it more closely
- Adding pinch-to-zoom navigation to charts embedded in mobile/touch web apps
- Constraining how far users can zoom/pan out of a dataset’s meaningful range with scale limits
- Resetting a zoomed chart back to its original view via a toolbar button using resetZoom()
Under The Hood
Architecture Chart.js registers this as a plugin object exported from src/index.ts, implementing lifecycle hooks (start, beforeUpdate, beforeDatasetsDraw/afterDatasetsDraw/beforeDraw/afterDraw, stop) defined in src/plugin.ts. State is centralized per-chart in src/state.ts, holding options, drag state, pan deltas, and original/updated scale limits. Core zoom/pan math lives in src/core.ts (zoom, zoomRect, zoomScale, pan, resetZoom, getZoomLevel, isZoomedOrPanned), delegating actual scale mutation to per-scale-type functions registered in src/scale.types.ts (indexed by scale.type, with a default fallback) — this indirection is what lets the plugin support category, linear, logarithmic, and time scales uniformly. Input handling is fully separated into src/handlers.ts (native mouse/wheel/keyboard DOM listeners, added and removed dynamically based on enabled options) and src/hammer.ts (touch gesture recognition via Hammer.js, restarted whenever relevant options change). This is a clean layered design: plugin.ts orchestrates the lifecycle, handlers/hammer.ts capture raw input, core.ts translates input into scale changes, scale.types.ts encapsulates per-scale-type math, and state.ts holds the mutable per-chart state — extending the core zoom algorithm would mainly touch core.ts and scale.types.ts, not the input-handling layer.
Tech Stack Written in TypeScript 5.0 and bundled with Rollup 4 (via @rollup/plugin-swc, plugin-commonjs, plugin-node-resolve, and plugin-terser) into CJS, ESM, and minified builds, with declaration files emitted separately via tsc. It peer-depends on chart.js (>=3.2.0, developed against ^4.x) and hard-depends on hammerjs for touch gesture recognition, reusing chart.js/helpers utilities (isNumber, sign, getRelativePosition, _isPointInArea) rather than reimplementing geometry helpers. The documentation site is built with VuePress plus typedoc-plugin-markdown, generating published API docs directly from the TSDoc comments on the option interfaces.
Code Quality Testing is extensive and multi-layered: Jasmine unit tests with c8 coverage, Karma browser tests (karma-chrome-launcher, karma-firefox-launcher, karma-rollup-preprocessor) that exercise real DOM/canvas behavior, and dedicated visual-regression fixtures under test/fixtures/{pan,zoom} that pair recorded chart configs with reference PNG screenshots. A separate test-types script type-checks a standalone exports.ts against the public API surface. ESLint (eslint-config-chartjs, typescript-eslint) lints source, tests, docs, and even markdown/HTML samples, and CI runs lint, typecheck, build, and the full test suite on both Ubuntu and Windows for every change. Error handling favors explicit console.warn deprecation notices over silent behavior changes, and the codebase consistently uses small pure functions over class hierarchies.
API Design
The public surface is deliberately declarative-first — wheel, drag, and pinch zoom can all be enabled purely through a zoom/pan/limits options object on options.plugins.zoom, with zero imperative code required for the common case. For programmatic control, the plugin binds a small, chart.js-idiomatic API directly onto the Chart instance (chart.zoom(), chart.pan(), chart.resetZoom(), chart.getZoomLevel()) rather than exposing a separate controller object, so it reads like a native Chart.js method rather than a bolted-on extension. Every option is typed through documented TypeScript interfaces (ZoomPluginOptions, ZoomOptions, PanOptions) whose TSDoc comments double as the published documentation, and centralized defaults mean most integrations only need to override a handful of fields. This follows Chart.js’s own plugin and typing conventions closely rather than introducing a novel pattern, but it executes that convention with very low boilerplate for consumers.
Used by 6 apps in this directory
Gitea
Devops · Developer Tools · Project Management
Self-hosted DevOps in a single Go binary — Git hosting, GitHub Actions-compatible CI/CD, and 30+ package registries without any SaaS dependency.
lila (Lichess)
Community
The forever-free, ad-free, open-source chess server powering millions of real-time games, AI analysis, puzzles, and tournaments worldwide.
Mixpost
Marketing · Social Media
Self-host your own social media scheduler and publish to 11 platforms without subscriptions or data lock-in.
PeerTube
Social Media
A federated, ActivityPub-based video hosting platform built by Framasoft — self-hostable instances interconnect into a network with no vendor lock-in, P2P-assisted streaming, and no ads.
PostHog
Analytics · Monitoring · Developer Tools
The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.
Windmill
Automation · Developer Tools
Turn scripts into webhooks, workflows, and auto-generated UIs — the fastest self-hostable workflow engine, 13x faster than Airflow.