ASCII Donut Math Animation — 30 Days Web Challenge Day 2

Published: (May 11, 2026 at 10:06 PM EDT)
3 min read
Source: Dev.to

Source: Dev.to

Overview

The classic donut.c program renders a spinning 3D torus using ASCII characters. For Day 2 of the 30 Days Web Challenge, the animation was ported to the browser with interactive glitch effects and sound. The donut appears as the “0” in “30 Days” on the landing page and hides easter‑egg animations.

Features

  • Mathematical torus rendering – classic sin/cos projection with a z‑buffer and luminance mapping.
  • Smooth rotation – two angles (A and B) increment each frame for continuous spinning.
  • Glitch mode – clicking the donut adds random rotation offsets and scrambles luminance values.
  • Neon glow styling – cyan text with a text‑shadow for a retro terminal feel; glitch switches to a chaotic rainbow glow.
  • Interactive easter egg – after five clicks the donut explodes into 30 colored particles, accompanied by synthesized sound.

Core Rendering Code

const render = () => {
  const b = new Int8Array(width * height).fill(-1); // output buffer
  const z = new Float32Array(width * height);       // z‑buffer

  const sA = Math.sin(A), cA = Math.cos(A);
  const sB = Math.sin(B), cB = Math.cos(B);

  for (let j = 0; j  0 && y  0 && x  z[o]) {
        z[o] = D;
        b[o] = N > 0 ? N : -1;
      }
    }
  }

  // Render to  element using luminance characters
  if (preRef.current) {
    let s = "";
    for (let k = 0; k  0 && k % width === 0) s += "\n";
      s += b[k] >= 0 ? lum[b[k]] : " ";
    }
    preRef.current.textContent = s;
  }

  A += 0.015;
  B += 0.008;
  frameId = requestAnimationFrame(render);
};

The luminance string ".,-~:;=!*#$@" maps brightness values to ASCII characters, from dim (.) to bright (@).

Glitch Effect

// Glitch: add random rotation offset
const glitchA = glitching ? (Math.random() - 0.5) * 0.5 : 0;
const glitchB = glitching ? (Math.random() - 0.5) * 0.3 : 0;

// During glitch, randomly scramble luminance
if (glitching && Math.random()  0 ? N : -1;
}

Visual Styling

style={{
  color: glitching ? `hsl(${Math.random() * 360}, 100%, 70%)` : "#00AFFF",
  textShadow: glitching
    ? "0 0 8px #ff0066, 0 0 20px #ff6600"
    : "0 0 6px #00AFFF, 0 0 20px #0077ff",
}}

Interaction Logic

const handleDonutClick = useCallback(() => {
  if (isGlitching || isExploding || showDonutPopup) return;
  const newCount = donutClicks + 1;

  if (newCount >= 5) {
    // BOOM!
    setDonutClicks(0);
    setIsExploding(true);
    playExplosionSound();

    const colors = ["#00AFFF", "#00E676", "#ff0066", "#ff6600", "#6C5CE7", "#FFD700"];
    const particles = Array.from({ length: 30 }, (_, i) => ({
      id: explosionId.current++,
      x: 50, y: 40,
      angle: (i / 30) * Math.PI * 2 + Math.random() * 0.5,
      speed: 5 + Math.random() * 15,
      color: colors[i % colors.length],
    }));
    setExplosionParticles(particles);
  } else {
    // Glitch for 1 second
    setDonutClicks(newCount);
    setIsGlitching(true);
    playGlitchSound();
  }
}, [donutClicks, isGlitching, isExploding, showDonutPopup]);

Technology Stack

TechnologyRole
Next.jsReact framework
TypeScriptType‑safe math operations
Canvas / <pre> elementASCII character rendering
Web Audio APIGlitch and explosion sound synthesis
Framer MotionParticle animations for the explosion

Live Demo & Source

  • Live Demo:
  • Source Code: (key file: DonutAnimation.tsx)
  • Original donut.c:

Originally published at

0 views
Back to Blog

Related posts

Read more »

What is React.js

What is React.js React helps developers create: - Websites - Single Page Applications SPA - Dashboards - E-commerce apps - Social media apps - Mobile apps with...