diff --git a/components/sections/CloudRevealSection.tsx b/components/sections/CloudRevealSection.tsx index 7d972cf..476b49c 100644 --- a/components/sections/CloudRevealSection.tsx +++ b/components/sections/CloudRevealSection.tsx @@ -11,31 +11,24 @@ import { } from 'framer-motion' import UnitRevealOverlay from './UnitRevealOverlay' -const CDN = 'https://media.ayris.tech/t' -const HERO_VIDEO = `${CDN}/vesta/hero/hero.mp4` -// Scroll aralığına göre opacity döndüren helper -function usePhaseOpacity( - scrollYProgress: ReturnType['scrollYProgress'], - inStart: number, - inEnd: number, - outStart: number, - outEnd: number -) { - return useTransform( - scrollYProgress, - [inStart, inEnd, outStart, outEnd], - [0, 1, 1, 0] - ) +const TOTAL_FRAMES = 299 +const OPENINARY_BASE = process.env.NEXT_PUBLIC_OPENINARY_URL ?? 'https://media.ayris.tech' + +function frameSrc(i: number) { + const path = `vesta/frames/ezgif-frame-${String(i + 1).padStart(3, '0')}.jpg` + return `${OPENINARY_BASE}/t/w_1920,f_webp,q_65/${path}` } + export default function CloudRevealSection() { const t = useTranslations('hero') const prefersReducedMotion = useReducedMotion() const sectionRef = useRef(null) const canvasRef = useRef(null) - const videoRef = useRef(null) + const framesRef = useRef<(HTMLImageElement | null)[]>([]) const [loaded, setLoaded] = useState(false) + const [loadProgress, setLoadProgress] = useState(0) const [activeUnit, setActiveUnit] = useState<{ id: string; label: string; sub: string } | null>(null) const { scrollYProgress } = useScroll({ @@ -66,46 +59,68 @@ export default function CloudRevealSection() { const phase4Opacity = useTransform(scrollYProgress, [0.78, 0.85, 0.95, 1], [0, 1, 1, 0]) const phase4Y = useTransform(scrollYProgress, [0.78, 0.85], [30, 0]) - // Video → canvas kurulumu + // Canvas boyutu + useEffect(() => { + const canvas = canvasRef.current + if (!canvas) return + const resize = () => { + canvas.width = window.innerWidth + canvas.height = window.innerHeight + } + resize() + window.addEventListener('resize', resize) + return () => window.removeEventListener('resize', resize) + }, []) + + // Frame preload useEffect(() => { if (prefersReducedMotion) return - const video = videoRef.current - const canvas = canvasRef.current - if (!video || !canvas) return - const ctx = canvas.getContext('2d') - if (!ctx) return - const draw = () => { - if (canvas.width === 0) { - canvas.width = window.innerWidth - canvas.height = window.innerHeight + framesRef.current = new Array(TOTAL_FRAMES).fill(null) + let loadedCount = 0 + let cancelled = false + + for (let i = 0; i < TOTAL_FRAMES; i++) { + const img = new Image() + img.src = frameSrc(i) + img.onload = () => { + if (cancelled) return + framesRef.current[i] = img + loadedCount++ + setLoadProgress(Math.round((loadedCount / TOTAL_FRAMES) * 100)) + + // İlk frame yüklenince ekranı aç + if (i === 0 && !loaded) { + const canvas = canvasRef.current + const ctx = canvas?.getContext('2d') + if (canvas && ctx) { + ctx.drawImage(img, 0, 0, canvas.width, canvas.height) + } + setLoaded(true) + } } - if (video.readyState >= 2) { - ctx.drawImage(video, 0, 0, canvas.width, canvas.height) + img.onerror = () => { + if (cancelled) return + loadedCount++ + if (loadedCount === TOTAL_FRAMES) setLoadProgress(100) } } - const onReady = () => { setLoaded(true); draw() } - - video.addEventListener('seeked', draw) - video.addEventListener('loadeddata', onReady) - video.addEventListener('canplay', onReady) - - // Yüklemeyi tetikle - video.load() - - return () => { - video.removeEventListener('seeked', draw) - video.removeEventListener('loadeddata', onReady) - video.removeEventListener('canplay', onReady) - } + return () => { cancelled = true } }, [prefersReducedMotion]) - // Scroll → video currentTime + // Scroll → canvas frame çiz useMotionValueEvent(scrollYProgress, 'change', (progress) => { - const video = videoRef.current - if (!video || !video.duration) return - video.currentTime = progress * video.duration + const frameIdx = Math.min( + Math.floor(progress * (TOTAL_FRAMES - 1)), + TOTAL_FRAMES - 1 + ) + const img = framesRef.current[frameIdx] + const canvas = canvasRef.current + const ctx = canvas?.getContext('2d') + if (img && canvas && ctx) { + ctx.drawImage(img, 0, 0, canvas.width, canvas.height) + } }) // Scroll kilidi @@ -122,19 +137,6 @@ export default function CloudRevealSection() { return () => window.removeEventListener('scroll', lockScroll) }, []) - // Canvas boyutu - useEffect(() => { - const canvas = canvasRef.current - if (!canvas) return - const resize = () => { - canvas.width = window.innerWidth - canvas.height = window.innerHeight - } - resize() - window.addEventListener('resize', resize) - return () => window.removeEventListener('resize', resize) - }, []) - if (prefersReducedMotion) { return (
@@ -153,16 +155,6 @@ export default function CloudRevealSection() {
- {/* Video kaynağı — görünmez ama yüklenebilir */} -