Sección Héroe 3D Animada con Video Impulsado por Scroll
De Wikiprompt, la enciclopedia libre de prompts
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ía: Prompts de coding
- Fuente: https://x.com/Kashberg_0/status/2067978971741147543
Discusión
0 comentarios