Animazione

Sistema di animazione avanzato per creare animazioni dinamiche, procedurali e basate su espressioni oltre i semplici fotogrammi chiave.

Tipi di Animazione

Il sistema di animazione supporta diversi tipi oltre ai tradizionali fotogrammi chiave:

  • Espressione: Espressioni JavaScript valutate per ogni fotogramma
  • Procedurale: Modelli di animazione procedurale integrati
  • Sequenza: Animazioni sequenziali basate su passaggi
  • Percorso: Movimento lungo percorsi di Bezier

Queste animazioni avanzate sono definite nella proprietà array animations degli elementi.

Animazioni dei Nodi vs Fotogrammi Chiave

Animazioni dei Nodi (array animations):

  • Animazioni procedurali, basate su espressioni o seguendo un percorso
  • Valutate ad ogni fotogramma
  • Maggiore priorità rispetto ai fotogrammi chiave
  • Possono sovrascrivere i valori dei fotogrammi chiave

Fotogrammi Chiave (array keyframes):

  • Semplice interpolazione delle proprietà tra punti definiti
  • Priorità inferiore
  • Prevedibile, facile da modificare

Priorità dell'Animazione

Quando più metodi di animazione mirano alla stessa proprietà:

  1. Massima: Animazioni dei nodi (espressione, procedurale, percorso, sequenza)
  2. Media: Animazioni a fotogrammi chiave
  3. Minima: Valori delle proprietà statiche
ProprietàTipoRichiestoEsempioIntervallo di valoriDescrizione
typestringtrue-expression | procedural | sequence | pathIl tipo di animazione.
enabledbooleanfalse--Se l'animazione è attiva.
targetstringtrue--Il percorso della proprietà da animare (ad es., "x", "rotation", "scaleX").
startTimenumberfalse--Tempo di inizio dell'animazione relativo all'inizio dell'elemento, in secondi.
durationnumberfalse--Durata dell'animazione in secondi. Per animazioni cicliche, questo è il periodo del ciclo.
loopbooleanfalse--Se l'animazione è ciclica.
blendModestringfalse-replace | add | multiplyCome questa animazione si combina con altre: sostituire (sovrascrivere), aggiungere (somma), moltiplicare (scala).
blendWeightnumberfalse--La forza/influenza di questa animazione (0-1). Utilizzato per fondere più animazioni.

Animazioni per Espressioni

Le espressioni sono codice JavaScript valutato per ogni fotogramma, con accesso alle variabili di contesto dell'animazione.

Variabili di Contesto Disponibili

{
  time: number; // Tempo assoluto attuale (secondi)
  localTime: number; // Tempo relativo all'inizio dell'elemento
  duration: number; // Durata dell'elemento
  progress: number; // Progresso normalizzato (0-1)
  index: number; // Indice dell'elemento nel gruppo
  total: number; // Numero totale di elementi nel gruppo
  fps: number; // Fotogrammi al secondo
  width: number; // Larghezza del canvas
  height: number; // Altezza del canvas
  value: any; // Valore della proprietà corrente
}

Esempio di Espressione

Animazione di rimbalzo utilizzando funzioni Math:

expressionAnimation.json
{
"id": "element-1",
"type": "Image",
"start": 0,
"duration": 5,
"animations": [
  {
    "type": "expression",
    "target": "y",
    "enabled": true,
    "expression": "100 + Math.abs(Math.sin(localTime * 3)) * 200",
    "startTime": 0,
    "duration": 5,
    "loop": true
  }
]
}

Espressione Complessa

Combina più effetti:

complexExpression.json
{
"animations": [
  {
    "type": "expression",
    "target": "rotation",
    "expression": "(localTime * 2 * Math.PI / duration) + Math.sin(localTime * 4) * 0.1",
    "loop": true
  },
  {
    "type": "expression",
    "target": "scaleX",
    "expression": "1 + Math.sin(localTime * 5) * 0.2",
    "loop": true
  }
]
}

Animazioni Procedurali

Modelli di animazione integrati con parametri configurabili.

Tipi Procedurali

  • wiggle: Oscillazione casuale (utile per effetti di telecamera a mano)
  • wave: Movimento sinusoidale/cosinusoidale
  • bounce: Effetto di rimbalzo elastico
  • pulse: Scaling ritmico

Esempio di Wiggle

wiggleAnimation.json
{
"animations": [
  {
    "type": "procedural",
    "proceduralType": "wiggle",
    "target": "rotation",
    "enabled": true,
    "frequency": 2,
    "amplitude": 0.1,
    "loop": true
  }
]
}

Animazioni di Sequenza

Animazioni basate su passaggi che cambiano valori a intervalli specifici.

ProprietàTipoRichiestoEsempioIntervallo di valoriDescrizione
valuesarraytrue--Array di valori da attraversare.
stepDurationnumbertrue--Durata di ciascun passaggio in secondi.
loopbooleanfalse--Se far ripetere la sequenza.

Esempio di Sequenza

Testo che cicla attraverso diverse dimensioni:

sequenceAnimation.json
{
"animations": [
  {
    "type": "sequence",
    "target": "fontSize",
    "enabled": true,
    "values": [24, 32, 40, 32, 24],
    "stepDuration": 0.5,
    "loop": true
  }
]
}

