SVGA Player Pro

简体中文

ChangeLog

Introduce

SVGAPlayer is a light-weight animation renderer. You use tools to export svga file from Adobe Animate CC or Adobe After Effects, and then use SVGAPlayer to render animation on mobile application.

SVGAPlayer-Pro render animation natively via Flutter CustomPainter, brings you a high-performance, low-cost animation experience.

If wonder more information, go to this website.

  • SVGAPlayer-Flutter supports 2.0 format only.

Usage

Here introduce SVGAPlayer-Pro usage. Wonder exporting usage? Click here.

Add dependency

dependencies:
  svgaplayer_pro: ^0.3.2

Locate files

SVGAPlayer could load svga file from Flutter local assets directory or remote server. Add file to pubspec.yaml by yourself.

Super simple to use

The simplest way to render an animation is to use SVGASimpleImage component.

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      child: SVGASimpleImage(
          resUrl: "https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true"),
    );
  }

}

Animation will run repeatedly. If you wondering a stronger animation controls, use code.

Code to use

To control an animation rendering, you need to create a SVGAAnimationController instance just like Flutter regular animation. Assign to SVGAImage, load and decode resource using SVGAParser, and then do things as you want with SVGAAnimationController.

import 'package:flutter/widgets.dart';
import 'package:svgaplayer_pro/svgaplayer_flutter.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  late final SVGAAnimationController animationController;

  @override
  void initState() {
    super.initState();
    animationController = SVGAAnimationController(vsync: this);
    loadAnimation();
  }

  @override
  void dispose() {
    this.animationController.dispose();
    super.dispose();
  }

  Future<void> loadAnimation() async {
    try {
      final videoItem = await SVGAParser.shared.decodeFromURL(
          "https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
      if (!mounted) {
        videoItem.dispose();
        return;
      }
      animationController
        ..videoItem = videoItem
        ..repeat(); // Or use forward() / reverse().
    } catch (error) {
      if (mounted) debugPrint('SVGA load failed: $error');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: SVGAImage(this.animationController),
    );
  }
}

Reuse MovieEntity

The MovieEntity will dispose after AnimationController dispose or AnimationController::videoItem reset.

After dispose, the MovieEntity can not reused.

If you eager to reuse the MovieEntity, assign MovieEntity::autorelease to false.

final videoItem = await SVGAParser.shared.decodeFromURL(
        "https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true");
videoItem.autorelease = false;

You need to call MovieEntity::dispose() method when no need to use.

Cache

Downloads are not cached. Use dio or another network library for persistent download caching; decoded resources are cached for the lifetime of a movie.

Use SVGAParser.decodeFromBytes (alias of decodeFromBuffer) to decode caching data.

Audio

SVGA files that embed MP3 tracks play automatically with the animation. Control gain on the controller:

animationController.volume = 0.5; // 0.0 ~ 1.0
animationController.muted = true;

Features

Here are many feature samples.

Resource lifecycle and limits

SVGAParser bounds downloads (64 MiB), inflated data (128 MiB), individual images (16 megapixels), and decoded images per movie (256 MiB). Downloads have a 30-second total timeout. These limits are configurable in the parser constructor. Invalid movies and images fail the returned Future; catch errors when loading. Native platforms parse in a worker isolate; Web uses the browser event loop.

Use const SVGAParser(retainSourceImages: false) to release encoded media after loading when the movie will not be serialized again. The default retains it for compatibility. Call movie.dispose() when manually managing a movie with autorelease = false.

setImage retains its own image clone; callers still dispose their original. setImageWithUrl owns its downloaded image. setText borrows the TextPainter by default; pass owned: true to transfer ownership. Owned resources are released on replacement, reset(), or movie disposal. Setter methods notify paused views. Direct writes to the public dynamic maps require calling refresh(); resources inserted directly remain caller-owned.

After mutating generated shapes, transforms or sprite keys, call movie.invalidateRenderCaches() and notify/rebuild the view. Short sprite tracks disappear after their final frame. Matte layers use alpha masks and are not drawn as ordinary content. Audio seeks with the animation, plays once per forward cycle, and is paused during reverse playback. Web audio is unsupported.

Verification

Run flutter analyze and flutter test in the package, and flutter test in example/. Optional network integration uses local static resource fixtures:

postman simulation run postman/simulations/resources.sim.yaml --port 4910 --no-history
# In a second terminal:
dart run tool/check_network.dart
flutter test --dart-define=SVGA_RESOURCE_BASE=http://127.0.0.1:4910/resources test/network_resource_integration_test.dart

The simulation models successful binary downloads, HTTP errors, delayed replies and oversized responses; it does not need a cloud workspace. Stop it with Ctrl-C. Without SVGA_RESOURCE_BASE, the three network integration tests are skipped.