import type { TransitionPresentation, TransitionPresentationComponentProps, } from "@remotion/transitions"; import { AbsoluteFill, Easing, interpolate } from "remotion"; import { H, LOGO_KARELER, PIKSEL, W } from "../marka"; import { clamp01, hash } from "../yardimci"; /** * Piksel dalgası: yeni sahne, bir noktadan (çoğunlukla imlecin tıkladığı * yer) yayılan iri piksellerle açılır. Dalganın önünde logonun üç rengi * (mavi, şeftali, turuncu) yanıp söner — hero haritasındaki ısınan * piksellerin sahne ölçeğindeki hâli. Hücreler sitenin nokta oranını * (%74, rx %20) taşır; dalga geçince birleşip kesintisiz yüzeye döner. */ export type PikselDalgaProps = { origin?: { x: number; y: number }; /** Hücre kenarı (px) */ hucre?: number; /** Dalga önünün kalınlığı (px) */ bant?: number; /** Dalga önündeki piksellerin renkleri */ renkler?: string[]; /** Çıkan sahne hafifçe geri çekilsin (derinlik) */ geriCekil?: number; tohum?: number; }; const VARSAYILAN_RENKLER = LOGO_KARELER.map((k) => k.renk); const koseUzakligi = (o: { x: number; y: number }) => Math.max( Math.hypot(o.x, o.y), Math.hypot(W - o.x, o.y), Math.hypot(o.x, H - o.y), Math.hypot(W - o.x, H - o.y), ); /** * Dalga önünün yarıçapı. Gelen sahne kendi öğelerini dalgayla eş zamanlı * belirtmek isterse (ör. haritanın noktaları) aynı fonksiyonu kullanır. */ export const dalgaYaricapi = ( p: number, origin: { x: number; y: number } = { x: W / 2, y: H / 2 }, bant = 420, ) => interpolate(clamp01(p), [0, 1], [0, koseUzakligi(origin) + bant * 1.25], { easing: Easing.bezier(0.45, 0.05, 0.4, 1), }); const PikselDalgaSunum: React.FC< TransitionPresentationComponentProps > = ({ children, presentationProgress, presentationDirection, passedProps }) => { const { origin = { x: W / 2, y: H / 2 }, hucre = 64, bant = 420, renkler = VARSAYILAN_RENKLER, geriCekil = 0.05, tohum = 3, } = passedProps; const p = presentationProgress; if (presentationDirection === "exiting") { return ( {children} ); } const sutun = Math.ceil(W / hucre); const satir = Math.ceil(H / hucre); const r = dalgaYaricapi(p, origin, bant); let maske = ""; let renkli = ""; for (let j = 0; j < satir; j++) { for (let i = 0; i < sutun; i++) { const cx = i * hucre + hucre / 2; const cy = j * hucre + hucre / 2; const d = Math.hypot(cx - origin.x, cy - origin.y) + (hash(i, j, tohum) - 0.5) * bant * 0.55; const t = clamp01((r - d) / bant); if (t <= 0) continue; // Önde renkli piksel belirip söner… if (t < 0.72) { const c = Math.sin(Math.PI * (t / 0.72)); const boy = hucre * PIKSEL.nokta * c; const renk = renkler[Math.floor(hash(i, j, tohum + 9) * renkler.length)]; renkli += ``; } // …arkasından yeni sahne piksel piksel açılır const m = Easing.bezier(0.22, 1, 0.36, 1)(clamp01((t - 0.38) / 0.62)); if (m > 0) { const boy = hucre * (PIKSEL.nokta + 0.3 * m); const rx = hucre * PIKSEL.rx * (1 - m); maske += ``; } } } const maskeUrl = `url("data:image/svg+xml;utf8,${encodeURIComponent( `${maske}`, )}")`; return ( {children} ); }; export function pikselDalga( props: PikselDalgaProps = {}, ): TransitionPresentation { return { component: PikselDalgaSunum, props }; }