"use client"; import { useEffect, useRef } from "react"; import { motion } from "framer-motion"; import { gsap } from "@/lib/gsap"; /** * Botanisch präzise verschnörkelte Ranken: * Das Wachstum ist exakt auf den gesamten Scrollverlauf abgestimmt (kein zu schnelles Wachsen). * Die Ranken entfalten sich genau synchron zur Scroll-Position und erreichen den * untersten Rand erst, wenn man auch ganz unten angekommen ist. */ // Botanisch geformtes Blatt mit spitzer Silhouetten-Form, Blattader & dezentem Hover-Wiegeln function Leaf({ x, y, rotate = 0, scale = 1, className = "", }: { x: number; y: number; rotate?: number; scale?: number; className?: string; }) { return ( {/* Äußere Blattsilhouette – edles Gelb-Grün / Smaragd */} {/* Feine Blattader */} ); } // Offene Spiral-Tendril (Ranken-Kringel) function Tendril({ d, className = "" }: { d: string; className?: string }) { return ( ); } // Ranke 1 (Links-Oben nach Mitte-Rechts - Hero Bereich) const STEM_1 = "M -40 20 C 120 70, 240 160, 320 300 C 400 440, 280 600, 420 740 C 520 860, 680 940, 820 1060"; const TENDRILS_1 = [ "M 240 160 C 275 135, 295 160, 275 185 C 255 195, 240 178, 252 165", "M 420 740 C 465 710, 485 745, 460 770 C 435 785, 415 755, 428 738", ]; const LEAF_NODES_1 = [ { x: 120, y: 70, rotate: -25, scale: 0.9 }, { x: 240, y: 160, rotate: 42, scale: 1.1 }, { x: 320, y: 300, rotate: -45, scale: 1.0 }, { x: 400, y: 440, rotate: 32, scale: 0.95 }, { x: 420, y: 740, rotate: -35, scale: 1.05 }, { x: 680, y: 940, rotate: 50, scale: 0.9 }, ]; // Ranke 2 (Rechts-Oben edel schwebend - Mittlerer Bereich) const STEM_2 = "M 920 30 C 760 150, 620 310, 710 490 C 800 680, 620 830, 740 1020 C 860 1180, 720 1340, 840 1500"; const TENDRILS_2 = [ "M 710 490 C 665 460, 640 495, 665 520 C 690 535, 710 505, 695 488", "M 740 1020 C 695 990, 670 1025, 695 1050 C 720 1065, 740 1035, 725 1018", ]; const LEAF_NODES_2 = [ { x: 760, y: 150, rotate: 155, scale: 1.0 }, { x: 710, y: 490, rotate: -130, scale: 1.15 }, { x: 620, y: 830, rotate: 140, scale: 0.9 }, { x: 740, y: 1020, rotate: -150, scale: 1.05 }, { x: 840, y: 1500, rotate: 135, scale: 1.1 }, ]; // Ranke 3 (Untere Ranke Links – Wächst erst in der 2. Seitenhälfte bis in den Footer) const STEM_3 = "M -30 50 C 210 180, 440 240, 520 430 C 600 620, 420 810, 610 1000 C 780 1170, 690 1340, 840 1550 C 920 1720, 780 1880, 910 2050"; const TENDRILS_3 = [ "M 520 430 C 565 400, 590 435, 565 460 C 540 475, 518 445, 532 428", "M 610 1000 C 655 970, 680 1005, 655 1030 C 630 1045, 608 1015, 622 998", "M 840 1550 C 885 1520, 910 1555, 885 1580 C 860 1595, 838 1565, 852 1548", ]; const LEAF_NODES_3 = [ { x: 210, y: 180, rotate: -30, scale: 1.05 }, { x: 440, y: 240, rotate: 35, scale: 0.9 }, { x: 520, y: 430, rotate: -40, scale: 1.1 }, { x: 420, y: 810, rotate: 45, scale: 1.0 }, { x: 610, y: 1000, rotate: -35, scale: 1.15 }, { x: 780, y: 1170, rotate: 30, scale: 0.95 }, { x: 840, y: 1550, rotate: -25, scale: 1.1 }, { x: 880, y: 1860, rotate: 40, scale: 0.95 }, ]; // Ranke 4 (Untere Ranke Rechts – Wächst erst in der 2. Seitenhälfte bis in den Footer) const STEM_4 = "M 900 40 C 740 220, 620 400, 700 600 C 780 800, 600 1000, 720 1220 C 840 1440, 680 1680, 780 1920 C 880 2080, 750 2200, 850 2320"; const TENDRILS_4 = [ "M 700 600 C 655 570, 630 605, 655 630 C 680 645, 700 615, 685 598", "M 720 1220 C 675 1190, 650 1225, 675 1250 C 700 1265, 720 1235, 705 1218", ]; const LEAF_NODES_4 = [ { x: 740, y: 220, rotate: 145, scale: 1.0 }, { x: 700, y: 600, rotate: 125, scale: 0.95 }, { x: 600, y: 1000, rotate: -140, scale: 1.1 }, { x: 720, y: 1220, rotate: 135, scale: 1.05 }, { x: 780, y: 1920, rotate: -130, scale: 0.95 }, ]; export default function ScrollFlourishes() { const rootRef = useRef(null); useEffect(() => { const root = rootRef.current; if (!root) return; const mm = gsap.matchMedia(); mm.add("(prefers-reduced-motion: no-preference)", () => { // 1. Dasharray & Offset für alle Linienpfade vorbereiten const strokePaths = root.querySelectorAll( ".vine-stem, .vine-tendril", ); strokePaths.forEach((p) => { const len = p.getTotalLength(); p.style.strokeDasharray = `${len}`; p.style.strokeDashoffset = `${len}`; }); const leaves = root.querySelectorAll(".vine-leaf"); gsap.set(leaves, { opacity: 0, scale: 0, transformOrigin: "0px 0px" }); // 2. Perfekt getaktete ScrollTrigger Timeline (Spannweite von 0 bis 1.0 des gesamten Dokument-Scrolls) const tl = gsap.timeline({ scrollTrigger: { trigger: document.body, start: "top top", end: "bottom bottom", scrub: 0.7, }, }); // Ranke 1 (Hero): Wächst im oberen Drittel (0.0 bis 0.38) tl.to( root.querySelectorAll(".vine-stem-1"), { strokeDashoffset: 0, ease: "none", duration: 0.38 }, 0, ); tl.to( root.querySelectorAll(".vine-tendril-1"), { strokeDashoffset: 0, ease: "none", duration: 0.08 }, 0.25, ); // Ranke 2 (Mitte-Rechts): Wächst im mittleren Bereich (0.22 bis 0.68) tl.to( root.querySelectorAll(".vine-stem-2"), { strokeDashoffset: 0, ease: "none", duration: 0.46 }, 0.22, ); tl.to( root.querySelectorAll(".vine-tendril-2"), { strokeDashoffset: 0, ease: "none", duration: 0.08 }, 0.48, ); // Ranke 3 (Untere Ranke Links): Wächst in der 2. Hälfte bis ganz nach unten (0.45 bis 1.0) tl.to( root.querySelectorAll(".vine-stem-3"), { strokeDashoffset: 0, ease: "none", duration: 0.55 }, 0.45, ); tl.to( root.querySelectorAll(".vine-tendril-3"), { strokeDashoffset: 0, ease: "none", duration: 0.08 }, 0.72, ); // Ranke 4 (Untere Ranke Rechts): Wächst in der 2. Hälfte bis ganz nach unten (0.50 bis 1.0) tl.to( root.querySelectorAll(".vine-stem-4"), { strokeDashoffset: 0, ease: "none", duration: 0.5 }, 0.5, ); tl.to( root.querySelectorAll(".vine-tendril-4"), { strokeDashoffset: 0, ease: "none", duration: 0.08 }, 0.78, ); // Blätter entfalten sich organisch zur jeweiligen Wachstumszeit tl.to( leaves, { opacity: 1, scale: 1, ease: "back.out(1.5)", duration: 0.1, stagger: 0.02, }, 0.1, ); // Subtiler, ruhiger Parallax-Versatz (Ohne hektische Maus-Swayings) tl.to( ".vine-container-1", { yPercent: 6, scale: 1.06, ease: "none", duration: 1 }, 0, ); tl.to( ".vine-container-2", { yPercent: 8, scale: 0.95, ease: "none", duration: 1 }, 0, ); tl.to( ".vine-container-3", { yPercent: -4, scale: 1.05, ease: "none", duration: 1 }, 0, ); tl.to( ".vine-container-4", { yPercent: 5, scale: 1.04, ease: "none", duration: 1 }, 0, ); }); return () => mm.revert(); }, []); return (
{/* Ranke 1: Links-Oben nach Mitte-Rechts (Hero) */}
{TENDRILS_1.map((d, i) => ( ))} {LEAF_NODES_1.map((node, i) => ( ))}
{/* Ranke 2: Rechts-Oben (Mittlerer Bereich) */}
{TENDRILS_2.map((d, i) => ( ))} {LEAF_NODES_2.map((node, i) => ( ))}
{/* Ranke 3: Untere Ranke Links – Wächst erst in der 2. Seitenhälfte bis in den Footer */}
{TENDRILS_3.map((d, i) => ( ))} {LEAF_NODES_3.map((node, i) => ( ))}
{/* Ranke 4: Untere Ranke Rechts – Wächst erst in der 2. Seitenhälfte bis in den Footer */}
{TENDRILS_4.map((d, i) => ( ))} {LEAF_NODES_4.map((node, i) => ( ))}
); }