A Flutter library for gradually painting SVG path objects on canvas
drawing_animation
A Flutter library for gradually painting SVG path objects on canvas (drawing line animation).
The rendering library exposes a central widget called AnimatedDrawing
which allows to render SVG paths (via AnimatedDrawing.svg
) or Flutter Path objects (via AnimatedDrawing.paths
) in a drawing like fashion.
Getting Started - AnimatedDrawing.svg
To get started with the drawing_animation
package you need a valid Svg file.
Currently only simple path elements without transforms are supported (see Supported SVG specifications)
- Add dependency in your
pubspec.yaml
dependencies:
drawing_animation: ^0.1.1
- Add the SVG asset
assets:
- assets/my_drawing.svg
-
Use the widget
An AnimatedDrawing widget can be initiated in two ways:
-
Simplified - without animation controller (See Example_01)
By default every animation repeats infinitely. For running an animation only once you can use a callback to set
run
to false after the first animation cycle completed (see fieldonFinish
).AnimatedDrawing.svg( "assets/my_drawing.svg", run: this.run, duration: new Duration(seconds: 3), onFinish: () => setState(() { this.run = false; }), )
-
Standard - with animation controller (See Example_02)
The simplified version will be sufficient in most of the use cases. If you wish to controll the animation furthermore or you want to syncronize it with other existing animations, you might consider using an custom animation controller:
AnimatedDrawing.svg( "assets/test.svg", controller: this.controller, )
-
-
Check out examples in the
examples
folder. It seems that antialising for the Paint/Canvas is switched off when using debug mode. For pretty results useflutter run --release
.
Getting Started - AnimatedDrawing.paths (still experimental)
By providing Path objects directly to the widget, elements can be changed dynamically, even during the animation. The internal data structure is rebuild every time the state changes, therefore the animation performance might suffer if the amount of elements in paths
is very high (see Limitations). More examples will be provided soon (for now see Example_01 and Example_04).
AnimatedDrawing.paths(
[
///Path objects
],
paints:[
///Paint objects (optional), specifies a [Paint] object for each [Path] element in `paths`.
],
run: this.run,
duration: new Duration(seconds: 3),
onFinish: () => setState(() {
this.run = false;
}),
)
Current limitations:
As stated, for every state change of the widget, the internal data structure for the path objects is rebuilt. When the amount of provided path objects is high and a custom animationOrder
is defined (which triggers a sorting operation over the data structure) it can result in lags. This becomes especially apparent when the state is rebuild at 60fps by another animation (e.g. rotating the path objects at every frame). Any suggestions on how to elegantly solve this are very welcome :-)
Supported SVG specifications
- Only path elements (
<path d="M3m1....">
) are supported for now. I'm currently considering to add flutter_svg as dependency for more complete SVG parsing. - Attributes
- stroke, only Hex-Color without alpha for now
- stroke-width
- style, but only the both fields above
- No transforms are supported, yet.
How can I use my own SVG files?
A lot of tools can convert existing SVG files to the supported format.
For example with Inkscape:
- Select all objects and ungroup till there is no group left (Ctrl+U)
- Convert selection to paths:
Path>>Object to Path
and hit save - Afterwards remove transforms with svgo or the webversion svgomg.
- Now it should work, if not feel free to write an issue!
Todo
- Better test coverage
- Improve SVG parsing capabilities
- Circles, rect etc.
- Better color parsing incl. alpha for hex code and RGB(A)
- Subsitute SVG parsing logic with an mature parsering library as flutter_svg
- Provide a way to overwrite color/brush etc. for
AnimatedDrawing.svg
- maybe also overpaints
object? - Define a [PathOrder] which maintains each Path and only sorts them relative to each other
- Improve performance AnimatedDrawing.paths, for every rebuild all provided paths have to be parsed again. Is there a way to check Path-Objects for equality like Keys for widget? Idea: implementing a proxy for Path which creates a unique hash when command evoked
- Showcase: write "drawing_animation" in different ways + 3 cirlcles + color it and one gif and put it at the top
- Showcase: Create fractals with L-Systems
- AnimatedDrawing.paths:
- Provide some kind of fixed boundingBox since Paths and the overall bounding box can dynamically change (e.g. rotating circle pulses in size)
- Also custom viewport