Creating a simple animation
Table of contents
Frame
s and Transition
s
Animations in VectSharp are created by defining a number of “keyframes” that determine the status of the animation at a specific time. Each frame has a duration (i.e., the amount of time for which it will be displayed), and between consecutive frames a “transition” happens, with its own duration.
The following code shows an example of how to create an animation with two key frames:
The final parameter in the Animation
constructor (the linearisation resolution) is used when morphing a path into a different path; this is not the case here, so any value will work. For more information on this, see Linearising paths.
The result should be similar to the following (the progress bar at the top has been added for the sake of this example, and will not be present in your output file):
Tagging objects
As you will notice, the animation does not move smoothly between the two frames, but rather changes “abruptly” upon the end of the transition. This is because at this stage VectSharp does not have any information on what should be “morphed” between one frame and the next one; we can provide this information by adding a tag
while drawing the circle:
When creating the animation, VectSharp will identify elements with the same tag
, and automatically morph them during the transition between consecutive frames. The resulting animation should be similar to the following (again, the progress bar has just been added for clarity and will not be present in your output file):
As you will notice, the circle now moves smoothly between the starting and end position, changing colour in the process.
Most plot elements can be morphed into other elements of the same kind:
- Rectangles can be morphed into other rectangles (attributes such as size, fill colour, stroke colour, line width etc. will morph continuously).
- Paths can be morphed into other paths. If the start and end path have the same number of figures (closed contours), and each figure in the start path has the same number and type of segments as the corresponding figure in the end path, the points will simply be interpolated; otherwise the paths will have to be linearised to create this correspondence (this is where the “linearisation resolution” parameter of the
Animation
constructor comes into play). - Text can be morphed into other text. Note that attributes such as the position or the fill colour will change smoothly between the starting and end position, while other things (such as the text itself) will change abruptly. If you wish to morph text, you should draw it as a path (see Morphing text).
- Transforms can be morphed into other transforms. Note that depending on the kind of transform, the transition may take “unexpected” paths (e.g., a rotation starting at angle 0 and ending at angle $\frac{3}{2}\pi$ may actually go in the opposite direction as the one you would expect - if this is a problem, you should add more key frames so that every rotation has to be animated by less than $\pi$).
- When drawing objects, brushes can be morphed into other brushes, both of the same kind and of a different kind. For example, a
SolidColourBrush
can be morphed into aLinearGradientBrush
or into aRadialGradientBrush
. However, because of limitations in SVG animations, morphing aLinarGradientBrush
into aRadialGradientBrush
may produce unexpected results - if you need this kind of effect, you should save the animation as an animated GIF or PNG, or as an animated SVG with frames. - Filters can be morphed into filters of the same kind (e.g., a
GaussianBlurFilter
can be morphed into anotherGaussianBlurFilter
with a different standard deviation).
In most instances, you just have to make sure to use the same tag
for objects that need to be morphed into one another, and the library will take care of performing the right interpolation. Note that for complex paths this might take a while, so you may want to “help” it, e.g. by splitting a single complex path into smaller elements (more on this in the Morphing text page).
Saving the animation in different formats
VectSharp can save an animation in various different formats.
Animated GIFs
Animated GIFs are one of the most established animated image formats, despite their limitations (maximum framerate of 50fps and 255 colours + 1 transparent colour for each frame). To create an animated GIF, you will need the VectSharp.Raster.ImageSharp NuGet package:
The SaveAsAnimatedGIF
method has three of overloads (one saving the image to a file, one saving the image to a Stream
and one saving it to an ImageSharp Image
object), and a number of optional parameters:
double scale
: the scale at which the raster image will be rendered.double frameRate
: the framerate of the animation, in frames per second (fps). The maximum value for this is 50, values higher than 50 will be capped at this value.double durationScaling
: this parameter is used to multiply the duration of the animation - for example, an animation that has a total duration of 10 seconds with adurationScaling
of2
will actually last 20 seconds.GifColorTableMode colorTableMode
: this parameter determines whether a different colour table is used for each frame (which produces bigger but better-looking files), or whether a single colour table is used for all frames (which produces smaller files).
Animated PNGs
Animated PNGs unfortunately are not as widely supported as GIFs, though they produce better-looking images (since there is no 256-colour restriction and full 8-bit alpha transparency can be used) and have a higher maximum framerate (90 fps). To create an animated PNG, you can use the VectSharp.Raster or VectSharp.Raster.ImageSharp NuGet packages (VectSharp.Raster is faster, but it has a native dependency; on the other hand, VectSharp.Raster.ImageSharp is slower and requires more RAM).
The SaveAsAnimatedPNG
method has two overloads, saving to a file or to a Stream
, and a few optional parameters:
double scale
: the scale at which the raster image will be rendered.double frameRate
: the framerate of the animation, in frames per second (fps). The maximum value for this is 90, values higher than 90 will be capped at this value.double durationScaling
: this parameter is used to multiply the duration of the animation - for example, an animation that has a total duration of 10 seconds with adurationScaling
of2
will actually last 20 seconds.InterframeCompression interframeCompression
: this parameter determines what kind of inter-frame compression is used. If this is set toInterframeCompression.None
, no inter-frame compression is used. If this is set toInterframeCompression.First
, frames are compressed by encoding only the difference between each frame and the first frame of the animation. If this is set toInterframeCompression.Previous
, frames are compressed by only encoding the difference between each frame and the previous frame. These settings have no effect on the appearance of the image, but only on the file size (None
produces the largest files, whilePrevious
produces the smallest). Note thatPrevious
requires all frames to be rendered in memory, which will increase RAM usage. Note also that if the animation has a transparent background, no compression can be performed, and this parameter is ignored.
Animated SVGs
Animated SVGs are supported by most major browsers, and can generally produce high-quality animations with small file sizes. However, there are a few small features that are not supported by animated SVGs (such as transitions between a LinearGradientBrush
and a RadialGradientBrush
). To create an animated SVG, you will need the VectSharp.SVG NuGet package:
The SaveAsAnimatedSVG
method has three overloads (saving to a file, to a Stream
or to an XmlDocument
) and a few optional parameters:
bool includeControls
: if this istrue
, javascript-based playback controls are included in the output file, which can be used to pause and change the position of the animation (as if it were a proper “video”). Otherwise, these controls are not included.double durationScaling
: this parameter is used to multiply the duration of the animation - for example, an animation that has a total duration of 10 seconds with adurationScaling
of2
will actually last 20 seconds.textOption
,linkDestinations
andfilterOption
: these parameters have the same function as for regular static SVG images.
Furthermore, the SaveAsAnimatedSVGWithFrames
method can be used to create an animated SVG that actually encodes every frame, instead of relying on SVG transitions (SMIL):
This produces larger files, but may work around some of the compatibility issues with certain features (such as transitions between LinearGradientBrush
es and RadialGradientBrush
es). This method also has three overloads saving to a file, to a Stream
or to an XmlDocument
, and the same optional parameters as the previous method, with the addition of the frameRate
parameter, which determines the frame rate of the animation in fps (no maximum value, but naturally the higher this is, the larger the output file will be).
Animated Canvas
When using VectSharp.Canvas to display graphics in an Avalonia application, it is also possible to create an animated canvas out of an Animation
object:
You can then place the AnimatedCanvas
object (which is a Control
) e.g. in a Window
or in a Viewbox
.
The PaintToAnimatedCanvas
method has a number of optional parameters:
double frameRate
: the framerate of the animation, in frames per second (fps). This determines how often the animated canvas is redrawn (invalidated).double durationScaling
: this parameter is used to multiply the duration of the animation - for example, an animation that has a total duration of 10 seconds with adurationScaling
of2
will actually last 20 seconds.textOption
andfilterOption
: these parameters have the same meaning as for normal static canvases.
The AnimatedCanvas
class also has some interesting properties:
int CurrentFrame
: gets/sets the current frame of the animation (between0
andFrameCount - 1
).int FrameCount
: gets the total number of frames in the animation.double FrameRate
: gets the framerate of the animation.bool IsPlaying
: can be get/set to determine whether the animation is playing or has been paused.
You can use these properties to control playback of the animation (e.g., you can set IsPlaying
to false and manually update the CurrentFrame
) or to implement something like animation controls.