import { AbsoluteFill, interpolate, random, spring, useCurrentFrame, useVideoConfig } from "remotion"; import { COLORS, MUSIC_SYMBOLS } from "../lib/constants"; const FloatingNote: React.FC<{ symbol: string; startX: number; startY: number; size: number; delay: number; speed: number; drift: number; }> = ({ symbol, startX, startY, size, delay, speed, drift }) => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const progress = interpolate(frame - delay, [0, 180 / speed], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp", }); const y = interpolate(progress, [0, 1], [startY, startY - 600]); const x = startX + Math.sin(progress * Math.PI * 2 * drift) * 40; const opacity = interpolate( progress, [0, 0.1, 0.7, 1], [0, 0.6, 0.6, 0], ); const rotation = interpolate(progress, [0, 1], [0, drift * 30]); const scale = spring({ frame: Math.max(0, frame - delay), fps, config: { damping: 12, stiffness: 80, mass: 0.8 }, }); return (
{symbol}
); }; const Particle: React.FC<{ x: number; y: number; delay: number; size: number; }> = ({ x, y, delay, size }) => { const frame = useCurrentFrame(); const progress = interpolate(frame - delay, [0, 120], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp", }); const opacity = interpolate(progress, [0, 0.3, 0.7, 1], [0, 0.8, 0.8, 0]); const scale = interpolate(progress, [0, 0.5, 1], [0.5, 1.2, 0.5]); return (
); }; export const IntroScene: React.FC = () => { const frame = useCurrentFrame(); const { fps, width, height } = useVideoConfig(); // Title animation const titleSpring = spring({ frame: Math.max(0, frame - 40), fps, config: { damping: 14, stiffness: 60, mass: 1 }, }); const titleOpacity = interpolate(titleSpring, [0, 1], [0, 1]); const titleScale = interpolate(titleSpring, [0, 1], [0.3, 1]); const titleY = interpolate(titleSpring, [0, 1], [60, 0]); // Subtitle animation const subtitleSpring = spring({ frame: Math.max(0, frame - 70), fps, config: { damping: 14, stiffness: 50, mass: 1 }, }); const subtitleOpacity = interpolate(subtitleSpring, [0, 1], [0, 1]); const subtitleY = interpolate(subtitleSpring, [0, 1], [30, 0]); // Treble clef animation const clefSpring = spring({ frame: Math.max(0, frame - 20), fps, config: { damping: 18, stiffness: 40, mass: 1.2 }, }); const clefOpacity = interpolate(clefSpring, [0, 1], [0, 0.15]); const clefScale = interpolate(clefSpring, [0, 1], [0.5, 1]); const clefRotation = interpolate(clefSpring, [0, 1], [-15, 0]); // Scene fade out const fadeOut = interpolate(frame, [170, 210], [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp", }); // Generate floating notes const floatingNotes = Array.from({ length: 18 }, (_, i) => ({ symbol: MUSIC_SYMBOLS[i % MUSIC_SYMBOLS.length], startX: (width / 18) * i + random(`note-${i}`) * 80 - 40, startY: height + 50 + (i % 3) * 80, size: 28 + (i % 4) * 12, delay: i * 8, speed: 0.8 + (i % 3) * 0.3, drift: 0.5 + (i % 4) * 0.4, })); // Generate particles const particles = Array.from({ length: 30 }, (_, i) => ({ x: Math.sin(i * 2.39) * width * 0.45 + width / 2, y: Math.cos(i * 1.73) * height * 0.4 + height / 2, delay: i * 4, size: 2 + (i % 4) * 2, })); // Pulsing ring const ringProgress = interpolate(frame, [60, 180], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp", }); const ringScale = interpolate(ringProgress, [0, 1], [0.5, 2.5]); const ringOpacity = interpolate(ringProgress, [0, 0.3, 1], [0, 0.3, 0]); return ( {/* Large treble clef background */}
{"\uD834\uDD1E"}
{/* Pulsing ring */}
{/* Floating notes */} {floatingNotes.map((note, i) => ( ))} {/* Particles */} {particles.map((p, i) => ( ))} {/* Title */}
In Tono
{/* Subtitle */}
La tua guida musicale
{/* Bottom decorative line */}
); };