From 35d0d5a7b1ebc4fb8b62aaf43d392184f7493218 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Sat, 17 Feb 2024 15:07:26 +0800 Subject: [PATCH] feat: use animator instead of transition. --- .../NumberDisplayer/NumberDisplayer.cs | 76 ++++++++++++++----- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/src/Ursa/Controls/NumberDisplayer/NumberDisplayer.cs b/src/Ursa/Controls/NumberDisplayer/NumberDisplayer.cs index 181e955..946d58e 100644 --- a/src/Ursa/Controls/NumberDisplayer/NumberDisplayer.cs +++ b/src/Ursa/Controls/NumberDisplayer/NumberDisplayer.cs @@ -3,6 +3,7 @@ using Avalonia.Animation; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Data; +using Avalonia.Styling; namespace Ursa.Controls; @@ -11,6 +12,7 @@ public abstract class NumberDisplayerBase : TemplatedControl public static readonly DirectProperty InternalTextProperty = AvaloniaProperty.RegisterDirect( nameof(InternalText), o => o.InternalText, (o, v) => o.InternalText = v); private string _internalText; + public string InternalText { get => _internalText; @@ -38,6 +40,9 @@ public abstract class NumberDisplayerBase : TemplatedControl public abstract class NumberDisplayer: NumberDisplayerBase { + private Animation? _animation; + private CancellationTokenSource _cts = new (); + public static readonly StyledProperty ValueProperty = AvaloniaProperty.Register, T?>( nameof(Value), defaultBindingMode:BindingMode.TwoWay); @@ -60,7 +65,7 @@ public abstract class NumberDisplayer: NumberDisplayerBase { ValueProperty.Changed.AddClassHandler, T?>((item, args) => { - item.InternalValue = args.NewValue.Value; + item.OnValueChanged(args.OldValue.Value, args.NewValue.Value); }); InternalValueProperty.Changed.AddClassHandler, T?>((item, args) => { @@ -68,29 +73,62 @@ public abstract class NumberDisplayer: NumberDisplayerBase }); DurationProperty.Changed.AddClassHandler, TimeSpan>((item, args) =>item.OnDurationChanged(args)); } - - private void OnDurationChanged(AvaloniaPropertyChangedEventArgs args) + + protected override void OnInitialized() { - this.Transitions ??= new Transitions(); - this.Transitions?.Clear(); - this.Transitions?.Add(GetTransition(args.NewValue.Value)); + base.OnInitialized(); + _animation = new Animation(); + _animation.Duration = Duration; + _animation.FillMode = FillMode.Forward; + _animation.Children.Add(new KeyFrame() + { + Cue = new Cue(0.0), + Setters = { new Setter{Property = InternalValueProperty } } + }); + _animation.Children.Add(new KeyFrame() + { + Cue = new Cue(1.0), + Setters = { new Setter{Property = InternalValueProperty } } + }); + Animation.SetAnimator(_animation.Children[0].Setters[0], GetAnimator()); } - protected abstract ITransition GetTransition(TimeSpan duration); + private void OnDurationChanged(AvaloniaPropertyChangedEventArgs args) + { + if (_animation is null) return; + _animation.Duration = args.NewValue.Value; + } + + protected virtual void OnValueChanged(T? oldValue, T? newValue) + { + _cts.Cancel(); + _cts = new CancellationTokenSource(); + (_animation?.Children[0].Setters[0] as Setter)!.Value = oldValue; + (_animation?.Children[1].Setters[0] as Setter)!.Value = newValue; + _animation?.RunAsync(this, _cts.Token); + } + + protected abstract InterpolatingAnimator GetAnimator(); + protected abstract string GetString(T? value); } public class Int32Displayer : NumberDisplayer { protected override Type StyleKeyOverride { get; } = typeof(NumberDisplayerBase); + - protected override ITransition GetTransition(TimeSpan duration) + protected override InterpolatingAnimator GetAnimator() { - return new IntegerTransition() + return new IntAnimator(); + } + + private class IntAnimator : InterpolatingAnimator + { + public override int Interpolate(double progress, int oldValue, int newValue) { - Property = InternalValueProperty, - Duration = duration - }; + return oldValue + (int)((newValue - oldValue) * progress); + } } protected override string GetString(int value) @@ -103,13 +141,17 @@ public class DoubleDisplayer : NumberDisplayer { protected override Type StyleKeyOverride { get; } = typeof(NumberDisplayerBase); - protected override ITransition GetTransition(TimeSpan duration) + protected override InterpolatingAnimator GetAnimator() { - return new DoubleTransition() + return new DoubleAnimator(); + } + + private class DoubleAnimator : InterpolatingAnimator + { + public override double Interpolate(double progress, double oldValue, double newValue) { - Property = InternalValueProperty, - Duration = duration - }; + return oldValue + (newValue - oldValue) * progress; + } } protected override string GetString(double value)