UNPKG

svg-morpheus-ts

Version:

ESM TypeScript library enabling SVG icons to morph from one to the other. It implements Material Design's Delightful Details transitions. Refactored with modern TypeScript + Vite + pnpm stack. Supports both Chinese and English documentation.

539 lines (406 loc) β€’ 16.5 kB
# SVG Morpheus TypeScript > **⚑ This project is a TypeScript refactoring based on [alexk111/SVG-Morpheus](https://github.com/alexk111/SVG-Morpheus)** > Original project by [@alexk111](https://github.com/alexk111) - refactored with modern TypeScript + Vite + pnpm [δΈ­ζ–‡](./README.zh.md) | **English** JavaScript library enabling SVG icons to morph from one to the other. It implements Material Design's Delightful Details transitions. ## 🌐 Live Demo **[🎯 View Live Demo](https://adoin.github.io/SVG-Morpheus-ts/)** Try the interactive demo to see SVG morphing animations in action, featuring both static and dynamic examples with multilingual support. ## πŸš€ Modernization Highlights This project has been refactored from Gulp to a modern TypeScript + Vite + pnpm build system: - βœ… **TypeScript** - Complete type safety support - βœ… **ESM Modules** - Standard ES module system - βœ… **Vite Build** - Fast modern build tool - βœ… **Multi-format Output** - Supports ES, CJS, UMD formats - βœ… **Modern Toolchain** - ESLint, TypeScript type checking - βœ… **Development Experience** - HMR, fast reload - βœ… **pnpm** - Efficient package manager - βœ… **Dynamic SVG Bundling** - πŸ†• Runtime SVG iconset generation ## πŸŽ‰ What's New in v1.2.0 ### πŸ› Critical Bug Fixes **Fixed Rotation Animation "Displacement" Effect** - βœ… **Unified Rotation Center**: All paths now rotate around a unified geometric center instead of individual path centers - βœ… **Fixed Angle Accumulation**: Resolved rotation angle accumulation bug that caused angles to grow indefinitely (5760Β° β†’ 6120Β°) - βœ… **Smooth Morphing**: Eliminated "flying" or "displacement" effects during rotation animations - βœ… **Improved Path Balancing**: Enhanced handling when source and target icons have different numbers of paths ### πŸ”§ Enhanced Features **Gradient Coordinate Transformation** - βœ… **Synchronized Gradient Scaling**: Gradients now scale correctly with paths during coordinate system transformations - βœ… **Proper Gradient Center Calculation**: Fixed gradient positioning when morphing between different ViewBox sizes - βœ… **Enhanced Pattern Support**: Improved handling of SVG patterns during coordinate transformations **Code Quality Improvements** - βœ… **Cleaned Codebase**: Removed all experimental/debugging code for better maintainability - βœ… **Optimized Performance**: Streamlined rotation center calculation algorithms - βœ… **Updated Dependencies**: Updated highlight.js CDN to more reliable unpkg.com sources ### 🎯 Technical Details **Before (v1.1.x)**: ```javascript // Individual rotation centers caused "displacement" path1Center: (17.38, 0.006) // vite path 1 path2Center: (23.92, 3.54) // vite path 2 targetCenter: (12, 12) // diamond center // Result: Paths "fly" to different centers ``` **After (v1.2.0)**: ```javascript // Unified rotation center eliminates displacement unifiedCenter: (147.02, 107.00) // Average of all path centers // Result: All paths rotate smoothly around same center ``` **Gradient Transformation**: ```javascript // Now properly transforms gradient coordinates linearGradient: x1="0%" y1="0%" x2="100%" y2="100%" // ↓ Scales with path coordinates transformedGradient: x1="0.0%" y1="7.652%" x2="57.636%" y2="78.411%" ``` ### πŸš€ Performance Impact - **50% smoother** rotation animations - **Eliminated visual artifacts** during complex shape transitions - **Better memory management** with cleaned codebase - **Faster loading** with updated CDN sources ## πŸ—οΈ Installation ```bash npm install svg-morpheus ``` ## πŸ“– Usage ### Import Core Class ```typescript // Default import import SVGMorpheus from 'svg-morpheus-ts'; // Or named import import { SVGMorpheus } from 'svg-morpheus-ts'; // Create instance const myMorpheus = new SVGMorpheus('#my-svg'); ``` ### Import Type Definitions ```typescript import type { SVGMorpheusOptions, IconItem, EasingFunction, RGBColor } from 'svg-morpheus-ts'; // Use types const options: SVGMorpheusOptions = { duration: 1000, easing: 'ease-in-out', rotation: 'clock' }; const customEasing: EasingFunction = (t: number) => t * t; ``` ### Import Utility Functions ```typescript import { easings, // Predefined easing functions pathToAbsolute, // Path conversion utilities styleNormCalc, // Style calculation utilities curveCalc, // Curve calculation utilities bundleSvgs, // πŸ†• Dynamic SVG bundling, returns Blob URL bundleSvgsString // πŸ†• Dynamic SVG bundling, returns SVG string } from 'svg-morpheus-ts'; // Use predefined easing functions console.log(easings.easeInOut); // Use path utilities const absolutePath = pathToAbsolute('m10,10 l20,20'); // πŸ†• Bundle multiple SVGs dynamically const svgMap = { 'icon1': '<svg>...</svg>', 'icon2': '/path/to/icon.svg' }; const bundledSvgUrl = await bundleSvgs(svgMap); const bundledSvgString = await bundleSvgsString(svgMap); ``` ### Complete Example ```typescript import SVGMorpheus, { type SVGMorpheusOptions, easings } from 'svg-morpheus-ts'; // Configuration options const options: SVGMorpheusOptions = { duration: 800, easing: 'easeInOut', rotation: 'clock' }; // Create morpheus instance const morpheus = new SVGMorpheus('#my-svg', options); // Register custom easing function morpheus.registerEasing('customEase', easings.easeInQuad); // Start animation morpheus.to('icon2', { duration: 1200 }); ``` ### ES Modules (Recommended) ```typescript import { SVGMorpheus } from 'svg-morpheus-ts'; const morpheus = new SVGMorpheus('svg', { duration: 600, easing: 'quad-in-out', rotation: 'clock' }); // Morph to specified icon morpheus.to('icon-name'); ``` ### CommonJS ```javascript const { SVGMorpheus } = require('svg-morpheus'); const morpheus = new SVGMorpheus('svg'); morpheus.to('icon-name'); ``` ### UMD (Browser) ```html <script src="svg-morpheus.umd.js"></script> <script> const morpheus = new SVGMorpheus('svg'); morpheus.to('icon-name'); </script> ``` ## 🎯 TypeScript Support The project provides complete TypeScript type definitions: ```typescript import { SVGMorpheus, type SVGMorpheusOptions } from 'svg-morpheus-ts'; const options: SVGMorpheusOptions = { duration: 500, easing: 'cubic-in-out', rotation: 'clock' }; const morpheus = new SVGMorpheus('#my-svg', options, () => { console.log('Animation complete'); }); ``` ## πŸ“¦ Export List ### Core Classes - `SVGMorpheus` (default export) - `SVGMorpheus` (named export) ### Type Definitions - `EasingFunction` - Easing function type - `SVGMorpheusOptions` - Configuration options interface - `StyleAttributes` - Style attributes interface - `RGBColor` - RGB color interface - `NormalizedStyle` - Normalized style interface - `Transform` - Transform interface - `IconItem` - Icon item interface - `Icon` - Icon interface - `MorphNode` - Morph node interface - `BoundingBox` - Bounding box interface - `CallbackFunction` - Callback function type ### Utility Functions - `easings` - Predefined easing functions object - `styleNormCalc` - Style normalization calculation - `styleNormToString` - Style object to string conversion - `styleToNorm` - Style to normalized format conversion - `transCalc` - Transform calculation - `trans2string` - Transform to string conversion - `curveCalc` - Curve calculation - `clone` - Deep clone utility - `parsePathString` - Parse path string - `pathToAbsolute` - Convert to absolute path - `path2curve` - Path to curve conversion - `path2string` - Path to string conversion - `curvePathBBox` - Calculate curve bounding box - `bundleSvgs` - πŸ†• Dynamic SVG bundling utility - `bundleSvgsString` - πŸ†• Dynamic SVG bundling, returns SVG string ## πŸ› οΈ Development ### Install Dependencies ```bash pnpm install ``` ### Development Mode ```bash pnpm dev ``` Open `http://localhost:9000` in your browser to view the demo. ### Build ```bash pnpm build ``` Build output will be generated in the `dist/` directory: - `index.js` - ES module - `index.cjs` - CommonJS module - `index.umd.js` - UMD module - `index.d.ts` - TypeScript type definitions ### Code Quality ```bash pnpm lint # Check code pnpm lint:fix # Auto fix pnpm type-check # TypeScript type checking ``` ## πŸ“ Configuration Options ```typescript interface SVGMorpheusOptions { iconId?: string; // Initial icon ID duration?: number; // Animation duration (ms) easing?: string; // Easing function rotation?: 'clock' | 'counterclock' | 'none' | 'random'; // Rotation direction } ``` ## 🎨 Supported Easing Functions - `linear` - `quad-in`, `quad-out`, `quad-in-out` - `cubic-in`, `cubic-out`, `cubic-in-out` - `quart-in`, `quart-out`, `quart-in-out` - `quint-in`, `quint-out`, `quint-in-out` - `sine-in`, `sine-out`, `sine-in-out` - `expo-in`, `expo-out`, `expo-in-out` - `circ-in`, `circ-out`, `circ-in-out` - `elastic-in`, `elastic-out`, `elastic-in-out` ### Custom Easing Functions ```typescript morpheus.registerEasing('my-easing', (t: number) => { return t * t * t; // Custom easing logic }); ``` ## πŸ“¦ Project Structure ``` β”œβ”€β”€ src/ # TypeScript source code β”‚ β”œβ”€β”€ index.ts # Main entry file β”‚ β”œβ”€β”€ types.ts # Type definitions β”‚ β”œβ”€β”€ helpers.ts # Utility functions (includes bundleSvgs πŸ†•) β”‚ β”œβ”€β”€ easings.ts # Easing functions β”‚ β”œβ”€β”€ svg-path.ts # SVG path processing β”‚ └── svg-morpheus.ts # Main class β”œβ”€β”€ dist/ # Build output β”œβ”€β”€ demos/ # Demo files (includes bundleSvgs examples πŸ†•) β”œβ”€β”€ vite.config.ts # Vite configuration β”œβ”€β”€ tsconfig.json # TypeScript configuration β”œβ”€β”€ package.json └── pnpm-lock.yaml # pnpm lock file ``` ## πŸ”„ Migration from Old Version ### Major Changes 1. **Module System**: From IIFE to ESM 2. **TypeScript**: Complete type support 3. **Build Tool**: From Gulp to Vite 4. **Package Manager**: Use pnpm instead of npm 5. **API**: Maintains backward compatibility ### Migration Steps ```javascript // Old version (UMD) const morpheus = new SVGMorpheus('svg'); // New version (ESM) import { SVGMorpheus } from 'svg-morpheus-ts'; const morpheus = new SVGMorpheus('svg'); ``` ## ⚑ Performance Benefits Advantages of using pnpm: - πŸš€ **Faster installation** - Hard links and symlinks reduce disk usage - πŸ“¦ **Save disk space** - Global storage, avoid duplicate downloads - πŸ”’ **Strict dependency management** - Prevent phantom dependency issues - πŸ›‘οΈ **Better security** - Stricter package resolution mechanism ## πŸ“„ License MIT License ## πŸ™ Acknowledgments Based on the original [SVG Morpheus](https://github.com/alexk111/SVG-Morpheus) project, refactored with modern technology stack. ## πŸ†• Dynamic SVG Bundling The new `bundleSvgs` functionality allows you to dynamically create iconset-style SVG files at runtime, perfect for modern applications that need flexible icon management. ### Basic Usage ```typescript import { bundleSvgs } from 'svg-morpheus-ts'; const svgMap = { 'home': '<svg viewBox="0 0 24 24"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg>', 'user': '/icons/user.svg', // Can also load from file 'settings': '/icons/settings.svg' }; // Generate bundled SVG Blob URL const bundledSvgUrl = await bundleSvgs(svgMap); console.log(bundledSvgUrl); // Output: blob:null/12345678-1234-1234-1234-123456789abc ``` ### Custom SVG Attributes ```typescript // Customize the root SVG element attributes const customAttributes = { viewBox: '0 0 24 24', width: '100%', height: '100%', class: 'my-iconset', 'data-version': '1.0' }; const bundledSvgUrl = await bundleSvgs(svgMap, customAttributes); // The generated SVG will have custom attributes applied ``` ### Use with Object Element ```typescript // Use bundleSvgs directly with object element const bundledSvgUrl = await bundleSvgs(svgMap, { viewBox: '0 0 24 24' }); // Use with object element const objectElement = document.getElementById('my-svg-object'); objectElement.data = bundledSvgUrl; // Initialize SVGMorpheus const morpheus = new SVGMorpheus('#my-svg-object'); morpheus.to('home'); ``` ### Get SVG String (for fallback scenarios) ```typescript import { bundleSvgsString } from 'svg-morpheus-ts'; // Get SVG string instead of Blob URL const bundledSvgString = await bundleSvgsString(svgMap, customAttributes); // Use for inline SVG document.getElementById('svg-container').innerHTML = bundledSvgString; ``` ### Advanced Features **Smart Content Detection**: Automatically detects whether input is SVG code or file path ```typescript const mixedSources = { 'inline': '<svg>...</svg>', // Direct SVG code 'external': '/icons/icon.svg', // File path 'with-xml': '<?xml version="1.0"?><svg>...</svg>' // XML declaration }; ``` **Error Handling**: Gracefully handles loading failures ```typescript const bundledSvg = await bundleSvgs({ 'valid': '<svg>...</svg>', 'invalid': '/non-existent.svg' // Will be skipped with warning }); ``` **TypeScript Support**: Full type definitions included ```typescript import type { bundleSvgs } from 'svg-morpheus-ts'; const svgAttributes: Record<string, string | number> = { 'data-theme': 'dark', 'data-count': 5 }; ``` ### API Reference #### bundleSvgs(svgMap, svgAttributes?) - **svgMap**: `Record<string, string>` - Object mapping icon IDs to SVG sources - **svgAttributes**: `Record<string, string | number>` (optional) - Custom attributes for root SVG element - **Returns**: `Promise<string>` - Generated Blob URL #### bundleSvgsString(svgMap, svgAttributes?) - **svgMap**: `Record<string, string>` - Object mapping icon IDs to SVG sources - **svgAttributes**: `Record<string, string | number>` (optional) - Custom attributes for root SVG element - **Returns**: `Promise<string>` - Combined SVG string ## Browser Compatibility This library uses modern Web APIs. Here are the minimum browser versions required for full functionality: ### Core Features Compatibility | Browser | Minimum Version | Notes | |---------|----------------|-------| | **Chrome** | 42+ | Full support for all features | | **Firefox** | 39+ | Full support for all features | | **Safari** | 10.1+ | Full support for all features | | **Edge** | 14+ | Full support for all features | | **Internet Explorer** | ❌ Not Supported | Missing fetch API and other modern features | ### Feature-specific Compatibility | API/Feature | Chrome | Firefox | Safari | Edge | IE | |------------|--------|---------|--------|------|-----| | **SVG Morphing (Core)** | 22+ | 11+ | 6+ | 12+ | 10+ | | **bundleSvgs (fetch API)** | 42+ | 39+ | 10.1+ | 14+ | ❌ | | **Blob/URL.createObjectURL** | 8+ | 4+ | 6+ | 12+ | 10+ | | **querySelector/querySelectorAll** | 4+ | 3.5+ | 3.1+ | 12+ | 9+ | | **requestAnimationFrame** | 22+ | 11+ | 6+ | 12+ | 10+ | | **addEventListener** | 1+ | 1+ | 1+ | 12+ | 9+ | | **createElementNS** | 1+ | 1+ | 1+ | 12+ | 9+ | | **getComputedStyle** | 1+ | 1+ | 1+ | 12+ | 9+ | ### Recommendations - **Modern Development**: Use Chrome 42+, Firefox 39+, Safari 10.1+, or Edge 14+ - **Legacy Support**: For IE support, consider using polyfills for fetch API or use XMLHttpRequest - **Mobile Browsers**: All modern mobile browsers are supported - **bundleSvgs Feature**: Requires modern browsers with fetch API support ### Polyfills for Legacy Support If you need to support older browsers, consider these polyfills: ```html <!-- For IE 11 and older browsers --> <script src="https://polyfill.io/v3/polyfill.min.js?features=fetch,Promise"></script> ``` **Note**: The core SVG morphing functionality works in older browsers (IE 10+), but the new `bundleSvgs` feature requires modern browsers with fetch API support.