搜尋套件、儲存庫與 APP 分類

套件詳情v1.2.0

flutter_spritesheet_animation

適用於 Flutter 的輕量級精靈表動畫小部件。支援基於網格和 JSON 資源圖集(TexturePacker、Aseprite),具備命名動畫、播放模式與外部控制器。

AndroidiOSLinuxmacOSWebWindows
近 30 天下載
1.6萬
喜歡數
22
Pub 分數
160

安裝套件

flutter pub add flutter_spritesheet_animation

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

一個輕量級的 Flutter 小部件,用於使用基於網格的佈局渲染精靈表動畫,並支援 TexturePacker 和 Aseprite 等工具產生的 JSON 資源圖格式。它支援命名動畫、多種播放模式以及外部動畫控制。非常適合需要平滑精靈過渡的 2D 遊戲和互動式 UI。該套件具備跨平台特性,可無縫整合至 Flutter 專案中。

適用情境

  • 2D遊戲角色動畫
  • 互動式 UI 元素
  • 基於精靈的載入指示器
  • 遊戲資產渲染
  • 動畫圖示

主要特色

  • 基於網格的精靈表解析
  • JSON 地圖支援(TexturePacker、Aseprite)
  • 命名的動畫序列
  • 播放模式控制(循環、單次、倒放)
  • 外部動畫控制器
  • 跨平台相容性

適合對象

  • 使用 Flutter 的遊戲開發者
  • 需要動畫角色的UI設計師
  • 基於精靈的資源項目
  • 輕量級動畫需求
  • 互動式應用元件

使用建議

  • 需要正確的JSON圖集設定
  • 限制為2D精靈渲染
  • 無內建物理或碰撞
  • 依賴外部工具進行精靈創建
  • 未針對高幀率複雜動畫進行優化

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。

flutter_spritesheet_animation

Lightweight spritesheet animation widget for Flutter. Supports grid-based and JSON atlas (TexturePacker, Aseprite) spritesheets with named animations, playback modes, and an external controller.

Zero external dependencies - uses only the Flutter SDK.

Features

  • Grid-based spritesheet animation (uniform frame grid)
  • JSON atlas animation (TexturePacker hash/array, Aseprite)
  • Named animations via frameTags
  • Playback modes: forward, reverse, pingPong
  • External controller for programmatic control
  • Per-frame duration support from atlas data
  • Pre-computed frame rects for optimal rendering
  • Configurable FPS, looping, blend mode, box fit
  • Speed multiplier that also works on atlas animations with per-frame durations
  • Fixed repeat counts with per-cycle callbacks

Installation

dependencies:
  flutter_spritesheet_animation: ^1.0.2

Usage

Grid Mode

For spritesheets with frames arranged in a uniform grid:

SpriteAnimation.grid(
  image: AssetImage('assets/explosion.png'),
  columns: 8,
  rows: 4,
  frameCount: 30,  // optional, defaults to columns * rows
  fps: 24,
  width: 128,
  height: 128,
)
Atlas Mode

For spritesheets defined by a JSON atlas (TexturePacker or Aseprite export):

// Load atlas from asset
final atlas = await SpriteAtlas.fromAsset('assets/character.json');

SpriteAnimation.atlas(
  image: AssetImage('assets/character.png'),
  atlas: atlas,
  animation: 'idle',  // named animation from frameTags
  width: 128,
  height: 128,
)
Controller

Use SpriteAnimationController for programmatic playback control:

final controller = SpriteAnimationController(
  fps: 24,
  mode: PlayMode.pingPong,
  loop: true,
  autoPlay: false,
);

// In your widget tree
SpriteAnimation.grid(
  image: AssetImage('assets/explosion.png'),
  columns: 8,
  rows: 4,
  controller: controller,
)

// Control playback
controller.play();
controller.pause();
controller.stop();
controller.goToFrame(5);

// Change settings at runtime
controller.fps = 30;
controller.mode = PlayMode.reverse;
controller.loop = false;

// Switch named animations (atlas mode)
controller.setAnimation('walk', atlas: atlas);

// Read state
controller.isPlaying;    // bool
controller.currentFrame; // int
controller.totalFrames;  // int
controller.animationName; // String?

// Don't forget to dispose when using externally
controller.dispose();
Precaching

Pre-cache spritesheet images to eliminate loading flash:

