A flexible particle effect library with realistic physics, spatial distortion, and interactive modes (repel, attract, vortex) for creating stunning image-based particle animations
A flexible, TypeScript-based particle effect library with realistic physics and interactive modes for creating stunning image-based particle animations. Works with vanilla JavaScript and React.
- Image-based particles: Convert any image into animated particles
- Realistic physics: Inverse square law forces with smooth falloff (no hard edges)
- Natural interactions: Smooth, organic mouse effects without visible radius boundaries
- Spatial distortion effect: Particles have individual mass - some escape forces, others resist
- Variable particle sizes: Each particle can have different size for organic look
- Multiple interaction modes: Repel, Attract, Vortex, and Chaos effects with turbulence
- Dynamic radius control: Adjust mouse interaction radius with mouse wheel/scroll in real-time
- Enhanced Perlin noise: Organic, flowing movement with pseudo-Perlin noise instead of pure random
- Chaos mode: Dynamic blend of repel and vortex with time-based oscillations
- Momentum-based gravity: Physics that feel natural, not just a downward pull
- React support: Built-in hook for easy React integration
- TypeScript: Full type safety and IntelliSense support
- Highly configurable: Intuitive 0-5 scale for density and size controls
- Transparent backgrounds: Perfect for overlay effects
- Flexible sizing: Set custom dimensions or maintain aspect ratio
- Lightweight: No dependencies (except React for the hook)
- Global mouse tracking: Mouse interactions work across entire window, not just canvas
``bash`
npm i particle-lsslib
Option 1: Automatic Renderer Selection (Recommended)
`typescript
import { ParticleEngineHybrid } from 'particle-lsslib';
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
const engine = new ParticleEngineHybrid({
canvas,
enablePerformanceMonitoring: true, // Optional: track FPS and metrics
settings: {
particleSize: 3,
density: 4,
mode: 'repel',
force: 5,
width: 800,
padding: 200,
backgroundColor: 'transparent',
},
});
// Load an image
await engine.loadImage('path/to/image.png');
// Start animation (automatically starts after loading)
engine.start();
// Check which renderer was selected
console.log(Using renderer: ${engine.getRenderer()}); // 'canvas2d', 'webgl', or 'webgl-worker'
// Monitor performance
console.log(engine.getPerformanceMetrics()); // { fps: 60, frameTime: 16.6, particleCount: 5000, renderer: 'canvas2d' }
`
Option 2: Canvas 2D Only (Direct ParticleEngine)
`typescript
import { ParticleEngine } from 'particle-lsslib';
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
const engine = new ParticleEngine({
canvas,
settings: {
particleSize: 3,
density: 4,
mode: 'repel',
force: 5,
width: 800,
padding: 200,
backgroundColor: 'transparent',
},
});
await engine.loadImage('path/to/image.png');
engine.start();
`
Basic Usage with React Hook
`tsx
import { useParticleEffect } from 'particle-lsslib';
function ParticleCanvas() {
const { canvasRef, loadImage, updateSettings } = useParticleEffect({
settings: {
particleSize: 2,
density: 4,
mode: 'vortex',
},
});
const handleFileChange = async (e: React.ChangeEvent
const file = e.target.files?.[0];
if (file) await loadImage(file);
};
return (
Advanced: Using ParticleEngineHybrid in React
`tsx
import { useEffect, useRef } from 'react';
import { ParticleEngineHybrid } from 'particle-lsslib';function HybridParticleCanvas() {
const canvasRef = useRef(null);
const engineRef = useRef(null);
useEffect(() => {
if (!canvasRef.current) return;
// Create hybrid engine with automatic renderer selection
engineRef.current = new ParticleEngineHybrid({
canvas: canvasRef.current,
enablePerformanceMonitoring: true,
settings: {
particleSize: 2,
density: 4,
mode: 'chaos',
force: 5,
width: 450,
padding: 200,
},
});
// Load image
engineRef.current.loadImage('/your-image.png');
// Log renderer info
console.log(
Renderer: ${engineRef.current.getRenderer()});
console.log('Capabilities:', engineRef.current.getCapabilities()); // Cleanup
return () => {
engineRef.current?.destroy();
};
}, []);
return ;
}
`API Reference
$3
The hybrid engine automatically selects the best renderer based on browser capabilities:
- Canvas 2D: Default, works everywhere
- WebGL: High-performance GPU rendering (coming soon)
- WebGL Worker: WebGL in Web Worker with OffscreenCanvas for maximum performance (AVAILABLE NOW)
#### Constructor
`typescript
new ParticleEngineHybrid(options: ParticleEngineOptions)
`Options:
-
canvas: HTMLCanvasElement - The canvas element to render on
- renderer?: 'canvas2d' | 'webgl' | 'webgl-worker' - Force specific renderer (optional)
- enablePerformanceMonitoring?: boolean - Track FPS and performance metrics (default: false)
- settings?: Partial settings object (see Settings below)
- onParticlesGenerated?: Callback function called when particles are createdExample:
`typescript
const engine = new ParticleEngineHybrid({
canvas: document.getElementById('canvas') as HTMLCanvasElement,
renderer: 'canvas2d', // Optional: force specific renderer
enablePerformanceMonitoring: true,
settings: {
particleSize: 2,
density: 4,
mode: 'chaos',
},
});
`#### Methods
#####
loadImage(source: ImageSource): Promise
Load and process an image. Accepts URL string, HTMLImageElement, or File object.#####
start(): void
Start the animation loop.#####
stop(): void
Stop the animation loop.#####
updateSettings(settings: PartialParticleSettings): void
Update one or more settings.#####
getSettings(): ParticleSettings | null
Get current settings (returns null if using WebGL Worker).#####
getParticleCount(): number
Get the current number of particles.#####
getRenderer(): RendererType
Get the current renderer being used.Returns:
'canvas2d' | 'webgl' | 'webgl-worker'`typescript
const renderer = engine.getRenderer();
console.log(Using: ${renderer});
`#####
getCapabilities(): BrowserCapabilities
Get browser capabilities detected by the engine.Returns:
`typescript
{
supportsWebGL: boolean;
supportsWebGL2: boolean;
supportsOffscreenCanvas: boolean;
supportsWebGLInWorker: boolean;
maxTextureSize: number;
recommendedRenderer: RendererType;
}
`Example:
`typescript
const caps = engine.getCapabilities();
console.log(WebGL supported: ${caps.supportsWebGL});
console.log(Recommended renderer: ${caps.recommendedRenderer});
`#####
getPerformanceMetrics(): PerformanceMetrics
Get current performance metrics (only if enablePerformanceMonitoring is true).Returns:
`typescript
{
fps: number; // Current frames per second
frameTime: number; // Average frame time in ms
particleCount: number; // Current number of particles
renderer: RendererType; // Active renderer
}
`Example:
`typescript
setInterval(() => {
const metrics = engine.getPerformanceMetrics();
console.log(FPS: ${metrics.fps}, Particles: ${metrics.particleCount});
}, 1000);
`#####
destroy(): void
Clean up and remove event listeners.---
$3
#### Constructor
`typescript
new ParticleEngine(options: ParticleEngineOptions)
`Options:
-
canvas: HTMLCanvasElement - The canvas element to render on
- settings?: Partial settings object (see Settings below)
- onParticlesGenerated?: Callback function called when particles are created#### Methods
#####
loadImage(source: ImageSource): Promise
Load and process an image. Accepts:
- URL string
- HTMLImageElement
- File object`typescript
await engine.loadImage('image.png');
await engine.loadImage(fileInput.files[0]);
`#####
start(): void
Start the animation loop.#####
stop(): void
Stop the animation loop.#####
updateSettings(settings: Partial
Update one or more settings.`typescript
engine.updateSettings({
mode: 'attract',
force: 10,
gravity: 0.1,
});
`#####
getSettings(): ParticleSettings
Get current settings.#####
getParticleCount(): number
Get the current number of particles.#####
destroy(): void
Clean up and remove event listeners.$3
`typescript
interface ParticleSettings {
particleSize: number; // Particle size scale 0-5 (0=tiny 0.5px, 5=large 4px) (default: 2.5)
density: number; // Particle density 0-5 (0=sparse, 5=very dense) (default: 2.5)
gravity: number; // Momentum-based gravity force (default: 0)
mouseRadius: number; // Interaction radius - adjustable with mouse wheel (default: 100)
scale: number; // Image scale multiplier (default: 1)
mode: InteractionMode; // 'repel' | 'attract' | 'vortex' | 'chaos' (default: 'repel')
force: number; // Interaction force strength (default: 5)
padding: number; // Canvas padding in pixels (default: 200)
paddingX?: number; // Horizontal padding - overrides padding if set
paddingY?: number; // Vertical padding - overrides padding if set
backgroundColor: string; // Background color or 'transparent' (default: 'transparent')
width?: number; // Custom width - overrides scale if set
height?: number; // Custom height - overrides scale if set
noise?: number; // Noise/randomness factor 0-1 (default: 0.3) - now uses Perlin noise
minParticleSize?: number; // Minimum particle size for variation
maxParticleSize?: number; // Maximum particle size for variation
}
`#### Physics & Visual Effects
New in v2.0: The library now uses realistic inverse square law physics (like real gravity) instead of linear forces. Each particle has:
- Individual mass (0.5-2.0): Affects resistance to forces
- Individual size: Random size between
minParticleSize and maxParticleSize
- Escape probability: Some particles escape forces based on distance and mass (spatial distortion effect)
- Brownian motion: Subtle random movement controlled by noise parameter#### Image Sizing Options
You can control the image size in three ways:
1. Using width/height (maintains aspect ratio if only one is set)
`typescript
engine.updateSettings({ width: 800 }); // Height calculated automatically
engine.updateSettings({ height: 600 }); // Width calculated automatically
engine.updateSettings({ width: 800, height: 600 }); // Both specified
`2. Using scale multiplier
`typescript
engine.updateSettings({ scale: 1.5 }); // 150% of original size
`3. Custom padding (uniform or separate)
`typescript
// Uniform padding
engine.updateSettings({
padding: 300, // Same padding on all sides
backgroundColor: '#000000' // Black background
});// Separate horizontal and vertical padding
engine.updateSettings({
paddingX: 400, // Horizontal padding
paddingY: 200, // Vertical padding
backgroundColor: '#000000'
});
`$3
For realistic spatial distortion (Recommended):
`typescript
{
particleSize: 2,
density: 4, // Dense for smooth effect (0-5 scale: higher = more dense)
mode: 'repel',
force: 3, // Lower force with inverse square law physics
gravity: 0, // Keep particles stable
mouseRadius: 200, // Large interaction area with smooth falloff
width: 450,
padding: 250, // Space for particles to move freely
backgroundColor: 'transparent',
noise: 0.4, // Spatial distortion and turbulence
minParticleSize: 0.3, // Very small particles
maxParticleSize: 1.5, // Varied sizes for organic look
}
`For high-performance (many particles):
`typescript
{
particleSize: 2.5,
density: 4.5, // Very dense (0-5 scale: 4.5 = lots of particles)
force: 2, // Lower with new physics
mouseRadius: 180,
padding: 200,
noise: 0.3,
minParticleSize: 0.5,
maxParticleSize: 2,
}
`For low-resource devices:
`typescript
{
particleSize: 3,
density: 1.5, // Sparse (0-5 scale: 1.5 = fewer particles, better performance)
force: 4,
mouseRadius: 150,
padding: 150,
noise: 0.2, // Less computation
minParticleSize: 1,
maxParticleSize: 3,
}
`For dramatic vortex effect:
`typescript
{
particleSize: 2.5,
density: 3.5, // Medium-high density
mode: 'vortex',
force: 5,
mouseRadius: 250,
noise: 0.6, // High turbulence
minParticleSize: 0.2,
maxParticleSize: 2,
}
`For mesmerizing chaos effect (NEW):
`typescript
{
particleSize: 2,
density: 4, // Dense for smooth transitions
mode: 'chaos',
force: 4, // Balanced force for mixed effects
mouseRadius: 220,
noise: 0.5, // High noise enhances chaotic behavior
minParticleSize: 0.3,
maxParticleSize: 1.8,
padding: 250,
}
`Important Notes (v3.0+):
-
particleSize: Intuitive 0-5 scale where higher = larger particles (0=0.5px tiny, 5=4px large). Default: 2.5
- density: Intuitive 0-5 scale where higher = more dense (0=sparse, 5=very dense). Default: 2.5. Recommended: 3-5 for smooth effects
- force: With inverse square law physics, use lower values (2-5). Old linear physics needed higher values
- noise: Controls randomness and spatial distortion (0 = no randomness, 1 = maximum chaos)
- minParticleSize / maxParticleSize: Override automatic size calculation for custom variation
- padding: Ensures particles can move outside image bounds without being cut off
- gravity: Momentum-based - moving particles feel more gravity. Set to 0 for stable effects
- mouseRadius: Actual effect radius is 1.5x larger with smooth falloff (no hard edges)$3
####
useParticleEffect(options?: UseParticleEffectOptions)Options:
-
settings?: Initial particle settings
- autoStart?: Auto-start animation (default: true)
- onParticlesGenerated?: Callback when particles are generatedReturns:
`typescript
{
canvasRef: React.RefObject;
loadImage: (source: ImageSource) => Promise;
start: () => void;
stop: () => void;
updateSettings: (settings: PartialParticleSettings) => void;
getParticleCount: () => number;
getEngine: () => ParticleEngine | null;
}
`Browser Capabilities Detection
The library includes automatic browser capabilities detection to select the best renderer:
`typescript
import { detectCapabilities, logCapabilities } from 'particle-lsslib';// Detect browser capabilities
const capabilities = detectCapabilities();
console.log(capabilities);
// {
// supportsWebGL: true,
// supportsWebGL2: true,
// supportsOffscreenCanvas: true,
// supportsWebGLInWorker: true,
// maxTextureSize: 16384,
// recommendedRenderer: 'webgl-worker'
// }
// Pretty-print capabilities to console
logCapabilities(capabilities);
`Capabilities Explained:
-
supportsWebGL: Browser supports WebGL 1.0 (GPU rendering)
- supportsWebGL2: Browser supports WebGL 2.0 (better GPU rendering)
- supportsOffscreenCanvas: Browser supports OffscreenCanvas (rendering in workers)
- supportsWebGLInWorker: Browser can use WebGL inside Web Workers
- maxTextureSize: Maximum texture size supported by GPU
- recommendedRenderer: Best renderer for this browserRenderer Selection Logic:
1. WebGL Worker (
webgl-worker): If browser supports WebGL + OffscreenCanvas + Workers
2. WebGL (webgl): If browser supports WebGL but not workers (coming soon)
3. Canvas 2D (canvas2d): Fallback for all browsersForce a Specific Renderer:
`typescript
const engine = new ParticleEngineHybrid({
canvas,
renderer: 'canvas2d', // Override automatic selection
settings: { / ... / },
});
`---
Performance Monitoring
Enable performance monitoring to track FPS, frame time, and particle count:
`typescript
const engine = new ParticleEngineHybrid({
canvas,
enablePerformanceMonitoring: true,
settings: { / ... / },
});// Check metrics every second
setInterval(() => {
const metrics = engine.getPerformanceMetrics();
console.log(
);
}, 1000);
`Performance Metrics:
-
fps: Current frames per second (60 = smooth)
- frameTime: Average time to render one frame in milliseconds
- particleCount: Total number of active particles
- renderer: Which renderer is being usedPerformance Tips:
- Lower
density (0-2) for fewer particles and better FPS
- Use particleSize 2-3 for balanced visual quality and performance
- Lower noise (0-0.3) reduces computation
- Canvas 2D: Good for < 10,000 particles
- WebGL: Excellent for 10,000+ particles (coming soon)
- WebGL Worker: Best for 50,000+ particles without blocking UI (coming soon)---
Interaction Modes
$3
Particles are pushed away from the cursor using inverse square law (like magnetic repulsion). Creates a realistic spatial distortion effect where some particles escape and others resist based on their mass.`typescript
engine.updateSettings({
mode: 'repel',
force: 3, // Lower values with new physics
noise: 0.4, // Adds turbulence and escape behavior
});
`$3
Particles are pulled toward the cursor using gravitational physics. Lighter particles are pulled more strongly, heavier ones resist.`typescript
engine.updateSettings({
mode: 'attract',
force: 2,
noise: 0.3,
});
`$3
Particles spiral around the cursor with tangential rotation and radial pull. High turbulence creates chaotic, organic movement.`typescript
engine.updateSettings({
mode: 'vortex',
force: 5,
noise: 0.6, // High turbulence for dramatic effect
});
`$3
A dynamic hybrid mode that seamlessly blends repel and vortex effects with time-based oscillations. Creates unpredictable, organic motion patterns that evolve over time. Each particle has its own unique phase, resulting in mesmerizing, ever-changing formations.`typescript
engine.updateSettings({
mode: 'chaos',
force: 4, // Balanced force for mixed effects
noise: 0.5, // High noise enhances chaotic behavior
});
`Chaos Mode Features:
- Time-based blending: Dynamically oscillates between repel and vortex over time
- Unique particle phases: Each particle follows its own oscillation pattern
- Perpendicular waves: Additional wave forces create flowing, liquid-like motion
- Enhanced turbulence: Extra randomness for truly chaotic, organic effects
- Best for: Abstract art, mesmerizing animations, unpredictable interactions
Mouse Wheel Control:
All modes now support dynamic radius adjustment with the mouse wheel/scroll:
- Scroll up: Increase interaction radius (up to 800px)
- Scroll down: Decrease interaction radius (minimum 20px)
- Changes take effect immediately without page reload
Physics Explained
$3
The library now uses inverse square law physics, which means force strength follows the formula:
`
Force = (strength × mass_effect) / distance²
`This creates more realistic interactions compared to linear forces:
Benefits:
- Particles close to cursor experience exponentially stronger forces
- Particles far away are barely affected
- Creates natural "event horizon" where some particles escape
- Matches real-world physics (gravity, magnetism, electrostatics)
$3
Each particle has individual properties:
`typescript
{
mass: 0.5 to 2.0, // Random mass affects resistance
size: minParticleSize to maxParticleSize, // Random size
escapeChance: random() // Probability to resist force
}
`How it works:
1. Lighter particles (mass < 1.0) are more affected by forces
2. Heavier particles (mass > 1.0) resist forces better
3. Distance matters: Particles further from cursor escape easier
4. Randomness: Each frame, particles randomly resist based on their escape threshold
This creates the spatial distortion effect where:
- Some particles are pulled/pushed strongly
- Others barely move or escape entirely
- Creates organic, non-uniform behavior
- Looks like space-time is warping around the cursor
$3
The
noise parameter (0-1) adds several effects:`typescript
noise: 0.4 // Recommended for realistic distortion
`Effects of noise:
- Perpendicular forces: Particles get pushed at angles, not just radially
- Brownian motion: Subtle random movement even when mouse is away
- Turbulence: In vortex mode, creates chaotic spiral patterns
- Escape behavior: Higher noise = more particles escape forces
$3
Due to inverse square law, use much lower force values than v1.x:
| Mode | Old (v1.x) | New (v2.0+) | v3.1+ | Effect |
|------|-----------|-------------|-------|--------|
| Repel | 8-15 | 2-5 | 2-5 | Realistic bubble |
| Attract | 6-12 | 1-4 | 1-4 | Gravitational pull |
| Vortex | 10-20 | 3-8 | 3-8 | Spiral with turbulence |
| Chaos | - | - | 3-6 | Dynamic blend (NEW) |
Complete React Example
`tsx
import React, { useState, useEffect } from 'react';
import { useParticleEffect, InteractionMode } from 'particle-lsslib';function App() {
const [mode, setMode] = useState('repel');
const [force, setForce] = useState(3);
const [noise, setNoise] = useState(0.4);
const { canvasRef, loadImage, updateSettings } = useParticleEffect({
settings: {
mode,
force,
particleSize: 2,
density: 4, // Dense for smooth effect (0-5 scale: higher = more dense)
width: 450,
padding: 250, // Space for particles to move freely
mouseRadius: 200, // Large interaction radius with smooth falloff
gravity: 0, // No gravity keeps particles stable
backgroundColor: 'transparent',
noise, // Spatial distortion and turbulence
minParticleSize: 0.3, // Very small particles
maxParticleSize: 1.5, // Varied sizes for organic look
},
});
useEffect(() => {
// Load default image on mount
loadImage('/your-image.png');
}, [loadImage]);
const handleFileChange = async (e: React.ChangeEvent) => {
const file = e.target.files?.[0];
if (file) await loadImage(file);
};
const handleModeChange = (newMode: InteractionMode) => {
setMode(newMode);
updateSettings({ mode: newMode });
};
const handleForceChange = (e: React.ChangeEvent) => {
const newForce = parseFloat(e.target.value);
setForce(newForce);
updateSettings({ force: newForce });
};
const handleNoiseChange = (e: React.ChangeEvent) => {
const newNoise = parseFloat(e.target.value);
setNoise(newNoise);
updateSettings({ noise: newNoise });
};
return (
type="range"
min="1"
max="10"
step="0.5"
value={force}
onChange={handleForceChange}
/>
type="range"
min="0"
max="1"
step="0.1"
value={noise}
onChange={handleNoiseChange}
/>
);
}
`Use Cases
$3
Perfect for overlaying on other content:
`typescript
const engine = new ParticleEngine({
canvas,
settings: {
backgroundColor: 'transparent',
padding: 300,
width: 800,
},
});
`$3
For standalone displays:
`typescript
const engine = new ParticleEngine({
canvas,
settings: {
backgroundColor: '#0a0a0a',
padding: 150,
height: 600, // Width auto-calculated
},
});
`Browser Support
Works in all modern browsers that support:
- Canvas API
- ES2020
- RequestAnimationFrame
Changelog
$3
New Features:
- WebGL Worker Renderer: Fully implemented WebGL rendering in Web Worker
- Off-main-thread rendering for maximum performance
- Uses OffscreenCanvas for zero-copy rendering
- Handles 50,000+ particles without blocking UI
- Automatic mouse event forwarding to worker
- Graceful cleanup and fallback handling
- Separate Padding Controls: New paddingX and paddingY options
- Set different horizontal and vertical padding
- Overrides uniform padding when specified
- Useful for wide or tall canvas layouts
Improvements:
- Fixed canvas dimension synchronization for WebGL Worker
- Canvas dimensions now set before transferring to offscreen
- Eliminates visual artifacts and rendering issues
- Better error handling in worker initialization
- Improved TypeScript types for padding options
API Additions:
`typescript
// Separate padding control
engine.updateSettings({
paddingX: 400, // Horizontal padding
paddingY: 200, // Vertical padding
});
`Performance:
- WebGL Worker now production-ready
- Up to 10x performance improvement for high particle counts
- Smooth 60 FPS with 50,000+ particles
- Main thread remains responsive during heavy rendering
$3
New Features:
- ParticleEngineHybrid: New hybrid engine with automatic renderer selection
- Detects browser capabilities (WebGL, WebGL2, OffscreenCanvas, Web Workers)
- Automatically selects best renderer: Canvas 2D, WebGL, or WebGL Worker
- Graceful fallback if preferred renderer not supported
- Browser Capabilities Detection:
detectCapabilities() and logCapabilities() utilities
- Detect WebGL support and version
- Check OffscreenCanvas and Web Worker support
- Get maximum GPU texture size
- Automatic renderer recommendation
- Performance Monitoring: Track FPS, frame time, and particle count
- Enable with enablePerformanceMonitoring: true
- Access metrics with getPerformanceMetrics()
- Monitor renderer performance in real-time
- Enhanced Package Exports: Better ESM/CommonJS compatibility
- Explicit exports field in package.json
- Improved module resolution for bundlersAPI Additions:
`typescript
// New hybrid engine
new ParticleEngineHybrid({ canvas, renderer?, enablePerformanceMonitoring? })
engine.getRenderer() // Get active renderer
engine.getCapabilities() // Get browser capabilities
engine.getPerformanceMetrics() // Get FPS and performance data// New utilities
detectCapabilities() // Detect what browser supports
logCapabilities() // Pretty-print capabilities
`$3
New Features:
- ✨ Chaos Mode: New 'chaos' interaction mode that dynamically blends repel and vortex effects with time-based oscillations
- Time-based oscillation creates evolving, unpredictable patterns
- Each particle has unique phase for organic variation
- Perpendicular wave forces add flowing, liquid-like motion
- Enhanced turbulence for truly chaotic effects
- ✨ Dynamic Radius Control: Adjust mouse interaction radius with mouse wheel/scroll in real-time
- Scroll up to increase radius (up to 800px)
- Scroll down to decrease radius (minimum 20px - reduced from 50px)
- Changes apply instantly without page reload
- ✨ Enhanced Perlin Noise System: Upgraded brownian motion with pseudo-Perlin noise
- Smoother, more organic movement patterns
- Combines random noise with Perlin noise for natural flow
- Subtle swirling motion based on distance from particle origin
- Much more fluid and less chaotic than pure random
Improvements:
- Lower minimum radius (20px instead of 50px) for finer control
- Perlin noise creates more organic, flowing particle movement
- Better noise implementation with layered sine waves
- Chaos mode provides new creative possibilities for abstract animations
Usage:
`typescript
// Try the new Chaos mode
engine.updateSettings({
mode: 'chaos',
force: 4,
noise: 0.5,
mouseRadius: 220,
});// Adjust radius with mouse wheel while running
// Scroll up = larger radius, Scroll down = smaller radius
`$3
Breaking Changes:
-
particleSize now uses 0-5 scale where higher = larger (was arbitrary pixel values)
- density now uses 0-5 scale where higher = more dense (was inverted - higher meant less dense)
- Effective mouse radius is now 1.5x the mouseRadius setting (creates smooth falloff zone)New Features:
- ✨ Smooth falloff function: Eliminates hard edges on mouse interactions using smoothstep interpolation
- ✨ Natural interactions: Mouse effects now have invisible, organic boundaries (no visible radius circle)
- ✨ Enhanced particle escape: 25-65% of particles now escape/ignore forces (was ~30%)
- ✨ Momentum-based gravity: Gravity now amplifies with particle velocity for natural physics
- ✨ Intuitive 0-5 scales: Both
particleSize and density use logical scales
- particleSize 0-5: 0=0.5px (tiny) → 5=4px (large)
- density 0-5: 0=gap 10px (sparse) → 5=gap 1px (very dense)Improvements:
- Smoother, more organic mouse interactions without visible boundaries
- More particles visually escape the mouse effect for better realism
- Gravity feels more like momentum transfer than constant downward pull
- Much more intuitive configuration - higher numbers = more/bigger
- Better visual clarity - no harsh cutoff at interaction radius edge
Migration Guide:
`typescript
// Old (v2.x) - confusing inverted density
{
particleSize: 2, // Arbitrary pixel value
density: 4, // Lower = MORE dense (confusing!)
}// New (v3.0+) - intuitive scales
{
particleSize: 2.5, // 0-5 scale: higher = larger
density: 2.5, // 0-5 scale: higher = MORE dense (logical!)
mouseRadius: 100, // Actual effect is 1.5x with smooth falloff
}
`$3
Breaking Changes:
- Force values now use inverse square law - use lower values (2-5 instead of 8-15)
- Global mouse tracking on
window instead of canvas elementNew Features:
- ✨ Realistic inverse square law physics (like real gravity/magnetism)
- ✨ Individual particle mass (0.5-2.0) affects resistance to forces
- ✨ Variable particle sizes with
minParticleSize and maxParticleSize
- ✨ Spatial distortion effect - some particles escape, others resist
- ✨ Configurable noise/turbulence with noise parameter (0-1)
- ✨ Brownian motion for subtle random movement
- ✨ Mass-based air friction (lighter particles have more drag)
- ✨ Global mouse tracking works anywhere on pageImprovements:
- More organic, realistic particle behavior
- Better visual variation with size differences
- Dramatic spatial warping effects
- Improved physics simulation accuracy
Migration Guide:
`typescript
// Old (v1.x)
{
force: 10,
mouseRadius: 100,
}// New (v2.0+) - Use lower force values
{
force: 3, // Much lower with inverse square law
mouseRadius: 200, // Can increase radius for dramatic effect
noise: 0.4, // Add spatial distortion
minParticleSize: 0.3,
maxParticleSize: 1.5,
}
`License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Author
Created by lucqa.com by kdonjs
Keywords
particles canvas animation interactive physics react typescript webgl graphics spatial-distortion inverse-square-law realistic-physics`