SVG Drawing Animation

pub package Unit Tests Buy Me A Coffee

Widget for drawing line animations of SVG. For now, it only renders paths. Feel free to propose pull requests if you want to support a new feature.

Features

  • load SVG from any source (string, network...). See built-in SvgProviders.
  • supports Duration and speed.
  • supports Curves.
  • supports Animations.
  • customizable loading and error state.
  • customizable "pen" rendering.

See SvgDrawingAnimation for more.

Difference with other packages

  • drawing_animation served as inspiration for this package. It appears not to be maintained any more. Check out the table below for differences.
  • flutter_svg provides a Widget to render static SVG. We use flutter_svg to parse SVG.
  • animated_svg makes smooth transitions between two different SVG.
Feature this package drawing animation
Draws animations of SVG
Load SVG from String
Load SVG from Network
Load SVG from Assets
Load SVG from File
Recursive style (eg a group's style applies to its children)
Duration, Curve, repeats
Speed instead of Duration
Draws the Pen
Line orders (in order, all at once, top to bottom...)

Usage

Basic Usage

import 'package:svg_drawing_animation/svg_drawing_animation.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        home: Scaffold(
            appBar: AppBar(title: const Text('Example')),
            body: Center(
                child: SvgDrawingAnimation(
              SvgProvider.network(
                  'https://upload.wikimedia.org/wikipedia/commons/4/4a/African_Elephant_SVG.svg'),
              duration: const Duration(seconds: 10),
            ))));
  }
}

Fit it in a box

MaterialApp(
  title: 'Flutter Demo',
  home: Scaffold(
      appBar: AppBar(title: const Text('Example')),
      body: Center(
          child: SizedBox(
              width: 300,
              height: 300,
              child: SvgDrawingAnimation(
        SvgProvider.network(
            'https://upload.wikimedia.org/wikipedia/commons/4/4a/African_Elephant_SVG.svg'),
        duration: const Duration(seconds: 10),
      )))));

With curves and repeat

SvgDrawingAnimation(
    SvgProvider.network(
        'https://upload.wikimedia.org/wikipedia/commons/4/4a/African_Elephant_SVG.svg'),
    duration: const Duration(seconds: 10),
    curve: Curves.decelerate,
    repeats: true)

Speed instead of duration

SvgDrawingAnimation(
    SvgProvider.network(
        'https://upload.wikimedia.org/wikipedia/commons/4/4a/African_Elephant_SVG.svg'),
    speed: 100,
    repeats: true)

Custom animation

You can use your own AnimationController.

class ReplayableCard extends StatefulWidget {
  const ReplayableCard({super.key});

  @override
  State<ReplayableCard> createState() => _ReplayableCardState();
}

class _ReplayableCardState extends State<ReplayableCard>
    with SingleTickerProviderStateMixin {
  late AnimationController controller;

  @override
  void initState() {
    controller =
        AnimationController(vsync: this, duration: Duration(seconds: 5));
    controller.forward();

    super.initState();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        controller.reset();
        controller.forward();
      },
      child: Card(
        child: SizedBox(
          width: 100,
          height: 100,
          child: SvgDrawingAnimation(SvgProvider.string(kanjiSvg),
              animation: controller),
        ),
      ),
    );
  }
}

Custom progress indicator

SvgDrawingAnimation(
    SvgProvider.network(
        'https://upload.wikimedia.org/wikipedia/commons/4/4a/African_Elephant_SVG.svg'),
    duration: const Duration(seconds: 4),
    loadingWidgetBuilder: (context) => Center(child: LinearProgressIndicator()))

Custom error handling

By default svg_drawing_animation shows an error message when an error occurs, but you can customize what to show to the user instead.

SvgDrawingAnimation(
    SvgProvider.network(
        'https://upload.wikimedia.org/wikipedia/commons/4/4a/African_Elephant_SVG.svg'),
    duration: const Duration(seconds: 4),
    errorWidgetBuilder: (context) => Text('Oops! Something went wrong.'))

Drawing the Pen

SvgDrawingAnimation(
    SvgProvider.network(
        'https://upload.wikimedia.org/wikipedia/commons/4/4a/African_Elephant_SVG.svg'),
    duration: const Duration(seconds: 4),
    penRenderer: CirclePenRenderer(radius: 15))

Design choices

Constructor parameters: Duration, Curve, repeats

We've followed the style of ImplicitlyAnimatedWidget, which take a Duration, a Curve and a repeats flag similar to AnimatedRotation.turns. This allows for a good amount of customization without having to mess with AnimationControllers and StatefulWidgets.

See docs.flutter.dev/development/ui/animations for comprehensive information on animations.

SvgProvider

Flutter's Image widdget uses an ImageProvider, while flutter_svg's SvgPicture uses a similar PictureProvider pattern. We follow that architecture by introducing an SvgProvider with Futures instead of Streams for simplicity.

Loading and Error states

We allow custom rendering of loading and error states similar to Image's ImageLoadingBuilder and ImageErrorWidgetBuilder.

Developing

Re-generating http.Client mocks

Run flutter pub run build_runner build. See Flutter Cookbook on Mockito.

Libraries

svg_drawing_animation
SVG Drawing Animation