// Single image
await SpriteAnimation.precache(
  const AssetImage('assets/explosion.png'),
  context,
);

// Multiple images in parallel
await SpriteAnimation.precacheAll([
  const AssetImage('assets/idle.png'),
  const AssetImage('assets/walk.png'),
  const AssetImage('assets/attack.png'),
], context);
Callbacks
SpriteAnimation.grid(
  image: AssetImage('assets/explosion.png'),
  columns: 8,
  rows: 4,
  loop: false,
  onFrame: (frame) => print('Frame: $frame'),
  onComplete: () => print('Animation finished'),
)
Atlas JSON Formats

TexturePacker (hash):

{
  "frames": {
    "idle_0.png": {
      "frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
      "rotated": false,
      "trimmed": false,
      "spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
      "sourceSize": { "w": 64, "h": 64 }
    }
  },
  "meta": {
    "size": { "w": 256, "h": 256 },
    "frameTags": [
      { "name": "idle", "from": 0, "to": 3 },
      { "name": "walk", "from": 4, "to": 9 }
    ]
  }
}

Aseprite (array):

{
  "frames": [
    {
      "filename": "idle_0.png",
      "frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
      "duration": 100
    }
  ],
  "meta": {
    "frameTags": [
      { "name": "idle", "from": 0, "to": 3 }
    ]
  }
}

Both formats are auto-detected.

Performance

Optimized for smooth 60fps animation rendering:

  • Zero widget rebuilds: Uses CustomPainter(repaint: controller) — frame changes repaint only the paint layer, skipping build() entirely
  • Zero-allocation tick loop: Raw microsecond arithmetic instead of Duration objects in the hot path
  • Pre-computed frame rects: Grid source rectangles are calculated once at load time, not during paint
  • Reusable Paint object: Single Paint instance reused across frames, avoiding per-frame allocations
  • Accumulator-based timing: Frame advancement uses a time accumulator for accurate frame pacing
  • Image precaching: precache() / precacheAll() to eliminate loading flash
  • Multiple instances: Each widget runs independently with its own controller, ticker, and paint layer
  • No external dependencies: Zero overhead from third-party packages

API Reference

SpriteAnimation
Property Type Default Description
image ImageProvider required Spritesheet image
columns int - Grid columns (grid mode)
rows int - Grid rows (grid mode)
frameCount int? columns*rows Total frames (grid mode)
atlas SpriteAtlas - Atlas data (atlas mode)
animation String? first Animation name (atlas mode)
fps double 12 Frames per second
autoPlay bool true Start automatically
loop bool true Loop animation
mode PlayMode forward Playback direction
blendMode BlendMode srcOver Canvas blend mode
fit BoxFit contain How sprite fits in bounds
width double? - Fixed width
height double? - Fixed height
controller SpriteAnimationController? - External controller
onFrame ValueChanged<int>? - Frame change callback
onComplete VoidCallback? - Completion callback
SpriteAnimationController
Method Description
play() Start or resume playback
pause() Pause at current frame
stop() Stop and reset to frame 0
goToFrame(int) Jump to specific frame
setAnimation(String, {SpriteAtlas}) Switch named animation
dispose() Clean up resources
Property Type Default Description
speed double 1 Playback multiplier applied to the whole clock
repeatCount int? null Cycles to play before completing; null is unlimited
completedCycles int 0 Cycles finished since playback started
onCycle ValueChanged<int>? - Fires on every wrap of a looping animation
Speed

fps sets the base frame rate, but atlas animations carry per-frame durations and ignore it. speed scales the clock either way:

final controller = SpriteAnimationController(speed: 2);   // twice as fast
controller.speed = 0.5;                                    // half speed
Fixed repeats
// Play the effect three times, then stop and call onComplete
final controller = SpriteAnimationController(repeatCount: 3)
  ..onCycle = (done) => debugPrint('cycle $done')
  ..onComplete = () => debugPrint('done');

repeatCount only applies while loop is true: a non-looping animation always stops after one pass.

SpriteAtlas
Method Description
SpriteAtlas.fromJson(String) Parse from JSON string
SpriteAtlas.fromAsset(String) Load from Flutter asset
getAnimation(String) Get animation data by name
animationNames List of available animation names

License

MIT

所屬分類

原始碼儲存庫

使用此套件的專案

暫無相關資料。

所在榜單