High-performance LED matrix animation library for Canvas 2D.
15KB minified | 4.7KB gzipped | Zero dependencies
- Smooth LED animations with customizable transitions
- Infinite scroll in 8 directions (cardinal + diagonal)
- Cascade, wave, interlaced, and random ignition/extinction patterns
- Multiple LED intensities with color interpolation
- Sparse grid optimization (only renders active LEDs)
- Color caching for minimal GC pressure
- Full TypeScript support with tree-shaking
- No memory leaks - proper cleanup on destroy
npm install leddingimport { Ledding, CircleRenderer, CenterAligner, Directions, Pattern } from 'ledding';
const pattern = [
[0, 1, 1, 0],
[1, 2, 2, 1],
[1, 2, 2, 1],
[0, 1, 1, 0],
];
const ledding = new Ledding('#container', {
ledSize: 20,
ledGap: 4,
artPattern: pattern,
renderer: CircleRenderer,
aligner: CenterAligner,
animation: {
scroll: {
direction: Directions.TO_LEFT,
speed: 80
}
}
});
// Pause/Resume
ledding.pause();
ledding.resume();
// Change pattern dynamically
ledding.setPattern(newPattern);
// Clean up
ledding.destroy();<script src="https://unpkg.com/ledding/dist/ledding.umd.min.js"></script>
<script>
const { Ledding, CircleRenderer, CenterAligner } = window.Ledding;
const instance = new Ledding.Ledding('#container', {
// options
});
</script>interface LeddingOptions {
// Base dimensions
ledSize: number; // LED size in pixels (default: 20)
ledGap: number; // Gap between LEDs (default: 4)
scaleToFit: boolean; // Auto-scale to fit container (default: true)
// Content
artPattern: number[][]; // 2D array pattern (0 = off, 1-N = on states)
// Strategies (tree-shakeable)
renderer: Renderer; // CircleRenderer | SquareRenderer
aligner: Aligner; // CenterAligner, TopLeftAligner, etc.
// Colors
colors: {
background: string | null; // null for transparent
base: string; // Base LED color (off state)
states: Record<number, string>; // Colors for each state (1, 2, 3...)
};
// Opacities
opacities: {
base: { min: number; max: number }; // Random range for base LEDs
active: number; // Opacity when active
};
// Performance
fps: number; // Target frame rate (default: 20)
// Animation
animation: {
scroll: {
direction: Direction; // 'to-left', 'to-right', etc.
speed: number; // Pixels per second
};
ignition: {
pattern: AnimationPattern; // 'cascade', 'wave', 'interlaced', 'random'
direction: Direction;
delay: number; // Frames between steps
step: number; // Group size for patterns
};
extinction: {
// Same as ignition
};
};
// Transition speeds (lerp factor)
transitions: {
ignition: { min: number; max: number; randomize: boolean };
extinction: { min: number; max: number; randomize: boolean };
morph: { min: number; max: number; randomize: boolean };
};
// Grid mode
grid: {
fill: boolean; // true = classic (all LEDs), false = sparse (optimized)
lifespan: number; // Frames before removing inactive LED (sparse mode)
};
}class Ledding {
// Properties
canvas: HTMLCanvasElement;
ctx: CanvasRenderingContext2D;
options: LeddingOptions;
isRunning: boolean;
// Methods
setup(): void; // Recalculate dimensions
pause(): void; // Pause animation
resume(): void; // Resume animation
setPattern(pattern: number[][]): void; // Change pattern
getFrameRate(): number; // Get configured FPS
getLedCount(): number; // Get current LED count
destroy(): void; // Clean up resources
// Events
on(event: LeddingEventType, callback: Function): void;
off(event: LeddingEventType, callback: Function): void;
// Event types: 'beforeDraw', 'afterDraw', 'resize', 'destroy'
}Control art positioning within the canvas:
import {
TopLeftAligner,
TopAligner,
TopRightAligner,
LeftAligner,
CenterAligner, // Default
RightAligner,
BottomLeftAligner,
BottomAligner,
BottomRightAligner
} from 'ledding';Control LED shape:
import { CircleRenderer, SquareRenderer } from 'ledding';
// CircleRenderer: Optimized with Path2D caching
// SquareRenderer: Simple rectangle fillimport { Directions } from 'ledding';
Directions.TO_LEFT
Directions.TO_RIGHT
Directions.TO_TOP
Directions.TO_BOTTOM
Directions.TO_TOP_LEFT
Directions.TO_TOP_RIGHT
Directions.TO_BOTTOM_LEFT
Directions.TO_BOTTOM_RIGHTimport { Pattern } from 'ledding';
Pattern.CASCADE // Sequential activation
Pattern.INTERLACED // Stripe-based activation
Pattern.WAVE // Multiple cascade waves
Pattern.RANDOM // Random activation order- Color caching: RGB strings are cached to avoid creating 20K+ strings/second
- Sparse grid mode: Only active LEDs are tracked and rendered
- Pre-bound functions: No
.bind()in animation loop - Proper cleanup: No memory leaks on destroy
- Frame limiting: Configurable FPS cap
- Visibility API: Pauses when tab is hidden
- Typed arrays: Uint8ClampedArray for color operations
- ESM: 34KB (15KB minified, 4.7KB gzipped)
- UMD: 39KB (15KB minified)
- CommonJS: 35KB
- TypeScript Declarations: 9.7KB
Import only what you need:
// Full bundle
import { Ledding, CircleRenderer, CenterAligner } from 'ledding';
// Minimal - only core
import { Ledding } from 'ledding';
import { CircleRenderer } from 'ledding/renderers';
import { CenterAligner } from 'ledding/aligners';- Chrome 69+
- Firefox 62+
- Safari 12+
- Edge 79+
Requires:
- Canvas 2D API
- ES6 Modules
- Path2D
- requestAnimationFrame
- Map/Set
# Install dependencies
npm install
# Build
npm run build
# Type check
npm run typecheck
# Watch mode
npm run devMIT