ShaderAnimatedControl 12.0.0
dotnet add package ShaderAnimatedControl --version 12.0.0
NuGet\Install-Package ShaderAnimatedControl -Version 12.0.0
<PackageReference Include="ShaderAnimatedControl" Version="12.0.0" />
<PackageVersion Include="ShaderAnimatedControl" Version="12.0.0" />
<PackageReference Include="ShaderAnimatedControl" />
paket add ShaderAnimatedControl --version 12.0.0
#r "nuget: ShaderAnimatedControl, 12.0.0"
#:package ShaderAnimatedControl@12.0.0
#addin nuget:?package=ShaderAnimatedControl&version=12.0.0
#tool nuget:?package=ShaderAnimatedControl&version=12.0.0
Lottie
A collection of animation controls for Avalonia including Lottie animation player and reusable base controls for custom animations.
Packages
| Package | NuGet | Downloads | Description |
|---|---|---|---|
| Lottie | An lottie animation player control for Avalonia. | ||
| AnimationControl | Reusable animation control base class for Avalonia applications. | ||
| CompositionAnimatedControl | Reusable composition-backed Skia control for static and animated rendering in Avalonia. | ||
| ShaderAnimatedControl | Reusable Skia shader-based animated control for Avalonia. |
Documentation
Project documentation is published with Lunet at wieslawsoltes.github.io/Lottie.
To build the site locally:
./build-docs.sh
To preview the site with Lunet watch mode:
./serve-docs.sh
Controls
Lottie Control
A lottie animation player control for Avalonia.
Installation:
dotnet add package Lottie
Basic Usage:
<Lottie Path="/Assets/LottieLogo1.json" />
AnimationControl
A reusable base class for creating custom animation controls in Avalonia. This control provides a simple animation frame loop that you can override to create custom animations.
Installation:
dotnet add package AnimationControl
Basic Usage:
public class MyAnimationControl : AnimationControl
{
protected override void OnAnimationFrame(TimeSpan now, TimeSpan last)
{
// Your animation logic here
// The control will automatically invalidate and request the next frame
var deltaTime = now - last;
// Update your animation state based on deltaTime
}
public override void Render(DrawingContext context)
{
base.Render(context);
// Your custom rendering logic here
}
}
Key Features:
- Automatic animation frame loop when attached to visual tree
- Override
OnAnimationFrame(TimeSpan now, TimeSpan last)for animation logic - Automatic visual invalidation after each frame
- Lightweight base for simple custom animations
CompositionAnimatedControl
A reusable base control for Skia rendering with optional animation using Avalonia's composition layer. It is override-first: subclass it and override a small set of virtual methods.
Installation:
dotnet add package CompositionAnimatedControl
Mode 1: Animated rendering (time-based or per-frame update)
You can animate by normalizing elapsed time into a loop, or by updating your state every frame and rendering using that state.
Example 1: simple time-based animation (used in demo tabs)
public sealed class SimpleTimelineControl : CompositionAnimatedControl
{
protected override Size OnGetSourceSize() => new Size(300, 200);
protected override NormalizeResult OnNormalizeElapsed(TimeSpan elapsed)
{
var loop = TimeSpan.FromSeconds(2);
if (loop <= TimeSpan.Zero) return new NormalizeResult(elapsed, false);
var remainder = TimeSpan.FromTicks(elapsed.Ticks % loop.Ticks);
var looped = elapsed >= loop;
return new NormalizeResult(remainder, looped);
}
protected override void OnRender(SKCanvas canvas, Rect rect, TimeSpan t, bool running)
{
canvas.Clear(SKColors.White);
var progress = (float)(t.TotalSeconds / 2.0);
var x = (float)(rect.X + rect.Width * progress);
using var paint = new SKPaint { Color = SKColors.CornflowerBlue, IsAntialias = true };
canvas.DrawCircle(x, (float)rect.Center.Y, 20, paint);
}
}
Example 2: bouncing ball with per-frame update and stretch-respecting drawing.
public sealed class BouncingBallControl : CompositionAnimatedControl
{
private const float LogicalWidth = 300f;
private const float LogicalHeight = 200f;
private const float Radius = 18f;
private SKPoint _position = new(40, 40);
private SKPoint _velocity = new(120f, 90f);
protected override Size OnGetSourceSize() => new Size(LogicalWidth, LogicalHeight);
protected override NormalizeResult OnNormalizeElapsed(TimeSpan ts) => new NormalizeResult(ts, false);
protected override void OnUpdate(TimeSpan delta)
{
var dt = (float)delta.TotalSeconds;
_position.X += _velocity.X * dt;
_position.Y += _velocity.Y * dt;
if (_position.X - Radius < 0) { _position.X = Radius; _velocity.X = Math.Abs(_velocity.X); }
else if (_position.X + Radius > LogicalWidth) { _position.X = LogicalWidth - Radius; _velocity.X = -Math.Abs(_velocity.X); }
if (_position.Y - Radius < 0) { _position.Y = Radius; _velocity.Y = Math.Abs(_velocity.Y); }
else if (_position.Y + Radius > LogicalHeight) { _position.Y = LogicalHeight - Radius; _velocity.Y = -Math.Abs(_velocity.Y); }
}
protected override void OnRender(SKCanvas canvas, Rect rect, TimeSpan _, bool __)
{
canvas.Clear(SKColors.White);
var scaleX = (float)(rect.Width / LogicalWidth);
var scaleY = (float)(rect.Height / LogicalHeight);
var cx = (float)rect.X + _position.X * scaleX;
var cy = (float)rect.Y + _position.Y * scaleY;
var r = Radius * Math.Min(scaleX, scaleY);
using var ball = new SKPaint { Color = SKColors.CornflowerBlue, IsAntialias = true };
canvas.DrawCircle(cx, cy, r, ball);
}
}
// Start/Stop animation from code-behind or view-model command
// myControl.Start();
// myControl.Stop();
Key virtuals:
OnGetSourceSize: logical content size used for layout and stretch.OnNormalizeElapsed: returns aNormalizeResultwhich maps elapsed time to a single loop and indicates loop completion (enables repeat counting).OnRender: draw into the providedSKCanvaswithinrect.OnUpdate: per-frame updates driven by the composition scheduler.Start()/Stop()control the animation loop;RepeatCountsets the number of loops (useCompositionAnimatedControl.Infinityfor endless).
Events:
Started,Stopped,DisposedUpdate(TimeSpan delta)
Mode 2: Static rendering with invalidation
For static content, omit Start() and call Redraw() when you need to refresh after state changes.
public sealed class StaticRedrawControl : CompositionAnimatedControl
{
private SKColor _color = SKColors.DarkSlateGray;
protected override Size OnGetSourceSize() => new Size(200, 100);
protected override NormalizeResult OnNormalizeElapsed(TimeSpan ts) => new NormalizeResult(TimeSpan.Zero, false);
protected override void OnRender(SKCanvas canvas, Rect rect, TimeSpan _, bool __)
{
canvas.Clear(SKColors.White);
using var paint = new SKPaint { Color = _color, IsAntialias = true };
canvas.DrawRect((float)rect.X + 20, (float)rect.Y + 20, (float)rect.Width - 40, (float)rect.Height - 40, paint);
}
public void Toggle()
{
_color = _color == SKColors.DarkSlateGray ? SKColors.OrangeRed : SKColors.DarkSlateGray;
Redraw();
}
}
Notes:
Redraw()issues a single render pass without starting the animation scheduler.StretchandStretchDirectionare supported in both modes.
ShaderAnimatedControl
A reusable control for rendering animated Skia shaders in Avalonia. This control loads and executes SKSL (Skia Shading Language) shaders with animation support.
Installation:
dotnet add package ShaderAnimatedControl
Basic Usage:
<ShaderAnimatedControl
ShaderUri="/Assets/MyShader.sksl"
ShaderWidth="512"
ShaderHeight="512"
IsShaderFillCanvas="False" />
// Handle the Draw event for custom shader parameter binding
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
myShaderControl.Draw += OnShaderDraw;
}
private void OnShaderDraw(object? sender, DrawEventArgs e)
{
if (e.Effect == null || e.ErrorText != null)
return;
// Create shader with custom parameters
var time = (float)e.EffectiveElapsed.TotalSeconds;
var resolution = new SKPoint((float)e.ShaderWidth, (float)e.ShaderHeight);
using var shader = e.Effect.ToShader(
new SKRuntimeEffectUniforms(e.Effect)
{
["iTime"] = time,
["iResolution"] = resolution
});
using var paint = new SKPaint { Shader = shader };
e.Canvas.DrawRect(e.DestRect, paint);
}
}
Key Features:
- Load SKSL shaders from assets or URIs
- Automatic animation loop with time-based parameters
- Configurable shader dimensions
- Fill canvas or maintain aspect ratio modes
- Draw event for custom shader parameter binding
- Built on top of CompositionAnimatedControl
Properties:
ShaderUri: URI to the SKSL shader fileShaderWidth/ShaderHeight: Logical shader dimensionsIsShaderFillCanvas: Whether to fill the entire canvas or maintain aspect ratio
Links
License
Lottie is licensed under the MIT license.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Avalonia (>= 12.0.0)
- Avalonia.Skia (>= 12.0.0)
- CompositionAnimatedControl (>= 12.0.0)
- SkiaSharp (>= 3.119.3-preview.1.1)
-
net8.0
- Avalonia (>= 12.0.0)
- Avalonia.Skia (>= 12.0.0)
- CompositionAnimatedControl (>= 12.0.0)
- SkiaSharp (>= 3.119.3-preview.1.1)
-
net9.0
- Avalonia (>= 12.0.0)
- Avalonia.Skia (>= 12.0.0)
- CompositionAnimatedControl (>= 12.0.0)
- SkiaSharp (>= 3.119.3-preview.1.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 12.0.0 | 0 | 4/12/2026 |
| 12.0.0-rc2 | 43 | 4/2/2026 |
| 11.3.0.2 | 137 | 8/16/2025 |