Update
This commit is contained in:
Родитель
fd4c6ff283
Коммит
3b2b6e22ef
|
@ -108,6 +108,70 @@ public class Lottie : Control
|
||||||
_baseUri = serviceProvider.GetContextBaseUri();
|
_baseUri = serviceProvider.GetContextBaseUri();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override void OnLoaded()
|
||||||
|
{
|
||||||
|
base.OnLoaded();
|
||||||
|
|
||||||
|
var elemVisual = ElementComposition.GetElementVisual(this);
|
||||||
|
var compositor = elemVisual?.Compositor;
|
||||||
|
if (compositor is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_customVisual = compositor.CreateCustomVisual(new LottieCompositionCustomVisualHandler());
|
||||||
|
ElementComposition.SetElementChildVisual(this, _customVisual);
|
||||||
|
|
||||||
|
LayoutUpdated += OnLayoutUpdated;
|
||||||
|
|
||||||
|
if (_preloadPath is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisposeImpl();
|
||||||
|
Load(_preloadPath);
|
||||||
|
|
||||||
|
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
|
||||||
|
_customVisual.SendHandlerMessage(
|
||||||
|
new LottiePayload(
|
||||||
|
LottieCommand.Update,
|
||||||
|
_animation,
|
||||||
|
Stretch,
|
||||||
|
StretchDirection));
|
||||||
|
|
||||||
|
Start();
|
||||||
|
_preloadPath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUnloaded()
|
||||||
|
{
|
||||||
|
base.OnUnloaded();
|
||||||
|
|
||||||
|
LayoutUpdated -= OnLayoutUpdated;
|
||||||
|
|
||||||
|
Stop();
|
||||||
|
DisposeImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLayoutUpdated(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_customVisual == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
|
||||||
|
_customVisual.SendHandlerMessage(
|
||||||
|
new LottiePayload(
|
||||||
|
LottieCommand.Update,
|
||||||
|
_animation,
|
||||||
|
Stretch,
|
||||||
|
StretchDirection));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
{
|
{
|
||||||
if (_animation == null)
|
if (_animation == null)
|
||||||
|
@ -122,52 +186,6 @@ public class Lottie : Control
|
||||||
return Stretch.CalculateSize(availableSize, sourceSize, StretchDirection);
|
return Stretch.CalculateSize(availableSize, sourceSize, StretchDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnLoaded()
|
|
||||||
{
|
|
||||||
var elemVisual = ElementComposition.GetElementVisual(this);
|
|
||||||
var compositor = elemVisual?.Compositor;
|
|
||||||
if (compositor is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_customVisual = compositor.CreateCustomVisual(new LottieCustomVisualHandler());
|
|
||||||
ElementComposition.SetElementChildVisual(this, _customVisual);
|
|
||||||
LayoutUpdated += OnLayoutUpdated;
|
|
||||||
|
|
||||||
base.OnLoaded();
|
|
||||||
|
|
||||||
if (_preloadPath is null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DisposeImpl();
|
|
||||||
Load(_preloadPath);
|
|
||||||
|
|
||||||
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
|
|
||||||
_customVisual.SendHandlerMessage(new LottieCustomVisualHandler.Payload(
|
|
||||||
LottieCustomVisualHandler.Command.Update,
|
|
||||||
_animation,
|
|
||||||
Stretch,
|
|
||||||
StretchDirection));
|
|
||||||
|
|
||||||
Start();
|
|
||||||
_preloadPath = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnLayoutUpdated(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (_customVisual == null) return;
|
|
||||||
_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
|
|
||||||
_customVisual.SendHandlerMessage(
|
|
||||||
new LottieCustomVisualHandler.Payload(
|
|
||||||
LottieCustomVisualHandler.Command.Update,
|
|
||||||
_animation,
|
|
||||||
Stretch,
|
|
||||||
StretchDirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
{
|
{
|
||||||
if (_animation == null)
|
if (_animation == null)
|
||||||
|
@ -212,12 +230,6 @@ public class Lottie : Control
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Stop()
|
|
||||||
{
|
|
||||||
_customVisual?.SendHandlerMessage(
|
|
||||||
new LottieCustomVisualHandler.Payload(LottieCustomVisualHandler.Command.Stop));
|
|
||||||
}
|
|
||||||
|
|
||||||
private SkiaSharp.Skottie.Animation? Load(Stream stream)
|
private SkiaSharp.Skottie.Animation? Load(Stream stream)
|
||||||
{
|
{
|
||||||
using var managedStream = new SKManagedStream(stream);
|
using var managedStream = new SKManagedStream(stream);
|
||||||
|
@ -227,12 +239,13 @@ public class Lottie : Control
|
||||||
|
|
||||||
Logger
|
Logger
|
||||||
.TryGet(LogEventLevel.Information, LogArea.Control)?
|
.TryGet(LogEventLevel.Information, LogArea.Control)?
|
||||||
.Log(this,
|
.Log(this, $"Version: {animation.Version} Duration: {animation.Duration} Fps:{animation.Fps} InPoint: {animation.InPoint} OutPoint: {animation.OutPoint}");
|
||||||
$"Version: {animation.Version} Duration: {animation.Duration} Fps:{animation.Fps} InPoint: {animation.InPoint} OutPoint: {animation.OutPoint}");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, "Failed to load animation.");
|
Logger
|
||||||
|
.TryGet(LogEventLevel.Warning, LogArea.Control)?
|
||||||
|
.Log(this, "Failed to load animation.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return animation;
|
return animation;
|
||||||
|
@ -240,7 +253,9 @@ public class Lottie : Control
|
||||||
|
|
||||||
private SkiaSharp.Skottie.Animation? Load(string path, Uri? baseUri)
|
private SkiaSharp.Skottie.Animation? Load(string path, Uri? baseUri)
|
||||||
{
|
{
|
||||||
var uri = path.StartsWith("/") ? new Uri(path, UriKind.Relative) : new Uri(path, UriKind.RelativeOrAbsolute);
|
var uri = path.StartsWith("/")
|
||||||
|
? new Uri(path, UriKind.Relative)
|
||||||
|
: new Uri(path, UriKind.RelativeOrAbsolute);
|
||||||
if (uri.IsAbsoluteUri && uri.IsFile)
|
if (uri.IsAbsoluteUri && uri.IsFile)
|
||||||
{
|
{
|
||||||
using var fileStream = File.OpenRead(uri.LocalPath);
|
using var fileStream = File.OpenRead(uri.LocalPath);
|
||||||
|
@ -264,7 +279,6 @@ public class Lottie : Control
|
||||||
if (path is null)
|
if (path is null)
|
||||||
{
|
{
|
||||||
DisposeImpl();
|
DisposeImpl();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +288,7 @@ public class Lottie : Control
|
||||||
{
|
{
|
||||||
_repeatCount = RepeatCount;
|
_repeatCount = RepeatCount;
|
||||||
_animation = Load(path, _baseUri);
|
_animation = Load(path, _baseUri);
|
||||||
|
|
||||||
if (_animation is null)
|
if (_animation is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -286,21 +301,31 @@ public class Lottie : Control
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.TryGet(LogEventLevel.Warning, LogArea.Control)?.Log(this, "Failed to load animation: " + e);
|
Logger
|
||||||
|
.TryGet(LogEventLevel.Warning, LogArea.Control)?
|
||||||
|
.Log(this, "Failed to load animation: " + e);
|
||||||
_animation = null;
|
_animation = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisposeImpl()
|
|
||||||
{
|
|
||||||
_customVisual?.SendHandlerMessage(
|
|
||||||
new LottieCustomVisualHandler.Payload(LottieCustomVisualHandler.Command.Dispose));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
_customVisual?.SendHandlerMessage(new LottieCustomVisualHandler.Payload(LottieCustomVisualHandler.Command.Start,
|
_customVisual?.SendHandlerMessage(
|
||||||
_animation,
|
new LottiePayload(
|
||||||
Stretch, StretchDirection, _repeatCount));
|
LottieCommand.Start,
|
||||||
|
_animation,
|
||||||
|
Stretch,
|
||||||
|
StretchDirection,
|
||||||
|
_repeatCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Stop()
|
||||||
|
{
|
||||||
|
_customVisual?.SendHandlerMessage(new LottiePayload(LottieCommand.Stop));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeImpl()
|
||||||
|
{
|
||||||
|
_customVisual?.SendHandlerMessage(new LottiePayload(LottieCommand.Dispose));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Avalonia.Skia.Lottie;
|
||||||
|
|
||||||
|
internal enum LottieCommand
|
||||||
|
{
|
||||||
|
Start,
|
||||||
|
Stop,
|
||||||
|
Update,
|
||||||
|
Dispose
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ using SkiaSharp;
|
||||||
|
|
||||||
namespace Avalonia.Skia.Lottie;
|
namespace Avalonia.Skia.Lottie;
|
||||||
|
|
||||||
internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
internal class LottieCompositionCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
{
|
{
|
||||||
private TimeSpan _primaryTimeElapsed, _animationElapsed;
|
private TimeSpan _primaryTimeElapsed, _animationElapsed;
|
||||||
private TimeSpan? _lastServerTime;
|
private TimeSpan? _lastServerTime;
|
||||||
|
@ -19,35 +19,24 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
private int _repeatCount;
|
private int _repeatCount;
|
||||||
private int _count;
|
private int _count;
|
||||||
|
|
||||||
public enum Command
|
|
||||||
{
|
|
||||||
Start,
|
|
||||||
Stop,
|
|
||||||
Update,
|
|
||||||
Dispose
|
|
||||||
}
|
|
||||||
|
|
||||||
public record struct Payload(
|
|
||||||
Command Command,
|
|
||||||
SkiaSharp.Skottie.Animation? Animation = null,
|
|
||||||
Stretch? Stretch = null,
|
|
||||||
StretchDirection? StretchDirection = null,
|
|
||||||
int? RepeatCount = null);
|
|
||||||
|
|
||||||
public override void OnMessage(object message)
|
public override void OnMessage(object message)
|
||||||
{
|
{
|
||||||
if (message is not Payload msg) return;
|
if (message is not LottiePayload msg)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
case
|
case
|
||||||
{
|
{
|
||||||
Command: Command.Start,
|
LottieCommand: LottieCommand.Start,
|
||||||
Animation: { } an,
|
Animation: { } an,
|
||||||
Stretch: { } st,
|
Stretch: { } st,
|
||||||
StretchDirection: { } sd,
|
StretchDirection: { } sd,
|
||||||
RepeatCount: { } rp
|
RepeatCount: { } rp
|
||||||
}:
|
}:
|
||||||
|
{
|
||||||
_running = true;
|
_running = true;
|
||||||
_lastServerTime = null;
|
_lastServerTime = null;
|
||||||
_stretch = st;
|
_stretch = st;
|
||||||
|
@ -58,24 +47,37 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
_animationElapsed = TimeSpan.Zero;
|
_animationElapsed = TimeSpan.Zero;
|
||||||
RegisterForNextAnimationFrameUpdate();
|
RegisterForNextAnimationFrameUpdate();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case
|
case
|
||||||
{
|
{
|
||||||
Command: Command.Update,
|
LottieCommand: LottieCommand.Update,
|
||||||
Stretch: { } st,
|
Stretch: { } st,
|
||||||
StretchDirection: { } sd
|
StretchDirection: { } sd
|
||||||
}:
|
}:
|
||||||
|
{
|
||||||
_stretch = st;
|
_stretch = st;
|
||||||
_stretchDirection = sd;
|
_stretchDirection = sd;
|
||||||
RegisterForNextAnimationFrameUpdate();
|
RegisterForNextAnimationFrameUpdate();
|
||||||
break;
|
break;
|
||||||
case {Command: Command.Stop}:
|
}
|
||||||
|
case
|
||||||
|
{
|
||||||
|
LottieCommand: LottieCommand.Stop
|
||||||
|
}:
|
||||||
|
{
|
||||||
_running = false;
|
_running = false;
|
||||||
_animationElapsed = TimeSpan.Zero;
|
_animationElapsed = TimeSpan.Zero;
|
||||||
_count = 0;
|
_count = 0;
|
||||||
break;
|
break;
|
||||||
case {Command: Command.Dispose}:
|
}
|
||||||
|
case
|
||||||
|
{
|
||||||
|
LottieCommand: LottieCommand.Dispose
|
||||||
|
}:
|
||||||
|
{
|
||||||
DisposeImpl();
|
DisposeImpl();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +97,6 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
RegisterForNextAnimationFrameUpdate();
|
RegisterForNextAnimationFrameUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void DisposeImpl()
|
private void DisposeImpl()
|
||||||
{
|
{
|
||||||
lock (_sync)
|
lock (_sync)
|
||||||
|
@ -128,7 +129,7 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
return frameTime;
|
return frameTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SkottieDraw(SKCanvas canvas)
|
private void Draw(SKCanvas canvas)
|
||||||
{
|
{
|
||||||
var animation = _animation;
|
var animation = _animation;
|
||||||
if (animation is null)
|
if (animation is null)
|
||||||
|
@ -158,14 +159,8 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
var dst = new SKRect(0, 0, animation.Size.Width, animation.Size.Height);
|
var dst = new SKRect(0, 0, animation.Size.Width, animation.Size.Height);
|
||||||
|
|
||||||
animation.SeekFrameTime(t, ic);
|
animation.SeekFrameTime(t, ic);
|
||||||
|
|
||||||
// Debug.WriteLine($"dst: {dst}, ic.Bounds: {ic.Bounds}");
|
|
||||||
|
|
||||||
canvas.Save();
|
canvas.Save();
|
||||||
|
|
||||||
animation.Render(canvas, dst);
|
animation.Render(canvas, dst);
|
||||||
// canvas.DrawRect(ic.Bounds, new SKPaint { Color = SKColors.Magenta, Style = SKPaintStyle.Stroke, StrokeWidth = 1 });
|
|
||||||
|
|
||||||
canvas.Restore();
|
canvas.Restore();
|
||||||
|
|
||||||
ic.Reset();
|
ic.Reset();
|
||||||
|
@ -187,8 +182,12 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
_lastServerTime = CompositionNow;
|
_lastServerTime = CompositionNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_animation is not { } an
|
||||||
if (_animation is not { } an || _stretch is not { } st || _stretchDirection is not { } sd) return;
|
|| _stretch is not { } st
|
||||||
|
|| _stretchDirection is not { } sd)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>();
|
var leaseFeature = context.TryGetFeature<ISkiaSharpApiLeaseFeature>();
|
||||||
|
@ -231,7 +230,7 @@ internal class LottieCustomVisualHandler : CompositionCustomVisualHandler
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SkottieDraw(canvas);
|
Draw(canvas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
|
namespace Avalonia.Skia.Lottie;
|
||||||
|
|
||||||
|
internal record struct LottiePayload(
|
||||||
|
LottieCommand LottieCommand,
|
||||||
|
SkiaSharp.Skottie.Animation? Animation = null,
|
||||||
|
Stretch? Stretch = null,
|
||||||
|
StretchDirection? StretchDirection = null,
|
||||||
|
int? RepeatCount = null);
|
Загрузка…
Ссылка в новой задаче