import React from 'react'; import { useCurrentFrame, useVideoConfig, interpolate, Easing, AbsoluteFill, spring, } from 'remotion'; // ============================================================================= // COMPOSITION CONFIG // ============================================================================= export const compositionConfig = { id: 'TenKCelebration', durationInSeconds: 6, fps: 30, width: 1080, height: 1920, }; // ============================================================================= // PROPS INTERFACE // ============================================================================= interface TenKCelebrationProps { primaryColor?: string; secondaryColor?: string; accentColor?: string; backgroundColor?: string; mainText?: string; subText?: string; } // ============================================================================= // STYLE CONSTANTS // ============================================================================= const EASINGS = { easeOut: Easing.bezier(0.33, 1, 0.68, 1), easeInOut: Easing.bezier(0.37, 0, 0.63, 1), overshoot: Easing.bezier(0.34, 1.56, 0.64, 1), elastic: Easing.bezier(0.68, -0.6, 0.32, 1.6), }; // ============================================================================= // PRE-GENERATED DATA // ============================================================================= const seededRandom = (seed: number): number => { const x = Math.sin(seed * 9999) * 10000; return x - Math.floor(x); }; // Pixel grid definitions for "10K" const DIGIT_1 = [ [0, 1], [1, 0], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [5, 0], [5, 2], ]; const DIGIT_0 = [ [0, 0], [0, 1], [0, 2], [0, 3], [1, 0], [1, 3], [2, 0], [2, 3], [3, 0], [3, 3], [4, 0], [4, 3], [5, 0], [5, 1], [5, 2], [5, 3], ]; const LETTER_K = [ [0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [2, 1], [1, 2], [3, 2], [0, 3], [4, 3], [5, 4], ]; // Generate confetti colors dynamically based on props const getConfettiColors = (primary: string, secondary: string, accent: string) => [ primary, secondary, accent, '#FFD700', '#FF6B6B', '#A855F7', '#F472B6' ]; // Generate confetti particles const CONFETTI_COUNT = 80; const generateConfetti = (colors: string[]) => Array.from({ length: CONFETTI_COUNT }, (_, i) => ({ x: seededRandom(i * 7) * 1080, delay: seededRandom(i * 13) * 40, speed: 0.5 + seededRandom(i * 19) * 1.5, rotation: seededRandom(i * 23) * 360, rotationSpeed: (seededRandom(i * 29) - 0.5) * 15, size: 8 + seededRandom(i * 31) * 16, colorIndex: Math.floor(seededRandom(i * 37) * colors.length), shape: Math.floor(seededRandom(i * 41) * 3), wobbleSpeed: 2 + seededRandom(i * 43) * 4, wobbleAmount: 20 + seededRandom(i * 47) * 40, })); const confettiParticles = generateConfetti([]); // Floating particles background const FLOATING_COUNT = 40; const floatingParticles = Array.from({ length: FLOATING_COUNT }, (_, i) => ({ x: seededRandom(i * 101) * 1080, y: seededRandom(i * 103) * 1920, size: 2 + seededRandom(i * 107) * 4, speed: 0.3 + seededRandom(i * 109) * 0.7, opacity: 0.2 + seededRandom(i * 113) * 0.4, })); // ============================================================================= // COMPONENTS // ============================================================================= const PixelBlock: React.FC<{ x: number; y: number; index: number; frame: number; fps: number; blockSize: number; gap: number; offsetX: number; offsetY: number; color: string; glowColor: string; }> = ({ x, y, index, frame, fps, blockSize, gap, offsetX, offsetY, color, glowColor }) => { const delay = index * 1.5; const startFrame = 15 + delay; const scale = spring({ frame: frame - startFrame, fps, config: { damping: 12, stiffness: 150, mass: 0.8 }, }); const finalX = offsetX + x * (blockSize + gap); const finalY = offsetY + y * (blockSize + gap); const initialX = finalX + (seededRandom(index * 53) - 0.5) * 400; const initialY = finalY - 300 - seededRandom(index * 59) * 200; const posX = interpolate(scale, [0, 1], [initialX, finalX]); const posY = interpolate(scale, [0, 1], [initialY, finalY]); const rotation = interpolate(scale, [0, 1], [seededRandom(index * 61) * 360, 0]); // Glow pulse const glowIntensity = interpolate( Math.sin(frame * 0.15 + index * 0.3), [-1, 1], [0.5, 1] ); return (
); }; const PixelNumber: React.FC<{ pixels: number[][]; frame: number; fps: number; offsetX: number; offsetY: number; startIndex: number; color: string; glowColor: string; }> = ({ pixels, frame, fps, offsetX, offsetY, startIndex, color, glowColor }) => { const blockSize = 38; const gap = 6; return ( <> {pixels.map(([row, col], i) => (