# Animations, images clés et transitions

## 1. Modèle d'ordonnancement

Cycle de vie d'un clip de niveau supérieur :
1. Attendre jusqu'à `start`
2. Insérer le nœud dans la scène
3. Exécuter animations, images clés et transitions pendant la fenêtre active du clip
4. Terminer le cycle de vie du clip

Comportement parallèle :
- `animations` et `keyframes` peuvent s'exécuter en parallèle
- La `transition` visuelle peut également s'exécuter en parallèle pour les clips non `audio`
- Les clips `audio` exécutent une automation audio au lieu de transitions visuelles

## 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;
}
```

Types d'animation actuellement pris en charge :
- `fadeIn`
- `fadeOut`
- `move`
- `scale`
- `rotate`
- `slideIn`
- `slideOut`
- `zoomIn`
- `zoomOut`

## 3. Comportement des champs

### `duration`
- Unité : secondes
- Requis
- Si `loop` est activé, un cycle de boucle utilise toujours cette valeur comme durée de base

### `delay`
- Unité : secondes
- Optionnel
- Les animations avec le même délai démarrent ensemble
- Les animations avec des délais différents s'exécutent à leur propre moment planifié

### `easing`
- Optionnel
- Vaut `linear` par défaut lorsqu'il est omis

### `loop`
- Type : `boolean | number`
- `true` : répéter autant de fois que possible dans la durée restante du clip
- Nombre : répéter ce nombre de cycles
- Si le temps total de boucle dépasse la fenêtre du clip, il est tronqué automatiquement

### `from`

Actuellement pertinent pour :
- `scale`
- `rotate`
- `move`

Notes :
- `move.from` doit être `{ x, y }`
- `scale.from` peut être un nombre ou une valeur 2D
- `rotate.from` doit être un nombre

### `to`

Actuellement pertinent pour :
- `scale`
- `rotate`
- `move`

Notes :
- `move.to` doit être `{ x, y }`

### `direction`

Actuellement utilisée par :
- `slideIn`
- `slideOut`

Certains templates intégrés transmettent également `direction` à leurs animations générées.

### `distance`

Actuellement utilisée par :
- `slideIn`
- `slideOut`

Valeur par défaut :
- Généralement `200` lorsqu'elle est omise

## 4. Comportement par type d'animation

### `fadeIn`
- Commence avec une opacité `0`
- Anime jusqu'à l'opacité d'origine

### `fadeOut`
- Anime de l'opacité actuelle vers `0`

### `zoomIn`
- Commence avec une échelle `[0, 0]`
- Anime jusqu'à l'échelle d'origine

### `zoomOut`
- Anime de l'échelle actuelle vers `[0, 0]`

### `slideIn`
- Commence avec un décalage défini par `direction + distance`
- Fait aussi apparaître progressivement depuis une opacité `0`

### `slideOut`
- Se termine en sortant selon `direction + distance`
- Fait aussi disparaître progressivement jusqu'à une opacité `0`

### `scale`
- Si `from` existe, l'échelle est d'abord définie sur `from`
- Ensuite elle anime vers `to`
- Si `to` est absent, elle revient à l'échelle d'origine

### `rotate`
- Si `from` existe, la rotation est d'abord définie
- Ensuite elle anime vers `to`
- Si `to` est absent, elle tourne généralement jusqu'à `360`

### `move`
- `from` et `to` doivent tous deux être des objets
- Exemple :

```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;
}
```

Propriétés actuellement confirmées comme prises en charge :
- `x`
- `y`
- `position`
- `opacity`
- `scale`
- `rotation`
- `width`
- `height`
- `fill`
- `stroke`

Comportement :
- `frames` sont triées par `time`
- La première frame définit directement la valeur initiale
- Les frames suivantes interpolent entre les points de contrôle
- Après la dernière image clé, le clip attend jusqu'à sa propre fin

## 6. `Transition`

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

Actuellement pris en charge :
- `fade`
- `slide`
- `zoom`
- `wipe`

Comportement à l'exécution :
- Chaque transition possède une phase d'intro et une phase d'outro
- Les deux phases utilisent `transition.duration`
- Si le temps combiné des transitions dépasse la durée du clip, le runtime le tronque automatiquement

## 7. Comportement par type de transition

### `fade`
- Intro : opacité `0 -> opacité d'origine`
- Outro : opacité d'origine `-> 0`

### `slide`
- Intro : glisse depuis l'extérieur du canvas
- Outro : glisse vers la direction choisie
- L'opacité change en même temps

### `zoom`
- Intro : zoom avant et fondu entrant
- Outro : zoom arrière et fondu sortant

### `wipe`
- Approximativement implémenté via une mise à l'échelle des axes
- Les directions gauche et droite compressent l'axe horizontal
- Les directions haut et bas compressent l'axe vertical

## 8. Liste des fonctions d'assouplissement

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

## 9. Contrôle du timing audio

En plus de `start` et `duration`, les clips `audio` prennent aussi en charge :
- `source.start`
- `source.end`
- `fadeIn`
- `fadeOut`

Ensemble, ces champs contrôlent :
- quand la lecture commence
- quel segment du média source est utilisé
- comment le volume évolue dans le temps

## 10. Exemple : intro du titre, maintien et sortie

```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
  }
}
```