Skip to content

Repository files navigation

Attractive

Live Demo License: MIT Vanilla JS

Strange attractor visualizer. Pick a chaotic system, feed it real-world data, adjust the rendering style, and see what it does.

26 attractors, 17 data sources, 30+ color palettes, 7 visual styles. No build step, just a canvas and math.

Attractive Preview

Open it →

Pick an attractor (Lorenz butterfly, Rössler spiral, Chua circuit, etc.), feed it data (climate, seismic, crypto, brain waves, live audio), and small changes in initial conditions produce wildly different patterns.

26 Attractor Systems

  • Classic: Lorenz (butterfly), Rössler (spiral band), Chua (double scroll)
  • Lorenz Family: Chen, Lü (bridge), Burke-Shaw
  • Multi-Scroll: Four-Wing, Dadras (tri-scroll), Dequan-Li, Rucklidge, Tsucs
  • Geometric: Aizawa (torus knot), Thomas (cyclical), Halvorsen (tetrahedral), Newton-Leipnik
  • Physics-Derived: Nosé-Hoover (molecular), Shimizu-Morioka (laser), Rabinovich-Fabrikant (plasma)
  • Simple Systems: Sprott (minimal), Genesio-Tesi, Arneodo, Bouali
  • Iterative Maps: Clifford (fractal), De Jong, Pickover (gnarled)

17 Data Sources

Real-world data modulates the chaos parameters:

  • Environmental: Climate (1960–2024), Weather, Ocean Currents, Tides, Solar Activity
  • Financial: Economic Indicators, Stock Market, Cryptocurrency
  • Physical: Seismic Activity, ISS Orbital Position, Traffic Flow, Power Grid
  • Biological: Heart Rate/ECG, Brain Waves/EEG, Pandemic Dynamics
  • Digital: Wikipedia Trends, Live Audio Input (microphone)

30+ Color Schemes

  • Vibrant: Bioluminescent, Neon, Electric, Cyberpunk, Acid
  • Warm: Fire, Sunset, Lava, Ember, Blood Moon, Solar, Oxidation
  • Cool: Ocean, Ice, Aurora, Forest, Arctic, Twilight
  • Cosmic: Cosmic, Nebula, Void, Supernova
  • Neutral: Monochrome, Pastel, Sepia
  • Dark: Matrix, Midnight, Obsidian
  • Scientific: Viridis, Plasma, Infrared, Stellar

7 Visual Styles

  • Clean - Crisp lines with subtle glow (default)
  • Da Vinci - Ink on aged parchment, hand-drawn lines
  • Blueprint - Cyanotype (white-on-blue) technical drawing with grid
  • Neon - Glowing tubes with strong blur
  • Chalk - Rough strokes on blackboard texture
  • Oscilloscope - Green phosphor on CRT with scanlines
  • Watercolor - Pastel washes with bleeding pigments

21 Mathematical Presets

Famous bifurcation points and special parameter combinations:

  • Lorenz Classic (σ=10, ρ=28)
  • Lorenz Periodic (ρ=24.74)
  • Rössler Funnel vs. Screw
  • Chua Double Scroll vs. Spiral
  • Four-Wing Symmetric
  • Thomas Slow (b=0.18)
  • and 15 more...

Controls

Mouse & Touch

  • Drag to rotate the 3D view
  • Shift+Drag or Right-click drag to pan
  • Scroll to zoom
  • Touch: 1-finger rotate, 2-finger pan/pinch zoom

Keyboard

  • Space - Play/pause animation
  • R - Random combination
  • Ctrl+Z / Cmd+Z - Undo last change
  • F - Fullscreen
  • Arrow keys - Rotate view
  • Escape - Close modal

Floating Toolbar

Bottom-left buttons control speed, trigger a random combo, export to PNG, and show help.

Other features

Random button pulls from 40+ hand-picked combos. Ctrl+Z steps back through changes. Auto-rotate, parameter sweeping, PNG export. Guided tour on first visit. Controls include keyboard shortcuts, named buttons, and screen reader announcements. Responsive layouts support mobile screens.

Explore the mathematics

A second toolbar opens equations, a WebGL 3D view, a numerical Lyapunov estimate, and five guided lessons. Tap a trajectory to inspect a point; hold to restart from it. With either canvas focused, Enter inspects the center. Arrow keys rotate the 3D camera and plus/minus zoom it.

The 3D view supports single or multiple trajectories, color, speed, glow, pause, rotation, and PNG export. Its line renderer is separate from the artistic Canvas 2D styles. Reduced motion produces a static view. Equations and lessons remain available if WebGL cannot start.

