import React, { useState, useEffect, useRef } from 'react'; import { Play, Pause, RotateCcw, Zap } from 'lucide-react'; const ViralTurtleArt = () => { const canvasRef = useRef(null); const [isPlaying, setIsPlaying] = useState(false); const [pattern, setPattern] = useState('spiral'); const [speed, setSpeed] = useState(50); const animationRef = useRef(null); const turtleRef = useRef({ x: 400, y: 400, angle: 0 }); const patterns = { spiral: { name: '🌀 Rainbow Spiral', viral: true }, flower: { name: '🌸 Blooming Flower', viral: true }, galaxy: { name: '🌌 Cosmic Galaxy', viral: true }, mandala: { name: '🕉️ Sacred Mandala', viral: true }, fractal: { name: '❄️ Fractal Snowflake', viral: true } }; const drawPattern = (ctx, turtle, step) => { const patterns = { spiral: () => { const angle = step * 3; const radius = step * 0.5; const hue = (step * 2) % 360; ctx.strokeStyle = `hsla(${hue}, 100%, 60%, 0.8)`; ctx.lineWidth = 3; ctx.lineCap = 'round'; const newX = 400 + Math.cos(angle * Math.PI / 180) * radius; const newY = 400 + Math.sin(angle * Math.PI / 180) * radius; ctx.beginPath(); ctx.moveTo(turtle.x, turtle.y); ctx.lineTo(newX, newY); ctx.stroke(); // Glow effect ctx.shadowBlur = 15; ctx.shadowColor = `hsl(${hue}, 100%, 60%)`; ctx.stroke(); ctx.shadowBlur = 0; turtle.x = newX; turtle.y = newY; }, flower: () => { const petals = 12; const petalIndex = Math.floor(step / 20) % petals; const petalProgress = (step % 20) / 20; const angle = (petalIndex * 360 / petals) * Math.PI / 180; const radius = 150 * Math.sin(petalProgress * Math.PI); const hue = (petalIndex * 30 + step) % 360; ctx.strokeStyle = `hsla(${hue}, 100%, 60%, 0.6)`; ctx.lineWidth = 4; ctx.lineCap = 'round'; const x = 400 + Math.cos(angle) * radius; const y = 400 + Math.sin(angle) * radius; ctx.beginPath(); ctx.moveTo(turtle.x, turtle.y); ctx.lineTo(x, y); ctx.stroke(); ctx.shadowBlur = 20; ctx.shadowColor = `hsl(${hue}, 100%, 60%)`; ctx.stroke(); ctx.shadowBlur = 0; turtle.x = x; turtle.y = y; }, galaxy: () => { const arms = 3; const armIndex = step % arms; const t = step * 0.1; const armAngle = (armIndex * 360 / arms + t * 5) * Math.PI / 180; const radius = t * 2; const spiralAngle = t * 0.3; const x = 400 + Math.cos(armAngle + spiralAngle) * radius; const y = 400 + Math.sin(armAngle + spiralAngle) * radius; const hue = (200 + step * 0.5) % 360; const saturation = 100 - (radius / 3); // Stars if (step % 5 === 0) { ctx.fillStyle = `hsla(${hue}, ${saturation}%, 80%, 0.9)`; ctx.shadowBlur = 10; ctx.shadowColor = 'white'; ctx.beginPath(); ctx.arc(x, y, 2, 0, Math.PI * 2); ctx.fill(); ctx.shadowBlur = 0; } // Nebula trails ctx.strokeStyle = `hsla(${hue}, ${saturation}%, 60%, 0.3)`; ctx.lineWidth = 3; ctx.beginPath(); ctx.moveTo(turtle.x, turtle.y); ctx.lineTo(x, y); ctx.stroke(); turtle.x = x; turtle.y = y; }, mandala: () => { const layers = 8; const points = 12; const layer = Math.floor(step / points) % layers; const pointIndex = step % points; const angle = (pointIndex * 360 / points) * Math.PI / 180; const radius = 50 + layer * 30; const hue = (layer * 45 + pointIndex * 10) % 360; const x = 400 + Math.cos(angle) * radius; const y = 400 + Math.sin(angle) * radius; // Symmetrical patterns for (let sym = 0; sym < 2; sym++) { const symAngle = angle + sym * Math.PI; const sx = 400 + Math.cos(symAngle) * radius; const sy = 400 + Math.sin(symAngle) * radius; ctx.strokeStyle = `hsla(${hue}, 100%, 60%, 0.7)`; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(400, 400); ctx.lineTo(sx, sy); ctx.stroke(); ctx.shadowBlur = 15; ctx.shadowColor = `hsl(${hue}, 100%, 60%)`; ctx.stroke(); ctx.shadowBlur = 0; // Ornaments ctx.fillStyle = `hsla(${hue}, 100%, 70%, 0.8)`; ctx.beginPath(); ctx.arc(sx, sy, 4, 0, Math.PI * 2); ctx.fill(); } turtle.x = x; turtle.y = y; }, fractal: () => { const branches = 6; const depth = Math.floor(step / 30) % 4; const branchIndex = step % branches; const angle = (branchIndex * 360 / branches + depth * 15) * Math.PI / 180; const length = 200 / Math.pow(2, depth); const hue = (180 + depth * 30 + branchIndex * 20) % 360; const endX = turtle.x + Math.cos(angle) * length; const endY = turtle.y + Math.sin(angle) * length; ctx.strokeStyle = `hsla(${hue}, 100%, 70%, ${0.9 - depth * 0.2})`; ctx.lineWidth = 4 - depth; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(turtle.x, turtle.y); ctx.lineTo(endX, endY); ctx.stroke(); ctx.shadowBlur = 10; ctx.shadowColor = `hsl(${hue}, 100%, 70%)`; ctx.stroke(); ctx.shadowBlur = 0; if (step % 30 === 0) { turtle.x = 400; turtle.y = 400; } else { turtle.x = endX; turtle.y = endY; } } }; if (patterns[pattern]) { patterns[pattern](); } }; const animate = () => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); let step = 0; const draw = () => { if (!isPlaying) return; drawPattern(ctx, turtleRef.current, step); step++; if (step > 500) { step = 0; resetCanvas(); } animationRef.current = setTimeout(draw, 100 - speed); }; draw(); }; const resetCanvas = () => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext('2d'); ctx.fillStyle = '#000000'; ctx.fillRect(0, 0, 800, 800); turtleRef.current = { x: 400, y: 400, angle: 0 }; }; useEffect(() => { resetCanvas(); }, []); useEffect(() => { if (isPlaying) { animate(); } else { if (animationRef.current) { clearTimeout(animationRef.current); } } return () => { if (animationRef.current) { clearTimeout(animationRef.current); } }; }, [isPlaying, pattern, speed]); const handlePatternChange = (newPattern) => { setPattern(newPattern); setIsPlaying(false); resetCanvas(); }; return (
Create mesmerizing patterns that'll blow up on TikTok