# Animações, keyframes e transições

## 1. Modelo de agendamento

Ciclo de vida de um clip de nível superior:
1. Esperar até `start`
2. Inserir o nó na cena
3. Executar animações, keyframes e transições durante a janela ativa do clip
4. Encerrar o ciclo de vida do clip

Comportamento em paralelo:
- `animations` e `keyframes` podem rodar em paralelo
- A `transition` visual também pode rodar em paralelo para clips que não sejam `audio`
- Clips `audio` executam automação de áudio em vez de transições visuais

## 2. `Animation`

```ts
interface Animation {
  type: AnimationType;
  duration: number;
  delay?: number;
  easing?: EasingFunction;
  loop?: boolean | number;
  from?: any;
  to?: any;
  direction?: "left" | "right" | "up" | "down";
  distance?: number;
}
```

Tipos de animação atualmente suportados:
- `fadeIn`
- `fadeOut`
- `move`
- `scale`
- `rotate`
- `slideIn`
- `slideOut`
- `zoomIn`
- `zoomOut`

## 3. Comportamento dos campos

### `duration`
- Unidade: segundos
- Obrigatório
- Se `loop` estiver ativado, um ciclo de loop ainda usa esse valor como duração base

### `delay`
- Unidade: segundos
- Opcional
- Animações com o mesmo atraso começam juntas
- Animações com atrasos diferentes executam em seu próprio momento programado

### `easing`
- Opcional
- O padrão é `linear` quando omitido

### `loop`
- Tipo: `boolean | number`
- `true`: repetir o máximo possível dentro da duração restante do clip
- Número: repetir por esse número de ciclos
- Se o tempo total de loop exceder a janela do clip, ele será truncado automaticamente

### `from`

Atualmente relevante para:
- `scale`
- `rotate`
- `move`

Notas:
- `move.from` deve ser `{ x, y }`
- `scale.from` pode ser um número ou um valor 2D
- `rotate.from` deve ser um número

### `to`

Atualmente relevante para:
- `scale`
- `rotate`
- `move`

Notas:
- `move.to` deve ser `{ x, y }`

### `direction`

Atualmente usada por:
- `slideIn`
- `slideOut`

Alguns templates embutidos também passam `direction` para suas animações geradas.

### `distance`

Atualmente usada por:
- `slideIn`
- `slideOut`

Padrão:
- Normalmente `200` quando omitida

## 4. Comportamento por tipo de animação

### `fadeIn`
- Começa com opacidade `0`
- Anima até a opacidade original

### `fadeOut`
- Anima da opacidade atual para `0`

### `zoomIn`
- Começa com escala `[0, 0]`
- Anima até a escala original

### `zoomOut`
- Anima da escala atual para `[0, 0]`

### `slideIn`
- Começa deslocada por `direction + distance`
- Também faz fade in a partir de opacidade `0`

### `slideOut`
- Termina saindo usando `direction + distance`
- Também faz fade out até opacidade `0`

### `scale`
- Se `from` existir, a escala é definida primeiro como `from`
- Depois anima para `to`
- Se `to` estiver ausente, retorna à escala original

### `rotate`
- Se `from` existir, a rotação é definida primeiro
- Depois anima para `to`
- Se `to` estiver ausente, normalmente gira até `360`

### `move`
- `from` e `to` devem ser ambos objetos
- Exemplo:

```json
{
  "type": "move",
  "duration": 1,
  "from": { "x": -200, "y": 0 },
  "to": { "x": 0, "y": 0 }
}
```

## 5. `keyframes`

```ts
interface Keyframe {
  property: string;
  frames: KeyframeFrame[];
}

interface KeyframeFrame {
  time: number;
  value: any;
  easing?: EasingFunction;
}
```

Propriedades atualmente confirmadas como suportadas:
- `x`
- `y`
- `position`
- `opacity`
- `scale`
- `rotation`
- `width`
- `height`
- `fill`
- `stroke`

Comportamento:
- `frames` são ordenados por `time`
- O primeiro frame define diretamente o valor inicial
- Frames posteriores interpolam entre pontos de controle
- Após o último keyframe, o clip espera até o seu próprio final

## 6. `Transition`

```ts
interface Transition {
  type: "fade" | "slide" | "zoom" | "wipe";
  duration: number;
  direction?: "left" | "right" | "up" | "down";
  easing?: EasingFunction;
}
```

Atualmente suportada:
- `fade`
- `slide`
- `zoom`
- `wipe`

Comportamento em runtime:
- Cada transição tem uma fase de entrada e uma fase de saída
- Ambas as fases usam `transition.duration`
- Se o tempo combinado das transições exceder a duração do clip, o runtime o trunca automaticamente

## 7. Comportamento por tipo de transição

### `fade`
- Entrada: opacidade `0 -> opacidade original`
- Saída: opacidade original `-> 0`

### `slide`
- Entrada: desliza de fora do canvas
- Saída: desliza para a direção selecionada
- A opacidade muda ao mesmo tempo

### `zoom`
- Entrada: aumenta a escala e faz fade in
- Saída: reduz a escala e faz fade out

### `wipe`
- Implementada aproximadamente por meio de escalonamento de eixos
- As direções esquerda e direita comprimem o eixo horizontal
- As direções cima e baixo comprimem o eixo vertical

## 8. Lista de easing

Atualmente suportada:
- `linear`
- `easeInSine`
- `easeOutSine`
- `easeInOutSine`
- `easeInQuad`
- `easeOutQuad`
- `easeInOutQuad`
- `easeInCubic`
- `easeOutCubic`
- `easeInOutCubic`
- `easeInQuart`
- `easeOutQuart`
- `easeInOutQuart`
- `easeInBack`
- `easeOutBack`
- `easeInOutBack`
- `easeInElastic`
- `easeOutElastic`
- `easeInOutElastic`
- `easeInBounce`
- `easeOutBounce`
- `easeInOutBounce`

## 9. Controle de tempo do áudio

Além de `start` e `duration`, clips `audio` também suportam:
- `source.start`
- `source.end`
- `fadeIn`
- `fadeOut`

Juntos, eles controlam:
- quando a reprodução começa
- qual segmento da mídia de origem é usado
- como o volume muda ao longo do tempo

## 10. Exemplo: entrada, permanência e saída de um título

```json
{
  "type": "text",
  "start": 0,
  "duration": 4,
  "text": "Hello",
  "transform": {
    "x": "50%",
    "y": "50%"
  },
  "style": {
    "fontSize": 72,
    "fill": "#ffffff"
  },
  "animations": [
    {
      "type": "slideIn",
      "direction": "up",
      "distance": 120,
      "duration": 0.6,
      "easing": "easeOutCubic"
    },
    {
      "type": "fadeOut",
      "delay": 3.2,
      "duration": 0.6,
      "easing": "easeInSine"
    }
  ],
  "transition": {
    "type": "fade",
    "duration": 0.25
  }
}
```