Discusión

Sección Héroe 3D Animada con Video Impulsado por Scroll

De Wikiprompt, la enciclopedia libre de prompts

Kashberg
Contribuido porKashbergXFuente

19 jun 2026

Sección Héroe 3D Animada con Video Impulsado por Scroll true avance completo para construir una página de aterrizaje cinematográfica con video de fondo, efectos de desplazamiento, desenfoque y animaciones fluidas usando React, Tailwind y Framer Motion.

Contenido del PromptGuardar

🌐
import { useEffect, useRef, useState } from 'react'; import { motion, useScroll, useTransform, useSpring } from 'motion/react'; import Lenis from 'lenis'; // ========== LiquidVideoCanvas Component ========== const LiquidVideoCanvas = () => { const videoRef = useRef<HTMLVideoElement>(null); const [isReady, setIsReady] = useState(false); const isSeekingRef = useRef(false); const nextSeekTimeRef = useRef<number | null>(null); // LERP smoothing for scroll-driven video const targetTimeRef = useRef(0); const currentTimeRef = useRef(0); const rafRef = useRef<number>(0); // Entrance animation state const [entrance, setEntrance] = useState({ scale: 1.12, opacity: 0 }); // Scroll progress tracking const { scrollYProgress } = useScroll(); // Progressive blur values const blur = useTransform( scrollYProgress, [0, 0.5, 1], [0, 5, 55] ); const springBlur = useSpring(blur, { stiffness: 100, damping: 30 }); // Apply blur via ref const blurRef = useRef<HTMLDivElement>(null); useEffect(() => { const unsubscribe = springBlur.on('change', (value) => { if (blurRef.current) { blurRef.current.style.backdropFilter = `blur(${value}px)`; } }); return () => unsubscribe(); }, [springBlur]); // Video frame seeking with LERP useEffect(() => { const video = videoRef.current; if (!video) return; const handleSeeked = () => { isSeekingRef.current = false; if (nextSeekTimeRef.current !== null) { const next = nextSeekTimeRef.current; nextSeekTimeRef.current = null; if (!video.seeking) { isSeekingRef.current = true; video.currentTime = next; } } }; const handleSeeking = () => { isSeekingRef.current = true; }; video.addEventListener('seeked', handleSeeked); video.addEventListener('seeking', handleSeeking); const animate = () => { const scrollProgress = scrollYProgress.get(); targetTimeRef.current = scrollProgress * (video.duration || 0); currentTimeRef.current += (targetTimeRef.current - currentTimeRef.current) * 0.12; if (!isSeekingRef.current && !video.seeking) { isSeekingRef.current = true; video.currentTime = currentTimeRef.current; } else { nextSeekTimeRef.current = currentTimeRef.current; } rafRef.current = requestAnimationFrame(animate); }; rafRef.current = requestAnimationFrame(animate); return () => { cancelAnimationFrame(rafRef.current); video.removeEventListener('seeked', handleSeeked); video.removeEventListener('seeking', handleSeeking); }; }, [scrollYProgress]); // Entrance animation on ready useEffect(() => { const video = videoRef.current; if (!video) return; const handleReady = () => { if (video.readyState >= 3) { setEntrance({ scale: 1, opacity: 1 }); } }; const timeout = setTimeout(() => { setEntrance({ scale: 1, opacity: 1 }); }, 3500); video.addEventListener('loadeddata', handleReady); video.addEventListener('canplay', handleReady); return () => { clearTimeout(timeout); video.removeEventListener('loadeddata', handleReady); video.removeEventListener('canplay', handleReady); }; }, []); return ( <div className="fixed inset-0 z-[1] bg-black"> <motion.div initial={{ scale: 1.12, opacity: 0 }} animate={entrance} transition={{ duration: 1.4, ease: [0.16, 1, 0.3, 1] }} className="w-full h-full" > <video ref={videoRef} className="w-full h-full object-cover" loop muted playsInline preload="auto" src="https://t.co/cvkGVS5C0E" /> </motion.div> </div> ); }; // ========== Text Scramble Effect ========== const ScrambleText = ({ text, className }: { text: string; className?: string }) => { const [displayText, setDisplayText] = useState(text); const frameRef = useRef(0); const intervalRef = useRef<ReturnType<typeof setInterval>>(); useEffect(() => { const chars = '!<>-_\\/[]{}-=+*^?#________'; const original = text; let iteration = 0; intervalRef.current = setInterval(() => { frameRef.current++; const result = original .split('') .map((char, index) => { if (char === ' ') return ' '; if (index < iteration) return original[index]; return chars[Math.floor(Math.random() * chars.length)]; }) .join(''); setDisplayText(result); if (iteration >= original.length) { clearInterval(intervalRef.current); } iteration += 1 / 3; }, 30); return () => clearInterval(intervalRef.current); }, [text]); return <span className={className}>{displayText}</span>; }; // ========== Main App Component ========== const App = () => { const mainRef = useRef<HTMLDivElement>(null); // Lenis smooth scroll setup useEffect(() => { const isDesktop = window.matchMedia('(min-width: 768px)').matches; if (!isDesktop) return; const lenis = new Lenis({ duration: 1.2, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), smoothWheel: true, }); const raf = (time: number) => { lenis.raf(time); requestAnimationFrame(raf); }; requestAnimationFrame(raf); return () => { lenis.destroy(); }; }, []); // Scroll-driven content animations const { scrollYProgress } = useScroll(); const contentOpacity = useTransform(scrollYProgress, [0, 0.3], [1, 0]); const contentY = useTransform(scrollYProgress, [0, 0.3], [0, -100]); return ( <div className="relative overflow-x-hidden bg-black text-white font-mono"> {/* Video Background */} <LiquidVideoCanvas /> {/* Progressive Blur Layer */} <div ref={useRef<HTMLDivElement>(null)} className="fixed bottom-0 left-0 right-0 z-30 h-full pointer-events-none" style={{ backdropFilter: 'blur(0px)' }} /> {/* Header */} <header className="fixed top-0 left-0 right-0 z-50 flex items-center justify-between px-6 py-4 md:px-12 md:py-6"> <div className="text-lg font-bold tracking-widest">SYNAPSE<span className="text-white/60">X</span></div> <nav className="hidden md:flex items-center gap-8 text-sm"> <a href="#about" className="hover:text-white/60 transition-colors">ABOUT</a> <a href="#tech" className="hover:text-white/60 transition-colors">TECH</a> <a href="#contact" className="hover:text-white/60 transition-colors">CONTACT</a> </nav> <div className="flex items-center gap-4"> <i className="bi bi-apple text-xl" /> <button className="border border-white/30 px-4 py-2 text-sm hover:bg-white hover:text-black transition-colors"> GET STARTED </button> </div> </header> {/* Main Content */} <motion.main ref={mainRef} style={{ opacity: contentOpacity, y: contentY }} className="relative z-10 min-h-screen flex flex-col items-center justify-center px-6 text-center" > <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.5, duration: 0.8 }} className="mb-6 text-sm tracking-[0.3em] text-white/60" > NEXT-GENERATION NEURAL INTERFACE </motion.div> <h1 className="text-5xl md:text-8xl font-bold leading-tight mb-8"> <ScrambleText text="SYNAPSE" className="block" /> <ScrambleText text="EVOLUTION" className="block text-white/80" /> </h1> <motion.p initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 1.2, duration: 0.8 }} className="max-w-2xl text-base md:text-lg text-white/70 mb-12" > Experience the future of human-computer interaction. Our neural bridge technology connects your mind directly to the digital realm with unprecedented speed and clarity. </motion.p> <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 1.6, duration: 0.8 }} className="flex flex-col md:flex-row gap-4" > <button className="bg-white text-black px-8 py-4 text-sm font-bold hover:bg-white/80 transition-colors"> EXPLORE THE FUTURE </button> <button className="border border-white/30 px-8 py-4 text-sm hover:bg-white/10 transition-colors"> WATCH DEMO </button> </motion.div> <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 2, duration: 1 }} className="absolute bottom-8 left-1/2 -translate-x-1/2 text-white/40 text-sm" > SCROLL TO EXPLORE </motion.div> </motion.main> {/* Additional Scroll Content */} <section className="relative z-10 min-h-screen flex items-center justify-center px-6"> <div className="max-w-4xl text-center"> <h2 className="text-4xl md:text-6xl font-bold mb-8"> <ScrambleText text="BEYOND LIMITS" /> </h2> <p className="text-lg text-white/70 leading-relaxed"> SynapseX represents a paradigm shift in how we interact with technology. Our proprietary neural interface technology achieves 99.9% signal accuracy with zero latency, enabling seamless thought-to-action conversion. </p> </div> </section> </div> ); }; export default App;

Iniciá sesión para ver el prompt completo

Continuar con:

Al iniciar sesión, aceptás nuestros Términos de uso y Política de privacidad

Uso

Este prompt está diseñado para usarse con coding. Copiá el contenido de arriba y pegalo en tu herramienta de IA preferida.

Para mejores resultados, personalizá los marcadores (indicados con corchetes o mayúsculas) con tus requisitos específicos.

Referencias

Categorías:coding| twitter| react| vite

Discusión