// Cena: janela de tempo de um plano. Entra com movimento (nunca corte seco) e sai deslizando, // sobrepondo 8 quadros com a próxima. Dentro dela, useCurrentFrame() começa em 0. import React, {createContext, useContext} from 'react'; import {AbsoluteFill, Sequence, useCurrentFrame} from 'remotion'; import {e5, eb, seg} from '../base'; export type Entrada = 'subir' | 'zoom' | 'direita' | 'esquerda' | 'girar' | 'cortar' | 'nenhuma'; export const SOBREPOE = 8; // quadros em que a saída desta cena cruza a entrada da próxima const CenaCtx = createContext({duracao: 60}); /** duração da cena atual em quadros (sem a sobreposição) */ export const useDuracaoCena = () => useContext(CenaCtx).duracao; export type CenaProps = {de: number; ate: number; entrada?: Entrada; ultima?: boolean; children: React.ReactNode}; const Janela: React.FC<{duracao: number; entrada: Entrada; ultima: boolean; children: React.ReactNode}> = ({duracao, entrada, ultima, children}) => { const f = useCurrentFrame(); const q = 10; // quadros da entrada const en = entrada === 'nenhuma' ? 0 : 1 - (entrada === 'cortar' ? eb(seg(f, 0, q)) : e5(seg(f, 0, q))); const xo = ultima ? 0 : e5(seg(f, duracao, duracao + SOBREPOE)); let tf = ''; if (entrada === 'subir') tf += `translateY(${en * 120}px) `; if (entrada === 'zoom') tf += `scale(${1 + en * 0.9}) `; if (entrada === 'direita') tf += `translateX(${en * 348}px) `; if (entrada === 'esquerda') tf += `translateX(${-en * 348}px) `; if (entrada === 'girar') tf += `rotate(${en * -14}deg) scale(${1 + en * 0.5}) `; if (entrada === 'cortar') tf += `scale(${1 + en * 0.14}) `; tf += `scale(${1 + xo * 0.08})`; const blur = (entrada === 'cortar' ? 0 : en * 6) + xo * 6; const op = entrada === 'cortar' ? 1 - xo : (1 - en * 0.6) * (1 - xo); return 0.3 ? `blur(${blur}px)` : undefined}}>{children}; }; export const Cena: React.FC = ({de, ate, entrada = 'subir', ultima = false, children}) => { const duracao = ate - de; return {children} ; };