'use client' import { useEffect, useRef, useState } from 'react' import { useTranslations } from 'next-intl' import { motion, useScroll, useTransform, useMotionValueEvent, useReducedMotion, } from 'framer-motion' const TOTAL_FRAMES = 298 const FRAME_PATH = (n: number) => `/frames/ezgif-frame-${String(n).padStart(3, '0')}.jpg` export default function CloudRevealSection() { const t = useTranslations('hero') const prefersReducedMotion = useReducedMotion() const sectionRef = useRef(null) const canvasRef = useRef(null) const framesRef = useRef([]) const currentFrameRef = useRef(0) const [loaded, setLoaded] = useState(false) const [loadProgress, setLoadProgress] = useState(0) const { scrollYProgress } = useScroll({ target: sectionRef, offset: ['start start', 'end end'], }) // Tagline: ilk %15'te solar, aşağı kayar const taglineOpacity = useTransform(scrollYProgress, [0, 0.15], [1, 0]) const taglineY = useTransform(scrollYProgress, [0, 0.15], [0, 40]) // Progress bar: scroll'a göre genişler (0 → 100%) const progressScaleX = useTransform(scrollYProgress, [0, 1], [0, 1]) // Frame preload useEffect(() => { if (prefersReducedMotion) return const images: HTMLImageElement[] = new Array(TOTAL_FRAMES) let loadedCount = 0 let cancelled = false for (let i = 0; i < TOTAL_FRAMES; i++) { const img = new Image() img.src = FRAME_PATH(i + 1) img.onload = () => { if (cancelled) return loadedCount++ setLoadProgress(Math.round((loadedCount / TOTAL_FRAMES) * 100)) if (loadedCount === TOTAL_FRAMES) { framesRef.current = images setLoaded(true) drawFrame(0, images) } } images[i] = img } return () => { cancelled = true } }, [prefersReducedMotion]) function drawFrame(index: number, images?: HTMLImageElement[]) { const canvas = canvasRef.current if (!canvas) return const ctx = canvas.getContext('2d') if (!ctx) return const imgs = images || framesRef.current const img = imgs[index] if (!img || !img.complete || img.naturalWidth === 0) return ctx.drawImage(img, 0, 0, canvas.width, canvas.height) } useMotionValueEvent(scrollYProgress, 'change', (progress) => { if (!loaded) return const frameIndex = Math.min( Math.floor(progress * (TOTAL_FRAMES - 1)), TOTAL_FRAMES - 1 ) if (frameIndex !== currentFrameRef.current) { currentFrameRef.current = frameIndex drawFrame(frameIndex) } }) useEffect(() => { const canvas = canvasRef.current if (!canvas) return const resize = () => { canvas.width = window.innerWidth canvas.height = window.innerHeight drawFrame(currentFrameRef.current) } resize() window.addEventListener('resize', resize) return () => window.removeEventListener('resize', resize) }, [loaded]) if (prefersReducedMotion) { return (

Vesta Muğla

{t('tagline')}

{t('subtitle')}

) } return (
{/* Canvas */} {/* Gradient — alt kısım okunabilir olsun */}
{/* Loading */} {!loaded && (

{loadProgress}%

)} {/* Sol alt — tagline metni */}

Vesta Muğla

{t('tagline')}

{t('subtitle')}

{/* Sağ alt — scroll göstergesi */} {loaded && ( {t('scroll')} )} {/* Alt progress bar */}
) }