Baktiyar Ablaikhan

Chromatic Split Glow

Source
arlan.me/vault ↗
Author
Arlan
Licence
MIT

Loading…

The word chrome glowing on a dark card with a shifting rainbow chromatic-aberration split that follows the cursor.

Code

"use client";

import { approach, drawBlurred, useStage, type Scene } from "./stage";

/*
 * "chrome" glowing on a dark card, split into a shifting rainbow of offset
 * copies that add back to white at the core. The split follows the cursor;
 * left alone, it drifts in a slow orbit.
 */

const HUES = 7;

function createScene(): Scene {
  const aim = { x: 0, y: 0 };
  return {
    frame({ ctx, w, h, t, dt, p }) {
      ctx.fillStyle = "#1c2133";
      ctx.fillRect(0, 0, w, h);
      const cx = w / 2;
      const cy = h / 2;
      const size = Math.min(h * 0.36, w * 0.21);
      // aim: from the word toward the pointer, or an idle orbit
      const tx = p.inside ? (p.x - cx) / w : Math.cos(t * 0.6) * 0.45;
      const ty = p.inside ? (p.y - cy) / h : Math.sin(t * 0.8) * 0.3;
      aim.x = dt === 0 ? tx : approach(aim.x, tx, 5, dt);
      aim.y = dt === 0 ? ty : approach(aim.y, ty, 5, dt);
      const spread = size * 0.16;

      ctx.font = `800 ${size}px "Helvetica Neue", Inter, "Segoe UI", Arial, sans-serif`;
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      const paint = (x: number, y: number) => (c: CanvasRenderingContext2D) => {
        c.fillStyle = "#000";
        c.fillText("chrome", x, y);
      };

      // soft glow behind
      ctx.globalAlpha = 0.55;
      drawBlurred(ctx, size * 0.5, "#6d7cff", paint(cx, cy));
      ctx.globalAlpha = 0.35;
      drawBlurred(ctx, size * 0.18, "#c7d0ff", paint(cx, cy));
      ctx.globalAlpha = 1;

      // rainbow split, additive
      ctx.globalCompositeOperation = "lighter";
      const shift = t * 40;
      for (let i = 0; i < HUES; i++) {
        const k = i / (HUES - 1) - 0.5;
        const hue = (shift + i * (300 / (HUES - 1))) % 360;
        const ox = aim.x * spread * 10 * k;
        const oy = aim.y * spread * 10 * k;
        ctx.fillStyle = `hsla(${hue},100%,56%,0.3)`;
        ctx.fillText("chrome", cx + ox, cy + oy);
        ctx.globalAlpha = 0.35;
        drawBlurred(ctx, size * 0.06, `hsl(${hue},100%,60%)`, paint(cx + ox, cy + oy));
        ctx.globalAlpha = 1;
      }
      // white-hot core
      ctx.fillStyle = "rgba(255,255,255,0.12)";
      ctx.fillText("chrome", cx, cy);
      ctx.globalCompositeOperation = "source-over";
    },
  };
}

export default function ChromaSplit() {
  const ref = useStage(createScene, 1);
  return <div ref={ref} className="relative h-full w-full overflow-hidden bg-[#1c2133]" />;
}
Prompt

Build "Chromatic Split Glow", a text animation. What it does: The word chrome glowing on a dark card with a shifting rainbow chromatic-aberration split that follows the cursor. Write it as a single self-contained React component in TypeScript that fills its parent (w-full h-full), styled with Tailwind CSS. Technique: an HTML canvas, a requestAnimationFrame loop, pointer tracking. It sits on a dark background, in a 16:10 frame. Respect prefers-reduced-motion with a still state, pause work when the element is off screen, and keep it accessible. Original: https://www.arlan.me/vault (Arlan, MIT).