Lessons apply standard model parameters, overriding the current dataset defaults. Completion is stored in this browser. The twin-trajectory sensitive-dependence demonstration is not included; the lessons do not claim to show it.

The largest Lyapunov exponent uses an independent fixed-step RK4 trajectory. It is an evolving numerical estimate for the current parameters, not a convergence guarantee. Display speed does not set its integration step. Discrete maps (Clifford, De Jong and Pickover) report that the estimate is unavailable. The view's Euler integration and the measurement's RK4 integration serve different purposes.

Quick Start

No build step required. Serve the directory with any static HTTP server:

python3 -m http.server 8000
# Open http://localhost:8000/

Or open index.html directly in a modern browser. Classic scripts share the application state; no bundler is required. Three.js and KaTeX are bundled locally. Optional sketch styles, fonts, and analytics retain their existing external sources.

How It Works

Each attractor is a system of three differential equations describing how a point moves through 3D space. The equations are integrated using Euler's method at 60fps.

Real-world data from the selected source modulates the chaos parameters (σ, ρ, β for Lorenz; a, b, c for Rössler; etc.). Each dataset–attractor combination has curated defaults that produce clear, distinct visualizations.

The rendering loop:

  1. Compute new particle positions using attractor equations
  2. Apply 3D rotation based on mouse/touch input
  3. Project 3D coordinates to 2D screen space
  4. Draw particle trails with style-specific effects (glow, hand-drawn lines, color transforms)
  5. Apply depth-based brightness and trail fade

Tech Stack

Vanilla JavaScript, with Three.js for the optional WebGL view, KaTeX for equations, and Rough.js for hand-drawn styles. See third-party notices. No framework or build step.

  • Rendering: HTML5 Canvas 2D API
  • Math: Euler integration of differential equations at 60fps
  • 3D Projection: Manual rotation matrix + orthographic projection
  • Artistic Effects: Rough.js for hand-drawn line styles
  • Accessibility: Semantic HTML5, ARIA landmarks, screen reader announcements

Project Structure

attractive/
├── index.html       # Layout, controls, modal (490 lines)
├── main.js          # All logic: attractors, datasets, rendering (2530 lines)
├── style.css        # Dark theme, responsive layout (1850 lines)
├── attractive-*.js  # 3D, equations, inspection, lessons and exponent estimate
├── analysis-tools.css # Responsive analysis controls
├── vendor/          # Bundled Three.js and KaTeX with licenses
├── tests/           # Browser integration checks
├── onboarding.js    # First-visit guided tour (165 lines)
├── social-card.png  # Open Graph preview image
└── README.md        # This file

Verification

node --check attractive-3d.js checks script syntax; repeat for the other attractive-*.js files. Serve the repository locally, start a separate Chromium instance with a remote debugging port, then run:

node tests/browser.mjs 9439 http://127.0.0.1:5059/

The browser check covers bundled dependency loading with external requests blocked, panels and focus, lesson parameter consistency, 3D pause/resume, reduced motion, keyboard inspection, a standard Lorenz estimate, map exclusion, and a 390px toolbar. It does not establish assistive-technology conformance or physical-device performance.

Adding Your Own Attractor

Add an entry to the attractors object in main.js:

myattractor: {
  name: 'My Attractor',
  description: 'What makes this system interesting.',
  params: [
    { name: 'α (Alpha)', min: 0, max: 10, step: 0.1, default: 5, tooltip: 'Controls X behavior' },
    { name: 'β (Beta)', min: 0, max: 20, step: 0.1, default: 10, tooltip: 'Controls Y behavior' },
    { name: 'γ (Gamma)', min: 0, max: 30, step: 0.1, default: 15, tooltip: 'Controls Z behavior' }
  ],
  compute: (x, y, z, params, dt) => {
    const dx = /* your equation */;
    const dy = /* your equation */;
    const dz = /* your equation */;
    return [x + dx * dt, y + dy * dt, z + dz * dt];
  },
  scale: 10,            // Zoom multiplier
  initPos: [0.1, 0, 0], // Starting position
  initSpread: 0.5       // Random spread
}

Then add a corresponding <option> in index.html under #attractorSelect.

License

MIT. See LICENSE for details.

Author

Luke Steuber · lukesteuber.com · @lukesteuber.com

Part of the data visualization portfolio at dr.eamer.dev.

About

Interactive 3D chaos attractor visualization with real-world data

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages