Reworked animations

This commit is contained in:
ClemensFischer 2024-05-21 22:05:01 +02:00
parent 12b33c5376
commit 8708c7ffe6
9 changed files with 159 additions and 85 deletions

View file

@ -0,0 +1,59 @@
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
// Copyright © 2024 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System.Threading.Tasks;
using System;
using Avalonia.Controls;
using Avalonia.Animation;
using Avalonia.Styling;
using System.Xml.Linq;
namespace MapControl
{
public static class OpacityHelper
{
public static Task FadeIn(Control element)
{
var animation = new Animation
{
Duration = MapBase.ImageFadeDuration,
Children =
{
new KeyFrame
{
KeyTime = TimeSpan.Zero,
Setters = { new Setter(Visual.OpacityProperty, 0d) }
},
new KeyFrame
{
KeyTime = MapBase.ImageFadeDuration,
Setters = { new Setter(Visual.OpacityProperty, 1d) }
}
}
};
return animation.RunAsync(element);
}
public static async Task SwapOpacities(Control topElement, Control bottomElement)
{
var animation = new Animation
{
Duration = MapBase.ImageFadeDuration,
Children =
{
new KeyFrame
{
KeyTime = MapBase.ImageFadeDuration,
Setters = { new Setter(Visual.OpacityProperty, 1d) }
}
}
};
await animation.RunAsync(topElement);
bottomElement.Opacity = 0d;
}
}
}

View file

@ -2,35 +2,13 @@
// Copyright © 2024 Clemens Fischer // Copyright © 2024 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL) // Licensed under the Microsoft Public License (Ms-PL)
using Avalonia.Animation;
using Avalonia.Styling;
using System;
namespace MapControl namespace MapControl
{ {
public partial class Tile public partial class Tile
{ {
private void AnimateImageOpacity() private void AnimateImageOpacity()
{ {
var animation = new Animation _ = OpacityHelper.FadeIn(Image);
{
Duration = MapBase.ImageFadeDuration,
Children =
{
new KeyFrame
{
KeyTime = TimeSpan.Zero,
Setters = { new Setter(Visual.OpacityProperty, 0d) }
},
new KeyFrame
{
KeyTime = MapBase.ImageFadeDuration,
Setters = { new Setter(Visual.OpacityProperty, 1d) }
}
}
};
_ = animation.RunAsync(Image);
} }
} }
} }

View file

@ -17,19 +17,16 @@ using Windows.Foundation;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Animation;
using DispatcherTimer = Microsoft.UI.Dispatching.DispatcherQueueTimer; using DispatcherTimer = Microsoft.UI.Dispatching.DispatcherQueueTimer;
#elif UWP #elif UWP
using Windows.Foundation; using Windows.Foundation;
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
#else #else
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading; using System.Windows.Threading;
#endif #endif
@ -209,7 +206,7 @@ namespace MapControl
} }
} }
SwapImages(image, boundingBox); await SwapImages(image, boundingBox);
updateInProgress = false; updateInProgress = false;
} }
@ -241,7 +238,7 @@ namespace MapControl
} }
} }
private void SwapImages(ImageSource image, BoundingBox boundingBox) private async Task SwapImages(ImageSource image, BoundingBox boundingBox)
{ {
if (Children.Count >= 2) if (Children.Count >= 2)
{ {
@ -254,21 +251,7 @@ namespace MapControl
topImage.Source = image; topImage.Source = image;
SetBoundingBox(topImage, boundingBox); SetBoundingBox(topImage, boundingBox);
#if AVALONIA await OpacityHelper.SwapOpacities(topImage, bottomImage);
#else
topImage.BeginAnimation(OpacityProperty, new DoubleAnimation
{
To = 1d,
Duration = MapBase.ImageFadeDuration
});
bottomImage.BeginAnimation(OpacityProperty, new DoubleAnimation
{
To = 0d,
BeginTime = MapBase.ImageFadeDuration,
Duration = TimeSpan.Zero
});
#endif
} }
} }
} }

View file

