Copy to your AI coding assistant, paste, and use instantly
Want your own animation? Use the converter to convert any GIF or video, then click “Copy Component” to get code with your frames embedded.
Save as src/components/AsciiAnimation.tsx
"use client";
import { useState, useEffect, useRef } from "react";
// To use your own animation:
// 1. Go to the converter: https://your-domain.com/ascii-animation
// 2. Upload your GIF or video
// 3. Click "Copy Component" to get code with your frames embedded
// Example ASCII fish frames (replace with your own)
const FRAMES = [
{"rows":[[{"char":" ","opacity":0},{"char":" ","opacity":0},{"char":" ","opacity":0},{"char":"0","opacity":0.8},{"char":"1","opacity":0.6}],[{"char":" ","opacity":0},{"char":"0","opacity":0.9},{"char":"1","opacity":0.5},{"char":"0","opacity":0.7},{"char":"1","opacity":0.4}],[{"char":"1","opacity":0.6},{"char":"0","opacity":0.8},{"char":"1","opacity":0.5},{"char":"0","opacity":0.9},{"char":" ","opacity":0}]]},
{"rows":[[{"char":" ","opacity":0},{"char":" ","opacity":0},{"char":"1","opacity":0.7},{"char":"0","opacity":0.9},{"char":" ","opacity":0}],[{"char":" ","opacity":0},{"char":"1","opacity":0.8},{"char":"0","opacity":0.6},{"char":"1","opacity":0.5},{"char":"0","opacity":0.7}],[{"char":"0","opacity":0.5},{"char":"1","opacity":0.9},{"char":"0","opacity":0.6},{"char":"1","opacity":0.8},{"char":" ","opacity":0}]]}
];
export default function AsciiAnimation({
fps = 12,
fontSize = 6,
textColor = "#1e3a5f",
className = "",
}) {
const [currentFrame, setCurrentFrame] = useState(0);
const animationRef = useRef(null);
const lastTimeRef = useRef(0);
useEffect(() => {
if (FRAMES.length === 0) return;
const frameInterval = 1000 / fps;
const animate = (timestamp) => {
if (timestamp - lastTimeRef.current >= frameInterval) {
lastTimeRef.current = timestamp;
setCurrentFrame((prev) => (prev + 1) % FRAMES.length);
}
animationRef.current = requestAnimationFrame(animate);
};
animationRef.current = requestAnimationFrame(animate);
return () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
};
}, [fps]);
if (FRAMES.length === 0) return null;
return (
<div
className={className}
style={{
fontFamily: "monospace",
fontSize: `${fontSize}px`,
lineHeight: 1,
}}
>
{FRAMES[currentFrame]?.rows.map((row, rowIdx) => (
<div key={rowIdx} style={{ whiteSpace: "pre", height: `${fontSize}px` }}>
{row.map((cell, colIdx) => (
<span
key={colIdx}
style={{
color: textColor,
opacity: cell.opacity,
}}
>
{cell.char}
</span>
))}
</div>
))}
</div>
);
}// Basic usage
<AsciiAnimation />
// Custom styling
<AsciiAnimation
fps={18}
fontSize={8}
textColor="#00ff00"
className="my-4"
/>
// In a hero section
<div className="relative h-screen flex items-center justify-center">
<AsciiAnimation fontSize={10} />
</div>fpsAnimation speed (default: 12)
fontSizeCharacter size in pixels (default: 6)
textColorAny CSS color (default: #1e3a5f)
classNameAdditional Tailwind/CSS classes
"use client";
import { useState, useEffect, useRef } from "react";
// To use your own animation:
// 1. Go to the converter: https://your-domain.com/ascii-animation
// 2. Upload your GIF or video
// 3. Click "Copy Component" to get code with your frames embedded
// Example ASCII fish frames (replace with your own)
const FRAMES = [
{"rows":[[{"char":" ","opacity":0},{"char":" ","opacity":0},{"char":" ","opacity":0},{"char":"0","opacity":0.8},{"char":"1","opacity":0.6}],[{"char":" ","opacity":0},{"char":"0","opacity":0.9},{"char":"1","opacity":0.5},{"char":"0","opacity":0.7},{"char":"1","opacity":0.4}],[{"char":"1","opacity":0.6},{"char":"0","opacity":0.8},{"char":"1","opacity":0.5},{"char":"0","opacity":0.9},{"char":" ","opacity":0}]]},
{"rows":[[{"char":" ","opacity":0},{"char":" ","opacity":0},{"char":"1","opacity":0.7},{"char":"0","opacity":0.9},{"char":" ","opacity":0}],[{"char":" ","opacity":0},{"char":"1","opacity":0.8},{"char":"0","opacity":0.6},{"char":"1","opacity":0.5},{"char":"0","opacity":0.7}],[{"char":"0","opacity":0.5},{"char":"1","opacity":0.9},{"char":"0","opacity":0.6},{"char":"1","opacity":0.8},{"char":" ","opacity":0}]]}
];
export default function AsciiAnimation({
fps = 12,
fontSize = 6,
textColor = "#1e3a5f",
className = "",
}) {
const [currentFrame, setCurrentFrame] = useState(0);
const animationRef = useRef(null);
const lastTimeRef = useRef(0);
useEffect(() => {
if (FRAMES.length === 0) return;
const frameInterval = 1000 / fps;
const animate = (timestamp) => {
if (timestamp - lastTimeRef.current >= frameInterval) {
lastTimeRef.current = timestamp;
setCurrentFrame((prev) => (prev + 1) % FRAMES.length);
}
animationRef.current = requestAnimationFrame(animate);
};
animationRef.current = requestAnimationFrame(animate);
return () => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
};
}, [fps]);
if (FRAMES.length === 0) return null;
return (
<div
className={className}
style={{
fontFamily: "monospace",
fontSize: `${fontSize}px`,
lineHeight: 1,
}}
>
{FRAMES[currentFrame]?.rows.map((row, rowIdx) => (
<div key={rowIdx} style={{ whiteSpace: "pre", height: `${fontSize}px` }}>
{row.map((cell, colIdx) => (
<span
key={colIdx}
style={{
color: textColor,
opacity: cell.opacity,
}}
>
{cell.char}
</span>
))}
</div>
))}
</div>
);
}