From 8708c7ffe6b2e1de708a6586b224d2168ee76a28 Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Tue, 21 May 2024 22:05:01 +0200 Subject: [PATCH] Reworked animations --- MapControl/Avalonia/OpacityHelper.Avalonia.cs | 59 +++++++++++++++++++ MapControl/Avalonia/Tile.Avalonia.cs | 24 +------- MapControl/Shared/MapImageLayer.cs | 23 +------- MapControl/UWP/MapControl.UWP.csproj | 6 +- MapControl/WPF/OpacityHelper.WPF.cs | 32 ++++++++++ MapControl/WinUI/Animatable.WinUI.cs | 35 ----------- MapControl/WinUI/MapBase.WinUI.cs | 16 ++++- MapControl/WinUI/OpacityHelper.WinUI.cs | 47 +++++++++++++++ MapControl/WinUI/Tile.WinUI.cs | 2 +- 9 files changed, 159 insertions(+), 85 deletions(-) create mode 100644 MapControl/Avalonia/OpacityHelper.Avalonia.cs create mode 100644 MapControl/WPF/OpacityHelper.WPF.cs delete mode 100644 MapControl/WinUI/Animatable.WinUI.cs create mode 100644 MapControl/WinUI/OpacityHelper.WinUI.cs diff --git a/MapControl/Avalonia/OpacityHelper.Avalonia.cs b/MapControl/Avalonia/OpacityHelper.Avalonia.cs new file mode 100644 index 00000000..b0c59cbe --- /dev/null +++ b/MapControl/Avalonia/OpacityHelper.Avalonia.cs @@ -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; + } + } +} diff --git a/MapControl/Avalonia/Tile.Avalonia.cs b/MapControl/Avalonia/Tile.Avalonia.cs index 46245212..23e313f8 100644 --- a/MapControl/Avalonia/Tile.Avalonia.cs +++ b/MapControl/Avalonia/Tile.Avalonia.cs @@ -2,35 +2,13 @@ // Copyright © 2024 Clemens Fischer // Licensed under the Microsoft Public License (Ms-PL) -using Avalonia.Animation; -using Avalonia.Styling; -using System; - namespace MapControl { public partial class Tile { private void AnimateImageOpacity() { - 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) } - } - } - }; - - _ = animation.RunAsync(Image); + _ = OpacityHelper.FadeIn(Image); } } } diff --git a/MapControl/Shared/MapImageLayer.cs b/MapControl/Shared/MapImageLayer.cs index 5c9a47ac..13333e9e 100644 --- a/MapControl/Shared/MapImageLayer.cs +++ b/MapControl/Shared/MapImageLayer.cs @@ -17,19 +17,16 @@ using Windows.Foundation; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Media.Animation; using DispatcherTimer = Microsoft.UI.Dispatching.DispatcherQueueTimer; #elif UWP using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; -using Windows.UI.Xaml.Media.Animation; #else using System.Windows; using System.Windows.Controls; using System.Windows.Media; -using System.Windows.Media.Animation; using System.Windows.Threading; #endif @@ -209,7 +206,7 @@ namespace MapControl } } - SwapImages(image, boundingBox); + await SwapImages(image, boundingBox); 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) { @@ -254,21 +251,7 @@ namespace MapControl topImage.Source = image; SetBoundingBox(topImage, boundingBox); -#if AVALONIA -#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 + await OpacityHelper.SwapOpacities(topImage, bottomImage); } } } diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj index 6c7ea0c3..d1e71c09 100644 --- a/MapControl/UWP/MapControl.UWP.csproj +++ b/MapControl/UWP/MapControl.UWP.csproj @@ -221,9 +221,6 @@ WorldMercatorProjection.cs - - Animatable.WinUI.cs - DependencyPropertyHelper.WinUI.cs @@ -263,6 +260,9 @@ Matrix.WinUI.cs + + OpacityHelper.WinUI.cs + Point.WinUI.cs diff --git a/MapControl/WPF/OpacityHelper.WPF.cs b/MapControl/WPF/OpacityHelper.WPF.cs new file mode 100644 index 00000000..daaee8c1 --- /dev/null +++ b/MapControl/WPF/OpacityHelper.WPF.cs @@ -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; + } + } +} diff --git a/MapControl/WinUI/Animatable.WinUI.cs b/MapControl/WinUI/Animatable.WinUI.cs deleted file mode 100644 index f892810e..00000000 --- a/MapControl/WinUI/Animatable.WinUI.cs +++ /dev/null @@ -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); - } - } - } -} diff --git a/MapControl/WinUI/MapBase.WinUI.cs b/MapControl/WinUI/MapBase.WinUI.cs index ff42c963..e86fcc8f 100644 --- a/MapControl/WinUI/MapBase.WinUI.cs +++ b/MapControl/WinUI/MapBase.WinUI.cs @@ -175,7 +175,7 @@ namespace MapControl centerAnimation.Completed += CenterAnimationCompleted; - this.BeginAnimation(nameof(AnimatedCenter), centerAnimation); + BeginAnimation(nameof(AnimatedCenter), centerAnimation); } } } @@ -270,7 +270,7 @@ namespace MapControl zoomLevelAnimation.Completed += ZoomLevelAnimationCompleted; - this.BeginAnimation(nameof(ZoomLevel), zoomLevelAnimation); + BeginAnimation(nameof(ZoomLevel), zoomLevelAnimation); } } } @@ -346,7 +346,7 @@ namespace MapControl headingAnimation.Completed += HeadingAnimationCompleted; - this.BeginAnimation(nameof(Heading), headingAnimation); + BeginAnimation(nameof(Heading), headingAnimation); } } } @@ -362,5 +362,15 @@ namespace MapControl 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(); + } } } diff --git a/MapControl/WinUI/OpacityHelper.WinUI.cs b/MapControl/WinUI/OpacityHelper.WinUI.cs new file mode 100644 index 00000000..9bfed25c --- /dev/null +++ b/MapControl/WinUI/OpacityHelper.WinUI.cs @@ -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; + } + } +} diff --git a/MapControl/WinUI/Tile.WinUI.cs b/MapControl/WinUI/Tile.WinUI.cs index 71202b61..7bfc84d8 100644 --- a/MapControl/WinUI/Tile.WinUI.cs +++ b/MapControl/WinUI/Tile.WinUI.cs @@ -18,7 +18,7 @@ namespace MapControl { private void BeginOpacityAnimation() { - Image.BeginAnimation(UIElement.OpacityProperty, + OpacityHelper.BeginOpacityAnimation(Image, new DoubleAnimation { From = 0d,