@ -221,9 +221,6 @@
<Compile Include="..\Shared\WorldMercatorProjection.cs"> <Compile Include="..\Shared\WorldMercatorProjection.cs">
<Link>WorldMercatorProjection.cs</Link> <Link>WorldMercatorProjection.cs</Link>
</Compile> </Compile>
<Compile Include="..\WinUI\Animatable.WinUI.cs">
<Link>Animatable.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\DependencyPropertyHelper.WinUI.cs"> <Compile Include="..\WinUI\DependencyPropertyHelper.WinUI.cs">
<Link>DependencyPropertyHelper.WinUI.cs</Link> <Link>DependencyPropertyHelper.WinUI.cs</Link>
</Compile> </Compile>
@ -263,6 +260,9 @@
<Compile Include="..\WinUI\Matrix.WinUI.cs"> <Compile Include="..\WinUI\Matrix.WinUI.cs">
<Link>Matrix.WinUI.cs</Link> <Link>Matrix.WinUI.cs</Link>
</Compile> </Compile>
<Compile Include="..\WinUI\OpacityHelper.WinUI.cs">
<Link>OpacityHelper.WinUI.cs</Link>
</Compile>
<Compile Include="..\WinUI\Point.WinUI.cs"> <Compile Include="..\WinUI\Point.WinUI.cs">
<Link>Point.WinUI.cs</Link> <Link>Point.WinUI.cs</Link>
</Compile> </Compile>

View file

@ -0,0 +1,32 @@
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
// Copyright © 2024 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Animation;
namespace MapControl
{
public static class OpacityHelper
{
public static async Task SwapOpacities(UIElement topElement, UIElement bottomElement)
{
topElement.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation
{
To = 1d,
Duration = MapBase.ImageFadeDuration
});
bottomElement.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation
{
To = 0d,
BeginTime = MapBase.ImageFadeDuration,
Duration = TimeSpan.Zero
});
await Task.CompletedTask;
}
}
}

View file

@ -1,35 +0,0 @@
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
// Copyright © 2024 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media.Animation;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media.Animation;
#endif
namespace MapControl
{
internal static class Animatable
{
public static void BeginAnimation(this DependencyObject obj, string property, Timeline animation)
{
Storyboard.SetTargetProperty(animation, property);
Storyboard.SetTarget(animation, obj);
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
public static void BeginAnimation(this DependencyObject obj, DependencyProperty property, Timeline animation)
{
if (animation != null && property == UIElement.OpacityProperty)
{
BeginAnimation(obj, nameof(UIElement.Opacity), animation);
}
}
}
}

View file

@ -175,7 +175,7 @@ namespace MapControl
centerAnimation.Completed += CenterAnimationCompleted; centerAnimation.Completed += CenterAnimationCompleted;
this.BeginAnimation(nameof(AnimatedCenter), centerAnimation); BeginAnimation(nameof(AnimatedCenter), centerAnimation);
} }
} }
} }
@ -270,7 +270,7 @@ namespace MapControl
zoomLevelAnimation.Completed += ZoomLevelAnimationCompleted; zoomLevelAnimation.Completed += ZoomLevelAnimationCompleted;
this.BeginAnimation(nameof(ZoomLevel), zoomLevelAnimation); BeginAnimation(nameof(ZoomLevel), zoomLevelAnimation);
} }
} }
} }
@ -346,7 +346,7 @@ namespace MapControl
headingAnimation.Completed += HeadingAnimationCompleted; headingAnimation.Completed += HeadingAnimationCompleted;
this.BeginAnimation(nameof(Heading), headingAnimation); BeginAnimation(nameof(Heading), headingAnimation);
} }
} }
} }
@ -362,5 +362,15 @@ namespace MapControl
headingAnimation = null; headingAnimation = null;
} }
} }
public void BeginAnimation(string property, Timeline animation)
{
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, property);
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
} }
} }

View file

@ -0,0 +1,47 @@
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
// Copyright © 2024 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Threading.Tasks;
#if WINUI
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media.Animation;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media.Animation;
#endif
namespace MapControl
{
public static class OpacityHelper
{
public static void BeginOpacityAnimation(DependencyObject obj, DoubleAnimation animation)
{
Storyboard.SetTargetProperty(animation, nameof(UIElement.Opacity));
Storyboard.SetTarget(animation, obj);
var storyboard = new Storyboard();
storyboard.Children.Add(animation);
storyboard.Begin();
}
public static async Task SwapOpacities(UIElement topElement, UIElement bottomElement)
{
BeginOpacityAnimation(topElement, new DoubleAnimation
{
To = 1d,
Duration = MapBase.ImageFadeDuration
});
BeginOpacityAnimation(bottomElement, new DoubleAnimation
{
To = 0d,
BeginTime = MapBase.ImageFadeDuration,
Duration = TimeSpan.Zero
});
await Task.CompletedTask;
}
}
}

View file

@ -18,7 +18,7 @@ namespace MapControl
{ {
private void BeginOpacityAnimation() private void BeginOpacityAnimation()
{ {
Image.BeginAnimation(UIElement.OpacityProperty, OpacityHelper.BeginOpacityAnimation(Image,
new DoubleAnimation new DoubleAnimation
{ {
From = 0d, From = 0d,