"use client"; import { useEffect, useRef, useState } from "react"; import { motion, useMotionValue, useScroll, useSpring, useTransform, } from "framer-motion"; import { ArrowDown } from "lucide-react"; import { gsap } from "@/lib/gsap"; export default function Hero() { const sectionRef = useRef(null); const { scrollY } = useScroll(); // Scroll-Transformationen (Reversibel) const ringY = useTransform(scrollY, [0, 1000], [0, 180]); const ringScale = useTransform(scrollY, [0, 1000], [1, 1.18]); const ringOpacity = useTransform(scrollY, [0, 400, 1000, 1500], [1, 1, 0.5, 0]); const ringRotate = useTransform(scrollY, [0, 1000], [0, 10]); // Interaktive Cursor-Bewegung (Subtile Spring-Physik für elegantes Hovering) const rawMouseX = useMotionValue(0); const rawMouseY = useMotionValue(0); const smoothMouseX = useSpring(rawMouseX, { stiffness: 60, damping: 28 }); const smoothMouseY = useSpring(rawMouseY, { stiffness: 60, damping: 28 }); // Subtile magnetische Linienverschiebung const magnetX = useTransform(smoothMouseX, [-0.5, 0.5], [-10, 10]); const magnetY = useTransform(smoothMouseY, [-0.5, 0.5], [-8, 8]); // SVG-Glow-Position (in viewBox 1550 x 950 Koordinaten) const [svgGlow, setSvgGlow] = useState({ x: 775, y: 475 }); const handleMouseMove = (e: React.MouseEvent) => { const rect = sectionRef.current?.getBoundingClientRect(); if (!rect) return; // Normalisierte Mauskoordinaten (-0.5 bis 0.5) const normX = (e.clientX - rect.left) / rect.width - 0.5; const normY = (e.clientY - rect.top) / rect.height - 0.5; rawMouseX.set(normX); rawMouseY.set(normY); // Umrechnung auf SVG-ViewBox-Koordinaten für das sanfte Aufleuchten const svgX = Math.round(((e.clientX - rect.left) / rect.width) * 1550); const svgY = Math.round(((e.clientY - rect.top) / rect.height) * 950); setSvgGlow({ x: svgX, y: svgY }); }; // Text-Intro startet erst, wenn der Preloader das "app:reveal"-Event feuert useEffect(() => { // Der Hero ist das LCP-Element. Auf Mobilgeräten bleibt er deshalb sofort // sichtbar, statt seine endgültige Darstellung durch eine Timeline zu verzögern. if (window.matchMedia("(max-width: 767px)").matches) return; let ctx: gsap.Context | undefined; let fallback: ReturnType | undefined; const start = () => { if (ctx) return; ctx = gsap.context(() => { gsap.fromTo( ".hero-el", { y: 34, opacity: 0 }, { y: 0, opacity: 1, duration: 1, stagger: 0.1, ease: "power3.out", }, ); }, sectionRef); }; const mm = gsap.matchMedia(); mm.add("(prefers-reduced-motion: no-preference)", () => { window.addEventListener("app:reveal", start, { once: true }); // Beim gecachten bzw. mobilen Preloader ist die Seite schon sichtbar, // bevor dieser Effect registriert wird. Dann sofort animieren statt auf // den Fallback-Timer zu warten. if (document.documentElement.dataset.preloader !== "active") { start(); } else { fallback = setTimeout(start, 1200); } }); return () => { mm.revert(); window.removeEventListener("app:reveal", start); if (fallback) clearTimeout(fallback); ctx?.revert(); }; }, []); return (
{/* Weicher Spot in der Mitte: Fadet am Rand und unten zu 100% transparent in den Seitenhintergrund aus */}
{/* Multischichtiges Ring-Design: Kreise fließen flüssig über die Sektionsgrenze nach unten */} {/* Subtiler radialer Glow-Verlauf unter dem Cursor */} {/* 1. Basis-Ellipsen mit dezentem Ruhe-Opacity */} {/* Dynamisch kreuzende Orbit-Bögen – reichen flüssig bis in die nächste Sektion */} {/* Feine Horizon-Linie hinter den Buttons */} {/* 2. Subtile Aufleuchten-Ebene unter dem Cursor */}

Kostenloser Zufallsgenerator für schnelle Entscheidungen

Lass den Zufall entscheiden – mit Münze, Glücksrad, Würfel & mehr für alle, die sich mal wieder nicht entscheiden können.

Jetzt entscheiden Mehr erfahren

7 Tools · Kostenlos · Ohne Anmeldung

{/* Scroll-Hinweis */} Scroll
); }