Animazioni di Percorso

Animare gli elementi lungo percorsi di curve di Bezier.

ProprietàTipoRichiestoEsempioIntervallo di valoriDescrizione
pathstring | arraytrue--Dati del percorso SVG (attributo d) o array di punti del percorso.
autoRotatebooleanfalse--Se ruotare automaticamente l'elemento per seguire la tangente del percorso.
durationnumbertrue--Tempo per completare l'intero percorso.

Esempio di Percorso

Movimento circolare:

pathAnimation.json
{
"animations": [
  {
    "type": "path",
    "target": "position",
    "enabled": true,
    "path": "M 100,100 a 200,200 0 1,1 0,1 Z",
    "autoRotate": true,
    "duration": 4,
    "loop": true
  }
]
}

Sintassi del Percorso della Proprietà

La proprietà target utilizza la notazione a punti per specificare proprietà annidate:

  • Semplice: "x", "y", "rotation"
  • Annidato: "scale.x", "position.y"
  • Array: "colors[0]", "points[2].x"

Esempi di Risoluzione del Target

{
  "target": "x"              // Posizione x dell'elemento
  "target": "scaleX"         // Scala orizzontale
  "target": "alpha"          // Opacità
  "target": "fill.color"     // Colore di riempimento (se fill è un oggetto)
  "target": "points[0].x"    // Coordinata x del primo punto
}

Modi di Fusione

Controlla come le animazioni si combinano quando più mirano alla stessa proprietà:

Sostituisci (Predefinito)

{
  "blendMode": "replace",
  "blendWeight": 1.0
}

Sostituisce completamente il valore della proprietà.

Aggiungi

{
  "blendMode": "add",
  "blendWeight": 0.5
}

Aggiunge al valore esistente (pesato). Utile per accumulare offset.

Moltiplica

{
  "blendMode": "multiply",
  "blendWeight": 1.0
}

Moltiplica il valore esistente. Utile per effetti di scaling.

Esempio di Animazioni Multiple

Combinare diversi tipi di animazione:

multipleAnimations.json
{
"id": "animated-element",
"type": "Shape",
"animations": [
  {
    "type": "expression",
    "target": "x",
    "expression": "width / 2 + Math.sin(localTime * 2) * 300",
    "blendMode": "replace",
    "loop": true
  },
  {
    "type": "procedural",
    "proceduralType": "wiggle",
    "target": "rotation",
    "frequency": 3,
    "amplitude": 0.2,
    "blendMode": "add",
    "blendWeight": 0.5
  },
  {
    "type": "sequence",
    "target": "alpha",
    "values": [1, 0.8, 1],
    "stepDuration": 0.3,
    "loop": true,
    "blendMode": "multiply"
  }
],
"keyframes": [
  {
    "id": "kf-1",
    "time": 0,
    "stateObj": { "scaleX": 1 }
  },
  {
    "id": "kf-2",
    "time": 2,
    "stateObj": { "scaleX": 1.5 }
  }
]
}

In questo esempio:

  • L'espressione controlla la posizione orizzontale (modalità di sostituzione)
  • Il wiggle procedurale aggiunge una sottile variazione di rotazione
  • La sequenza pulsa l'opacità
  • Il fotogramma chiave scala l'elemento (priorità più bassa)

Note Importanti

Sandbox per Espressioni

  • Le espressioni vengono eseguite in un contesto ristretto per motivi di sicurezza
  • Accesso solo alle variabili di contesto dell'animazione
  • Non può accedere al DOM, librerie esterne o API di Node.js
  • Gli errori di valutazione disabiliteranno l'animazione

Prestazioni

  • Espressioni: Valutate ad ogni fotogramma - mantienile semplici
  • Procedurale: Funzioni integrate ottimizzate - molto efficienti
  • Sequenza: Sovraccarico minimo, buono per cambiamenti discreti
  • Percorso: Costo moderato, dipende dalla complessità del percorso

Tempistiche

  • startTime e duration sono relativi al tempo start dell'elemento
  • localTime nelle espressioni inizia a 0 quando l'elemento inizia
  • Le animazioni rispettano il confine di duration complessivo dell'elemento

Debugging

  • Se un'animazione non funziona, controlla:
    • enabled: true
    • La proprietà target esiste sull'elemento
    • La sintassi dell'espressione è un JavaScript valido
    • startTime è all'interno della durata dell'elemento
    • Nessun errore di battitura nel percorso della proprietà

Casi d'Uso Comuni

Effetto di Seguito Morbido

{
  "type": "expression",
  "target": "x",
  "expression": "value + (targetX - value) * 0.1"
}

Rimbalzo Elastico

{
  "type": "expression",
  "target": "scaleY",
  "expression": "1 + Math.exp(-localTime * 3) * Math.cos(localTime * 8) * 0.5"
}

Tremolio della Telecamera

{
  "type": "procedural",
  "proceduralType": "wiggle",
  "target": "x",
  "frequency": 10,
  "amplitude": 5
}

Animazione Staggered (in gruppi)

{
  "type": "expression",
  "target": "alpha",
  "expression": "Math.max(0, Math.min(1, (localTime - index * 0.1) * 2))"
}