動畫

先進的動畫系統,用於創建超越簡單關鍵幀的動態、程序性和基於表達式的動畫。

動畫類型

動畫系統支持多種類型,超越傳統的關鍵幀:

  • 表達式:每幀評估的 JavaScript 表達式
  • 程序性:內建的程序動畫模式
  • 序列:基於步驟的順序動畫
  • 路徑:沿著貝茲路徑的運動

這些先進的動畫在元素的 animations 陣列屬性中定義。

節點動畫與關鍵幀

節點動畫 (animations 陣列):

  • 程序性、基於表達式或跟隨路徑的動畫
  • 每幀評估
  • 優先級高於關鍵幀
  • 可以覆蓋關鍵幀值

關鍵幀 (keyframes 陣列):

  • 在定義點之間的簡單屬性插值
  • 優先級較低
  • 可預測,易於編輯

動畫優先級

當多個動畫方法針對相同屬性時:

  1. 最高:節點動畫(表達式、程序性、路徑、序列)
  2. 中等:關鍵幀動畫
  3. 最低:靜態屬性值
屬性類型必要範例值範圍描述
typestringtrue-expression | procedural | sequence | path動畫的類型。
enabledbooleanfalse--動畫是否處於活動狀態。
targetstringtrue--要動畫的屬性路徑(例如,"x"、"rotation"、"scaleX")。
startTimenumberfalse--相對於元素開始的動畫開始時間,以秒為單位。
durationnumberfalse--動畫的持續時間,以秒為單位。對於循環動畫,這是循環週期。
loopbooleanfalse--動畫是否循環。
blendModestringfalse-replace | add | multiply此動畫與其他動畫的組合方式:替換(覆蓋)、添加(總和)、乘法(縮放)。
blendWeightnumberfalse--此動畫的強度/影響(0-1)。用於混合多個動畫。

表達式動畫

表達式是每幀評估的 JavaScript 代碼,可以訪問動畫上下文變量。

可用上下文變量

{
  time: number; // 當前絕對時間(秒)
  localTime: number; // 相對於元素開始的時間
  duration: number; // 元素持續時間
  progress: number; // 正規化的進度(0-1)
  index: number; // 組中元素的索引
  total: number; // 組中的總元素數量
  fps: number; // 每秒幀數
  width: number; // 畫布寬度
  height: number; // 畫布高度
  value: any; // 當前屬性值
}

表達式範例

使用數學函數的彈跳動畫:

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

複雜表達式

結合多種效果:

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

程序性動畫

內建的動畫模式,具有可配置的參數。

程序性類型

  • wiggle:隨機振蕩(適用於手持攝影機效果)
  • wave:正弦/餘弦波運動
  • bounce:彈性彈跳效果
  • pulse:有節奏的縮放

Wiggle 範例

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

序列動畫

基於步驟的動畫,在特定間隔內改變值。

屬性類型必要範例值範圍描述
valuesarraytrue--要逐步遍歷的值的數組。
stepDurationnumbertrue--每個步驟的持續時間,以秒為單位。
loopbooleanfalse--是否循環序列。

序列範例

文本循環不同大小:

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

路徑動畫

沿著貝茲曲線路徑對元素進行動畫。

屬性類型必要範例值範圍描述
pathstring | arraytrue--SVG 路徑數據(d 屬性)或路徑點的數組。
autoRotatebooleanfalse--是否自動旋轉元素以跟隨路徑切線。
durationnumbertrue--完成整個路徑所需的時間。

路徑範例

圓形運動:

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

屬性路徑語法

target 屬性使用點標記法來指定嵌套屬性:

  • 簡單"x""y""rotation"
  • 嵌套"scale.x""position.y"
  • 數組"colors[0]""points[2].x"

目標解析範例

{
  "target": "x"              // 元素的 x 位置
  "target": "scaleX"         // 水平縮放
  "target": "alpha"          // 不透明度
  "target": "fill.color"     // 填充顏色(如果填充是物件)
  "target": "points[0].x"    // 第一個點的 x 坐標
}

混合模式

控制當多個動畫目標相同屬性時的組合方式:

替換(默認)

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

完全替換屬性值。

添加

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

添加到現有值(加權)。對於累積偏移量非常有用。

乘法

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

乘以現有值。對於縮放效果非常有用。

多重動畫範例

結合不同的動畫類型:

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

在這個範例中:

  • 表達式控制水平位置(替換模式)
  • 程序性 wiggle 添加微妙的旋轉變化
  • 序列脈衝不透明度
  • 關鍵幀縮放元素(最低優先級)

重要說明

表達式沙盒

  • 表達式在受限的上下文中運行以確保安全
  • 只能訪問動畫上下文變量
  • 不能訪問 DOM、外部庫或 Node.js API
  • 評估錯誤將禁用動畫

性能

  • 表達式:每幀評估 - 保持簡單
  • 程序性:優化的內建函數 - 效率極高
  • 序列:最小開銷,適用於離散變化
  • 路徑:中等成本,取決於路徑複雜性

時間

  • startTimeduration 相對於元素的 start 時間
  • 表達式中的 localTime 在元素開始時從 0 開始
  • 動畫遵循元素的整體 duration 邊界

調試

  • 如果動畫無法正常運行,請檢查:
    • enabled: true
    • 元素上存在 target 屬性
    • 表達式語法是有效的 JavaScript
    • startTime 在元素的持續時間內
    • 沒有屬性路徑的拼寫錯誤

常見用例

平滑跟隨效果

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

彈性彈跳

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

鏡頭搖晃

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

錯開動畫(分組)

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