From 0ae16f2963ca98204ea6b00f403d1df38d619593 Mon Sep 17 00:00:00 2001 From: Mustafa Date: Thu, 30 Jul 2026 23:10:42 +0300 Subject: [PATCH] fix: RAF loop + scrollYProgress.on() for frame animation --- components/sections/CloudRevealSection.tsx | 51 ++++++++++++++-------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/components/sections/CloudRevealSection.tsx b/components/sections/CloudRevealSection.tsx index 87e9041..1b1914a 100644 --- a/components/sections/CloudRevealSection.tsx +++ b/components/sections/CloudRevealSection.tsx @@ -6,7 +6,6 @@ import { motion, useScroll, useTransform, - useMotionValueEvent, useReducedMotion, } from 'framer-motion' import UnitRevealOverlay from './UnitRevealOverlay' @@ -27,6 +26,7 @@ export default function CloudRevealSection() { const sectionRef = useRef(null) const canvasRef = useRef(null) const framesRef = useRef<(HTMLImageElement | null)[]>([]) + const scrollProgressRef = useRef(0) const [loaded, setLoaded] = useState(false) const [loadProgress, setLoadProgress] = useState(0) const [activeUnit, setActiveUnit] = useState<{ id: string; label: string; sub: string } | null>(null) @@ -72,6 +72,38 @@ export default function CloudRevealSection() { return () => window.removeEventListener('resize', resize) }, []) + // scrollYProgress → ref (RAF loop için) + useEffect(() => { + return scrollYProgress.on('change', (v) => { scrollProgressRef.current = v }) + }, [scrollYProgress]) + + // RAF loop: scroll progress + yüklü frame → canvas + useEffect(() => { + const canvas = canvasRef.current + if (!canvas) return + const ctx = canvas.getContext('2d') + if (!ctx) return + let rafId: number + const loop = () => { + const progress = scrollProgressRef.current + const targetIdx = Math.min( + Math.floor(progress * (TOTAL_FRAMES - 1)), + TOTAL_FRAMES - 1 + ) + // En yakın yüklü frame'i bul + for (let i = targetIdx; i >= 0; i--) { + const img = framesRef.current[i] + if (img && canvas.width > 0) { + ctx.drawImage(img, 0, 0, canvas.width, canvas.height) + break + } + } + rafId = requestAnimationFrame(loop) + } + rafId = requestAnimationFrame(loop) + return () => cancelAnimationFrame(rafId) + }, []) + // Frame preload useEffect(() => { if (prefersReducedMotion) return @@ -109,23 +141,6 @@ export default function CloudRevealSection() { return () => { cancelled = true } }, [prefersReducedMotion]) - // Scroll → canvas frame çiz - useMotionValueEvent(scrollYProgress, 'change', (progress) => { - const targetIdx = Math.min( - Math.floor(progress * (TOTAL_FRAMES - 1)), - TOTAL_FRAMES - 1 - ) - // Hedef frame yüklenmemişse geriye doğru ilk yüklü frame'i bul - let img: HTMLImageElement | null = null - for (let i = targetIdx; i >= 0; i--) { - if (framesRef.current[i]) { img = framesRef.current[i]; break } - } - const canvas = canvasRef.current - const ctx = canvas?.getContext('2d') - if (img && canvas && ctx && canvas.width > 0) { - ctx.drawImage(img, 0, 0, canvas.width, canvas.height) - } - }) // Scroll kilidi useEffect(() => {