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
Markdown
# 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.