// Camera: a câmera de mesa sobre o diorama. Chaves [[quadro, zoom, x, y]] (absolutas) e uma deriva de // ±10 px. Ela NÃO move a cena inteira: cada camada lê o contexto e anda conforme a sua `profundidade` // (0 = fundo, quase parado; 1 = frente, anda o dobro). É o paralaxe. import React, {createContext, useContext} from 'react'; import {useCurrentFrame} from 'remotion'; import {lerp, q, seg} from '../base'; export type ChaveCamera = [number, number, number, number]; const Ctx = createContext({zoom: 1, x: 0, y: 0}); export const useCamera = () => useContext(Ctx); const v = (f: number, ks: ChaveCamera[], i: 1 | 2 | 3) => { if (f <= ks[0][0]) return ks[0][i]; for (let k = 1; k < ks.length; k++) if (f <= ks[k][0]) {const t = seg(f, ks[k - 1][0], ks[k][0]); return lerp(ks[k - 1][i], ks[k][i], t * t * (3 - 2 * t));} return ks[ks.length - 1][i]; }; export const Camera: React.FC<{chaves?: ChaveCamera[]; children: React.ReactNode}> = ({chaves = [[0, 1, 0, 0]], children}) => { const f = q(useCurrentFrame()); const val = {zoom: v(f, chaves, 1), x: v(f, chaves, 2) + Math.sin(f / 40) * 10, y: v(f, chaves, 3) + Math.cos(f / 53) * 6}; return {children}; }; /** transform de paralaxe pra uma camada de profundidade p (0..1), com origem no centro da tela */ export const paralaxe = (cam: {zoom: number; x: number; y: number}, p: number) => { const k = 0.3 + 1.4 * p; return `translate(${-cam.x * k}px, ${-cam.y * k}px) scale(${1 + (cam.zoom - 1) * k})`; };