패키지, 저장소 및 앱 카테고리 검색

패키지 상세v1.2.0

flutter_spritesheet_animation

Flutter용 가벼운 스프라이트시트 애니메이션 위젯입니다. 그리드 기반 및 JSON 아틀라스(TexturePacker, Aseprite) 지원과 함께 이름이 지정된 애니메이션, 재생 모드, 외부 컨트롤러를 제공합니다.

AndroidiOSLinuxmacOSWebWindows
30일 다운로드
1.6만
좋아요
22
Pub 점수
160

패키지 설치

flutter pub add flutter_spritesheet_animation

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

그리드 기반 레이아웃과 TexturePacker 및 Aseprite와 같은 JSON 아틀라스 형식을 지원하는 가벼운 스프라이트시트 애니메이션 렌더링을 위한 플러터 위젯입니다. 이름 붙은 애니메이션, 여러 재생 모드, 외부 애니메이션 제어를 가능하게 합니다. 부드러운 스프라이트 전환을 필요로 하는 2D 게임 및 인터랙티브 UI에 적합합니다. 이 패키지는 크로스플랫폼이며 플러터 프로젝트에 원활하게 통합됩니다.

사용 사례

  • 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

카테고리

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.

순위