feat:Implements subtle animations for the NavMenu in a non-intrusive way.

This commit is contained in:
望尘空忧
2025-08-09 23:00:15 +08:00
parent 4a4e36d50d
commit bb7873ef66
2 changed files with 89 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Styling;
using Avalonia.Threading;
using Avalonia.VisualTree;
namespace Ursa.Controls;
public class WHAnimationHelper(Control control, AvaloniaProperty property)
{
private CancellationTokenSource? _cancellationTokenSource;
~WHAnimationHelper()
{
_cancellationTokenSource?.Dispose();
}
public void Stop()
{
control.PropertyChanged -= AnimationTargetOnPropertyChanged;
}
public void Start()
{
control.PropertyChanged += AnimationTargetOnPropertyChanged;
}
private void AnimationTargetOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (sender as Control != control ||
e.Property != property ||
control.IsLoaded is false ||
control.IsVisible is false) return;
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_cancellationTokenSource = new CancellationTokenSource();
var oldValue = control.DesiredSize;
control.UpdateLayout();
var newValue = control.DesiredSize;
newValue = newValue.WithWidth(newValue.Width + 20);
control.InvalidateArrange();
var animation = CreateAnimation(oldValue, newValue);
animation.RunAsync(control, _cancellationTokenSource.Token);
}
protected virtual Animation CreateAnimation(Size oldValue, Size newValue)
{
return new Animation
{
Duration = TimeSpan.FromMilliseconds(300),
Easing = new CubicEaseInOut(),
FillMode = FillMode.None,
Children =
{
new KeyFrame
{
Cue = new Cue(0.0),
Setters =
{
new Setter(Layoutable.WidthProperty, oldValue.Width)
}
},
new KeyFrame
{
Cue = new Cue(1.0),
Setters =
{
new Setter(Layoutable.WidthProperty, newValue.Width)
}
}
}
};
}
}