Glyph Matrix
magicui/glyph-matrixFreeComponent
An animated grid of subtly shifting glyphs with fade effect and theme support.
Live preview
live · rendered by the registry
Rendered by magicui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://magicui.design/r/glyph-matrix.jsonSource
1"use client"23import { useEffect, useRef } from "react"45import { cn } from "@/lib/utils"67interface GlyphMatrixProps extends React.HTMLAttributes<HTMLCanvasElement> {8 /** Characters to randomly pick from */9 glyphs?: string10 /** Cell size in px (also font size) */11 cellSize?: number12 /** Probability (0-1) a cell mutates each tick */13 mutationRate?: number14 /** Tick interval in ms */15 interval?: number16 /** Fade out toward bottom (0 = no fade) */17 fadeBottom?: number18 /** Glyph color (any CSS color). Pass a theme-aware value from the consumer. */19 color?: string20}2122/**23 * GlyphMatrix — an animated grid of subtly shifting glyphs.24 * Pass a `color` prop (e.g. driven by next-themes) to adapt it to25 * light and dark modes.26 */27export function GlyphMatrix({28 glyphs = "01·•+*/\\<>=",29 cellSize = 14,30 mutationRate = 0.04,31 interval = 90,32 className,33 fadeBottom = 0.6,34 color = "#6B7280",35 style,36 ...props37}: GlyphMatrixProps) {38 const canvasRef = useRef<HTMLCanvasElement | null>(null)39 // Current glyph color as RGBA (a in 0-1). Kept in a ref so a color change40 // (e.g. theme toggle) recolors the next frame without restarting the41 // animation. Defaults to #6B7280.42 const rgbaRef = useRef({ r: 107, g: 114, b: 128, a: 1 })4344 // Resolve the CSS color string to RGBA (handles hex, rgb, hsl, oklch, ...).45 useEffect(() => {46 const probe = document.createElement("canvas")47 probe.width = 148 probe.height = 149 const probeCtx = probe.getContext("2d")50 if (!probeCtx) return51 // Seed with the default so an invalid color falls back to it: the 2d52 // context keeps the previous fillStyle when assigned an invalid value53 // instead of silently turning black.54 probeCtx.fillStyle = "#6B7280"55 probeCtx.fillStyle = color56 probeCtx.fillRect(0, 0, 1, 1)57 const [r, g, b, a] = probeCtx.getImageData(0, 0, 1, 1).data58 rgbaRef.current = { r, g, b, a: a / 255 }59 }, [color])6061 useEffect(() => {62 const canvas = canvasRef.current63 if (!canvas) return6465 const ctx = canvas.getContext("2d")66 if (!ctx) return6768 let cols = 069 let rows = 070 let cells: string[] = []71 let alphas: number[] = []72 let raf = 073 let last = 074 let stopped = false7576 const resize = () => {77 const dpr = window.devicePixelRatio || 178 const { clientWidth: w, clientHeight: h } = canvas7980 canvas.width = w * dpr81 canvas.height = h * dpr82 ctx.setTransform(dpr, 0, 0, dpr, 0, 0)8384// … truncated
Files it writes
More from magicui
All 247 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Androidandroid | magicui | Components | Free | no deps | |
| Animated Beamanimated-beam | magicui | Components | Free | 1 dep | |
| Animated Circular Progress Baranimated-circular-progress-bar | magicui | Components | Free | no deps | |
| Animated Gradient Textanimated-gradient-text | magicui | Components | Free | no deps | |
| Animated Grid Patternanimated-grid-pattern | magicui | Components | Free | 1 dep | |
| Animated Listanimated-list | magicui | Components | Free | 1 dep | |
| Animated Shiny Textanimated-shiny-text | magicui | Components | Free | no deps | |
| Theme Toggleranimated-theme-toggler | magicui | Components | Free | 1 dep |
