Skip to content

Repository files navigation

MAGNETIC MEMORY — A 3D Experience

A real-time WebGL study of a vintage portable cassette recorder, built with React + Three.js. The recorder is fully procedural (no downloaded mesh): body, hinged transparent deck door, cassette with spinning reels, and the open transport mechanism — sliding head deck, capstan, pinch roller, reel spindles, tape guides, piano keys, volume knob — all modeled in code.

Art direction: titanium-silver body with graphite trim on a warm charcoal stage ("museum lighting" — the product glows, the room stays dark). Amber rim light, warm key from upper left, film grain overlay.

The composition targets 1440 × 1024 desktop, with a responsive mobile layout (390 × 844).

Run

npm install
npm run dev      # http://127.0.0.1:5173
npm run build    # production build → dist/
npm run preview  # serve the production build

Designs

Three complete UI directions sharing the same procedural cobalt machine (switcher at the bottom center; persisted; ?design=<id> to force one). Each changes layout, typography, palette and light rig (src/data/designs.js):

  • editorialEDITORIAL: gallery-catalog page. Playfair Display serif masthead ("Magnetic Memory" with an italic ember accent), hairline rules, small-caps meta, porcelain canvas.
  • swissSWISS: international-typographic grid. Space Grotesk mega title, numbered meta row (01 / OBJECT · CP-1978 · ©2026), 2px grid rules, bordered control blocks, hard square corners.
  • auroraAURORA: cinematic dark stage with teal/violet aurora glows, frosted-glass controls, minimal floating label, teal accent.

The model

  • src/components/recorder/RecorderModel.jsx — assembly + animation. The chassis is four blocks leaving a real deck slot (no fake dark panels), so the recessed well is genuine geometry.
  • src/components/recorder/Cassette.jsx — compact cassette: label sticker, open tape window, two reels (toothed hub + wound tape disc). Wound-tape fill follows playback progress; spin speed is inversely proportional to fill.
  • src/components/recorder/parts.jsx — deck mechanism (sliding head deck with record/play + erase heads, capstan, flywheel, pinch roller, tape guides, springs, reel spindles, screws), hinged acrylic deck door, transport key row (RECORD / REW / FF / PLAY / STOP / PAUSE), side panel (knurled volume knob, PHONES / MIC / DC IN jacks).
  • src/components/recorder/textures.js — all textures generated at runtime on canvas: brushed metal, faceplate lettering, cassette label, reel hubs, screw heads, key glyphs, knurling.
  • src/components/recorder/materials.js — cobalt painted metal (clearcoat), brushed silver, steel, rubber, acrylic.

Interactions

  • Cassette shelf (left): five tapes, five tracks. Click a tape (or turn the wheel / swipe / arrow keys) to glide it into the center highlight — browsing never touches the deck. Double-click the highlighted tape to load it: the tape in the deck flies out on an arc, flips its label at the apex, and settles back on the door. The 3D cassette label, shelf highlight and audio track all switch together. Double-clicking the deck's own tape toggles play/pause.
  • The play ritual: pressing play seats the cassette into the well (click), swings the door shut, depresses the PLAY key (click) and starts the music. Pause keeps the tape loaded; resume is instant.
  • Working piano keys on the machine itself (clickable): PLAY — play/pause · PAUSE — pause · STOP — stop + back to 0:00 · REW / FF — skip −10s / +10s · RECORD — arms the REC indicator LED. Keys physically depress while engaged.
  • EXPLODE — stops the tape, then separates the recorder into its assemblies with a staggered cascade; ASSEMBLE puts it back together.
  • Drag to rotate / scroll to zoom (pan disabled, zoom & pitch clamped).
  • Music: three user-provided tracks in public/audio/ (Drake — God's Plan · Justin Bieber & Nicki Minaj — Beauty And A Beat · Kanye West — Violent Crimes) plus seven royalty-free Kevin MacLeod tracks (CC-BY) filling the 10-tape shelf. The user-provided songs are commercially copyrighted — for this local MVP/demo only, do not redistribute.
  • Circular speaker button (top right) mutes everything.
  • prefers-reduced-motion is respected (no spin / tweens).

Tech

  • React 18 + Vite 5, Three.js + @react-three/fiber + @react-three/drei
  • Icons: @phosphor-icons/react
  • Fonts (bundled via @fontsource): Anton, IBM Plex Mono
  • Audio: Web Audio API (procedural click + motor hum, no audio files)

Assets & licenses

  • 3D model: procedural, created for this project — no external mesh, no paid assets, no runtime CDN requests.
  • Music: "Electrodoodle" — Kevin MacLeod (incompetech.com), CC-BY 3.0/4.0, bundled locally at public/audio/music.mp3.
  • Anton / IBM Plex Mono — Google Fonts via @fontsource (OFL).
  • An earlier iteration used the Poly Haven cassette_player (Oday Abuzaeed, CC0); the current build no longer ships it.

QA

See visual-qa.md for the screenshot → compare → fix rounds (layout v1, procedural model v2), interaction tests, console status and limitations. Final captures in screenshots/final/; capture script: node scripts/shoot.mjs <outdir>.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages