Bu sitede kaç tane WebGL Canvas var? Bir. Hero'daki portre, skill alanı, proje önizlemeleri, arka plan ve toz — hepsi layout seviyesinde bir kez mount edilen tek bir R3F Canvas'ın içinde yaşıyor. Bu yazı o kararın mimarisini anlatıyor.
Neden tek Canvas?
Bölüm başına Canvas açmak ilk bakışta temiz görünüyor: her bileşen kendi sahnesini yönetir. Pratikte her Canvas ayrı bir WebGL context'i demek — ayrı bellek, ayrı derlenen shader'lar, mobilde context limiti ve bölüm geçişlerinde beyaz flaş. Tek kalıcı Canvas'ta sahne hiç ölmüyor; bölümler sadece sahnenin durumunu değiştiriyor.
Scroll tek kaynaktan akar
Zincir kısa ve tek yönlü: Lenis scroll'u yumuşatır, ScrollTrigger Lenis'e senkronlanır, her şey bu ikisinden beslenir.
lenis.on("scroll", ScrollTrigger.update);
gsap.ticker.add((time) => lenis.raf(time * 1000));Hiçbir bileşen native scroll event dinlemiyor. Scroll ilerlemesi normalize edilip (0..1) paylaşılan bir state'e yazılıyor; canvas tarafı her frame oradan okuyor. DOM ve WebGL aynı sayıya baktığı için senkron kayması yok.
Kamera durakları veri, bileşen değil
Kameranın nereye gideceği hiçbir bileşende yazmıyor. choreography.ts içinde bir durak listesi var:
export const cameraStops: CameraStop[] = [
{ at: 0.0, position: [0, 0, 6], accent: "#58a6ff" }, // hero
{ at: 0.2, position: [0.7, -2.6, 6.5], accent: "#7c6cff" }, // about
// ...
];sampleChoreography(progress) iki durak arasında yumuşak interpolasyon yapıyor; kamera rig'i sadece bu örnekleyiciyi çağırıyor. Yeni bölüm eklemek = listeye durak eklemek. Sampler uzunluktan bağımsız, kod değişmiyor.
Scroll pencereleri
Her efektin bir "penceresi" var: portre decode'u 0.10–0.19 arasında, skill alanı kendi aralığında yaşıyor. Pencereler de aynı config dosyasında. Efekt bileşeni smoothstep(start, end, progress) ile kendi yoğunluğunu hesaplıyor — bölümler birbirinden habersiz, ama hepsi aynı skalada dans ediyor.
Öğrenilenler
- Koreografi veriyse prova ucuz: durakları ayarlamak kod değil config değişikliği; deneme-yanılma turu saniyeler sürüyor.
- R3F tuzağı — uniform'lar memo objesinden güncellenmez: texture ve değerler daima
materialRef.current.uniformsüzerinden bağlanmalı. Bu dersi üç kez aldım. useFrameiçinde allocation yasak: vektörler ve renkler dışarıda bir kez alloc edilip her frame yeniden kullanılıyor; GC duraksaması scroll akıcılığının bir numaralı düşmanı.