Add Interactive Zoom and Pan to Any SVG – svg-toolbelt

Category: Javascript , Zoom | June 15, 2025
Author:zakariaf
Views Total:301 views
Official Page:Go to website
Last Update:June 15, 2025
License:MIT

Preview:

Add Interactive Zoom and Pan to Any SVG – svg-toolbelt

Description:

svg-toolbelt is a lightweight JavaScript library that adds interactive, zoomable, and pannable experiences to any SVG.

Key Features:

  • Smooth Zoom & Pan: Offers mouse-wheel zoom (to cursor), click-drag panning, pinch-to-zoom, touch-drag, and keyboard navigation (+/- for zoom, arrows for pan, 0 to reset).
  • On-Screen Controls: Provides buttons for zoom in/out, reset, and fullscreen. These are customizable in position and style, and include an export function.
  • Visual Feedback: A transient zoom level indicator (e.g., “150%”) appears on zoom changes and is screen-reader accessible.
  • Mobile-First Design: Optimized touch interactions, responsive UI, and touch-friendly button sizes (44px minimum).
  • Accessibility Focused: WCAG 2.1 AA compliant, full keyboard navigation, ARIA labels, high contrast, and reduced motion support.
  • Modular Architecture: Tree-shakeable, so you only include the features (zoom, pan, touch, keyboard, controls, fullscreen) you need.
  • Framework Agnostic: Works with vanilla JavaScript or popular frameworks like React, Vue, and Angular.

See It In Action:

Use Cases:

  • Complex Documentation Diagrams: If you’re embedding large Mermaid flowcharts or system architecture diagrams in your docs, users on mobile will thank you. Instead of a tiny, unreadable image, they get something they can explore.
  • Interactive Data Visualizations: You might have a D3.js chart that generates a detailed SVG. svg-toolbelt can add a layer of user-friendly navigation without you needing to wire up D3’s zoom/pan from scratch or pull in more of D3 than you need.
  • Technical Schematics or Floor Plans: For any detailed vector graphic where users need to inspect specific areas, this provides a much better experience than just a static image.
  • Improving Accessibility of SVGs: The built-in accessibility features mean more users can understand and interact with your SVG content.

How To Use It:

1. Install svg-toolbelt and import it into your project.

# Yarn
$ yarn add svg-toolbelt
# NPM
$ npm install svg-toolbelt
# PNPM
$ pnpm install svg-toolbelt
// automatic instantiation
import { initializeSvgToolbelt } from 'svg-toolbelt';
// manual instantiation
import { SvgToolbelt } from 'svg-toolbelt';
// required stylesheet
import 'svg-toolbelt/dist/svg-toolbelt.css';

2. You can also load the necessary JavaScript and CSS files directly in the HTML document.

<link rel="stylesheet" href="/dist/svg-toolbelt.css">
<script src="/dist/svg-toolbelt.cjs.production.min.js"></script>
<!-- OR -->
<script type="module">
  import { initializeSvgToolbelt } from './dist/svg-toolbelt.esm.js';
</script>

3. Initialize svg-toolbelt on your SVG element:

<div class="zoomable">
  <svg>
    <!-- SVG Here -->
  </svg>
</div>
initializeSvgZoom('.zoomable');

4. If you need more fine-grained control or want to manage the lifecycle programmatically:

