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

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,0to 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:
- Import
SvgToolbeltand the CSS. - Get a ref to the container element.
- In a lifecycle hook (
useEffect,onMounted,ngOnInit), create anSvgZoominstance and callinit(). - In a cleanup hook (
useEffect‘s return function,onUnmounted,ngOnDestroy), calldestroy().
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







