import React from 'react'; import { useCurrentFrame, useVideoConfig, interpolate, AbsoluteFill, Img, } from 'remotion'; // ============================================================================= // COMPOSITION CONFIG // ============================================================================= export const compositionConfig = { id: 'CoverScrollingGrid', durationInSeconds: 6, fps: 30, width: 2160, height: 2160, }; // ============================================================================= // STYLE CONSTANTS // ============================================================================= const COLORS = { primary: '#7C3AED', secondary: '#A78BFA', accent: '#C084FC', background: '#110A1F', text: '#FFFFFF', } as const; // ============================================================================= // GRID CONFIGURATION // ============================================================================= const TILE_SIZE = 940; const GAP = 24; const TILE_STEP = TILE_SIZE + GAP; const COLUMNS = 2; const TOTAL_GRID_WIDTH = COLUMNS * TILE_SIZE + (COLUMNS - 1) * GAP; const BORDER_RADIUS = 32; // Images — 4 per column const ALL_IMAGES = [ 'https://lumenor.ai/cdn-cgi/imagedelivery/F5KOmplEz0rStV2qDKhYag/ac7a7b98-88f1-4771-c8db-7db6aeed1700/tn', 'https://lumenor.ai/cdn-cgi/imagedelivery/F5KOmplEz0rStV2qDKhYag/9c34a520-4225-4798-e5c0-b8ef65f96800/tn', 'https://lumenor.ai/cdn-cgi/imagedelivery/F5KOmplEz0rStV2qDKhYag/578e7eeb-0766-40f8-498a-933f64158e00/tn', 'https://piktochart.com/wp-content/uploads/2023/11/paris-garbage-viral-ai-images.jpg', 'https://piktochart.com/wp-content/uploads/2023/11/jos-avery-viral-ai-images.jpg', 'https://lumenor.ai/cdn-cgi/imagedelivery/F5KOmplEz0rStV2qDKhYag/ad0a4b43-aa05-4c78-8a4f-e5f02638b100/tn', 'https://lumenor.ai/cdn-cgi/imagedelivery/F5KOmplEz0rStV2qDKhYag/d50f390c-a88b-4391-f81f-cf01329dfd00/tn', 'https://lumenor.ai/cdn-cgi/imagedelivery/F5KOmplEz0rStV2qDKhYag/ab2f27ea-ceaa-434d-bb34-6afd2ff51800/tn', ]; const COLUMN_IMAGES = [ [ALL_IMAGES[0], ALL_IMAGES[1], ALL_IMAGES[2], ALL_IMAGES[3]], [ALL_IMAGES[4], ALL_IMAGES[5], ALL_IMAGES[6], ALL_IMAGES[7]], ]; const TILES_PER_COL = COLUMN_IMAGES[0].length; const SET_HEIGHT = TILES_PER_COL * TILE_STEP; // Scroll speeds per column (px/sec) — varied for depth const SCROLL_SPEEDS = [340, 480]; // ============================================================================= // PRE-GENERATED DATA // ============================================================================= const seededRandom = (seed: number): number => { const x = Math.sin(seed * 9999) * 10000; return x - Math.floor(x); }; // ============================================================================= // SUB-COMPONENTS // ============================================================================= const ImageTile: React.FC<{ src: string; shimmerDelay: number; time: number; }> = ({ src, shimmerDelay, time }) => { const shimmerCycle = ((time + shimmerDelay) % 5) / 5; const shimmerX = interpolate(shimmerCycle, [0, 0.25, 0.65, 1], [-150, -150, 250, 250]); return (
{/* Shimmer overlay sweep */}
{/* Inner border */}
); }; const ScrollColumn: React.FC<{ colIndex: number; time: number; height: number; }> = ({ colIndex, time, height }) => { const speed = SCROLL_SPEEDS[colIndex]; const scrollY = (time * speed) % SET_HEIGHT; const images = COLUMN_IMAGES[colIndex]; // 3 copies for seamless loop const repeatedImages = [...images, ...images, ...images]; return (
{repeatedImages.map((src, i) => ( ))}
); }; // ============================================================================= // MAIN COMPONENT // ============================================================================= const CoverScrollingGrid: React.FC = () => { const frame = useCurrentFrame(); const { fps, width, height } = useVideoConfig(); const time = frame / fps; const gridLeft = (width - TOTAL_GRID_WIDTH) / 2; const pulseGlow = interpolate( Math.sin(time * 1.5), [-1, 1], [0.08, 0.22] ); return ( {/* Ambient radial glow */}
{/* Grid container */}
{Array.from({ length: COLUMNS }, (_, colIndex) => ( ))}
{/* Top fade */}
{/* Bottom fade */}
{/* Vignette */}
); }; export default CoverScrollingGrid;