const container = document.querySelector('#mySVG');
if (container instanceof HTMLElement) {
  const instance = new SvgToolbelt(container, {
    // Zoom limits
    minScale: 0.1,
    maxScale: 10,
    zoomStep: 0.1,
    // Animation duration in milliseconds
    transitionDuration: 200,
    // Controls: whether to show on-screen buttons
    showControls: true,
    // Position of controls: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'
    controlsPosition: 'top-right',
    // Touch support
    enableTouch: true,
    // Keyboard support
    enableKeyboard: true,
    // Zoom level indicator
    showZoomLevelIndicator: true,
  });
// initialize
instance.init();
// zoom in/out
instance.zoomIn();
instance.zoomOut();
// destroy the instance
instance.destroy();

5. Integrate svg-toolbelt with React, Vue, or Angular frameworks:

  1. Import SvgToolbelt and the CSS.
  2. Get a ref to the container element.
  3. In a lifecycle hook (useEffect, onMounted, ngOnInit), create an SvgZoom instance and call init().
  4. In a cleanup hook (useEffect‘s return function, onUnmounted, ngOnDestroy), call destroy().

Here’s a condensed React example:

import React, { useEffect, useRef } from 'react';
import { SvgToolbelt, SvgEnhancerConfig } from 'svg-toolbelt';
import 'svg-toolbelt/dist/svg-toolbelt.css';
interface ZoomableSvgProps {
children: React.ReactNode;
config?: Partial<SvgEnhancerConfig>;
className?: string;
}
export function ZoomableSvg({ children, config, className }: ZoomableSvgProps) {
const containerRef = useRef<HTMLDivElement>(null);
const enhancerRef = useRef<SvgToolbelt>();
useEffect(() => {
if (containerRef.current) {
enhancerRef.current = new SvgToolbelt(containerRef.current, config);
enhancerRef.current.init();
}
return () => {
enhancerRef.current?.destroy();
};
}, [config]);
return (
<div ref={containerRef} className={className}>
{children}
</div>
);
}
// Usage
function MyComponent() {
return (
<ZoomableSvg config={{ minScale: 0.5, maxScale: 4 }}>
<svg viewBox="0 0 400 300">
{/* Your SVG content */}
</svg>
</ZoomableSvg>
);
}

Changelog:

v0.7.0 (06/15/2025)

  • The main library class SvgZoom has been renamed to SvgToolbelt.
  • The primary initialization function initializeSvgZoom has been renamed to initializeSvgToolbelt.
  • Backward Compatibility: To ensure a smooth transition for existing users, deprecated aliases (SvgZoom and initializeSvgZoom) have been added. These aliases will function as before but will log a console warning encouraging users to update to the new names.

v0.6.0 (06/08/2025)

  • Added public reset(), applyTransform(), and applyTransformWithTransition() methods to the base SvgEnhancer class
  • Keyboard navigation now emits arrow events for better integration
  • Enhanced cleanup of transition timeouts and event listeners
  • Added safety checks for malformed touch events and destroyed instances
  • Refactored all features to use centralized transform methods instead of direct DOM manipulation
  • Improved handling of browser API differences and fallbacks
  • Fixed potential memory leaks in transition management
  • Improved error handling for missing DOM APIs
  • Enhanced safety for operations on destroyed instances

v0.6.0 (06/06/2025)

  • Pan limits now automatically calculate based on SVG content dimensions, zoom level, and container size
  • Intelligent boundary detection that allows panning until only 10% of large content remains visible
  • Full container freedom for small or zoomed-out content
  • Enhanced edge case handling for very small content with adaptive padding
  • Fixed asymmetric panning issues where up/left panning was overly restricted
  • Users can now pan charts to show any portion (e.g., bottom-right) in the center of the screen
  • Better panning behavior at low zoom levels (e.g., 10%)
  • More generous panning allowances that feel natural and unrestricted
  • Replaced magic numbers with named constants for better maintainability
  • Enhanced SVG dimension parsing with robust validation for zero/negative values
  • Improved viewBox parsing with comprehensive NaN and type validation
  • Refactored bounds detection into separate helper methods
  • Comprehensive test coverage with 236 additional test cases
  • Fixed asymmetric panning: Resolved issue where up/left panning was too restrictive
  • Enhanced JSDOM compatibility: Better fallback mechanisms for testing environments
  • Improved feature destruction: Fixed TypeError in feature destroy method
  • Better small content handling: Adaptive padding prevents content from disappearing completely
  • Removed configuration options: maxPanX and maxPanY are no longer supported
  • Pan limits are now calculated automatically – no manual configuration needed
  • This change provides a significantly better user experience with intelligent content-aware boundaries

v0.5.0 (06/05/2025)

  • Preserve Original SVG Styles: No more forced dimensions, margins, borders, or backgrounds
  • Minimal Footprint: Only applies styles necessary for zoom/pan functionality
  • Enhanced Flexibility: SVGs maintain their original design and layout
  • Better Integration: Works seamlessly with existing CSS frameworks and custom styles
  • SVG wrapper no longer applies default styling (margins, borders, backgrounds)
  • SVGs preserve their original width, height, and display properties
  • Custom styling may be needed if you relied on the default wrapper appearance

You Might Be Interested In:


Leave a Reply