diff --git a/MapControl/Avalonia/MapBase.Avalonia.cs b/MapControl/Avalonia/MapBase.Avalonia.cs index 23fecf50..c40af495 100644 --- a/MapControl/Avalonia/MapBase.Avalonia.cs +++ b/MapControl/Avalonia/MapBase.Avalonia.cs @@ -161,21 +161,7 @@ namespace MapControl centerCts?.Cancel(); - centerAnimation = new Animation - { - FillMode = FillMode.Forward, - Duration = AnimationDuration, - Easing = AnimationEasing, - Children = - { - new KeyFrame - { - KeyTime = AnimationDuration, - Setters = { new Setter(CenterProperty, new Location(targetCenter.Latitude, CoerceLongitude(targetCenter.Longitude))) } - } - } - }; - + centerAnimation = CreateAnimation(CenterProperty, new Location(targetCenter.Latitude, CoerceLongitude(targetCenter.Longitude))); centerCts = new CancellationTokenSource(); await centerAnimation.RunAsync(this, centerCts.Token); @@ -226,21 +212,7 @@ namespace MapControl { zoomLevelCts?.Cancel(); - zoomLevelAnimation = new Animation - { - FillMode = FillMode.Forward, - Duration = AnimationDuration, - Easing = AnimationEasing, - Children = - { - new KeyFrame - { - KeyTime = AnimationDuration, - Setters = { new Setter(ZoomLevelProperty, targetZoomLevel) } - } - } - }; - + zoomLevelAnimation = CreateAnimation(ZoomLevelProperty, targetZoomLevel); zoomLevelCts = new CancellationTokenSource(); await zoomLevelAnimation.RunAsync(this, zoomLevelCts.Token); @@ -288,21 +260,7 @@ namespace MapControl headingCts?.Cancel(); - headingAnimation = new Animation - { - FillMode = FillMode.Forward, - Duration = AnimationDuration, - Easing = AnimationEasing, - Children = - { - new KeyFrame - { - KeyTime = AnimationDuration, - Setters = { new Setter(HeadingProperty, targetHeading) } - } - } - }; - + headingAnimation = CreateAnimation(HeadingProperty, targetHeading); headingCts = new CancellationTokenSource(); await headingAnimation.RunAsync(this, headingCts.Token); @@ -317,5 +275,23 @@ namespace MapControl headingAnimation = null; } } + + private Animation CreateAnimation(DependencyProperty property, object value) + { + return new Animation + { + FillMode = FillMode.Forward, + Duration = AnimationDuration, + Easing = AnimationEasing, + Children = + { + new KeyFrame + { + KeyTime = AnimationDuration, + Setters = { new Setter(property, value) } + } + } + }; + } } } diff --git a/MapControl/Avalonia/MapImageLayer.Avalonia.cs b/MapControl/Avalonia/MapImageLayer.Avalonia.cs new file mode 100644 index 00000000..e9566189 --- /dev/null +++ b/MapControl/Avalonia/MapImageLayer.Avalonia.cs @@ -0,0 +1,32 @@ +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// Copyright © Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using System.Threading.Tasks; + +namespace MapControl +{ + public partial class MapImageLayer + { + public static void FadeOver(Image topImage, Image bottomImage) + { + var animation = new Animation + { + FillMode = FillMode.Forward, + Duration = MapBase.ImageFadeDuration, + Children = + { + new KeyFrame + { + KeyTime = MapBase.ImageFadeDuration, + Setters = { new Setter(Visual.OpacityProperty, 1d) } + } + } + }; + + _ = animation.RunAsync(topImage).ContinueWith( + _ => bottomImage.Opacity = 0d, + TaskScheduler.FromCurrentSynchronizationContext()); + } + } +} diff --git a/MapControl/Avalonia/OpacityHelper.Avalonia.cs b/MapControl/Avalonia/OpacityHelper.Avalonia.cs deleted file mode 100644 index 74fda5c9..00000000 --- a/MapControl/Avalonia/OpacityHelper.Avalonia.cs +++ /dev/null @@ -1,56 +0,0 @@ -// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control -// Copyright © Clemens Fischer -// Licensed under the Microsoft Public License (Ms-PL) - -using System.Threading.Tasks; -using System; - -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 SwapOpacitiesAsync(Control topElement, Control bottomElement) - { - var animation = new Animation - { - FillMode = FillMode.Forward, - 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 3582af4e..6a1ebcc7 100644 --- a/MapControl/Avalonia/Tile.Avalonia.cs +++ b/MapControl/Avalonia/Tile.Avalonia.cs @@ -2,13 +2,33 @@ // Copyright © Clemens Fischer // Licensed under the Microsoft Public License (Ms-PL) +using System; + namespace MapControl { public partial class Tile { private void AnimateImageOpacity() { - _ = OpacityHelper.FadeIn(Image); + 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); } } } diff --git a/MapControl/Shared/MapImageLayer.cs b/MapControl/Shared/MapImageLayer.cs index 4a4db6c6..720474c9 100644 --- a/MapControl/Shared/MapImageLayer.cs +++ b/MapControl/Shared/MapImageLayer.cs @@ -28,7 +28,7 @@ namespace MapControl /// Displays a single map image, e.g. from a Web Map Service (WMS). /// The image must be provided by the abstract GetImageAsync() method. /// - public abstract class MapImageLayer : MapPanel, IMapLayer + public abstract partial class MapImageLayer : MapPanel, IMapLayer { public static readonly DependencyProperty DescriptionProperty = DependencyPropertyHelper.Register(nameof(Description)); @@ -199,7 +199,7 @@ namespace MapControl } } - await SwapImages(image, boundingBox); + SwapImages(image, boundingBox); updateInProgress = false; } @@ -231,7 +231,7 @@ namespace MapControl } } - private async Task SwapImages(ImageSource image, BoundingBox boundingBox) + private void SwapImages(ImageSource image, BoundingBox boundingBox) { if (Children.Count >= 2) { @@ -244,7 +244,7 @@ namespace MapControl topImage.Source = image; SetBoundingBox(topImage, boundingBox); - await OpacityHelper.SwapOpacitiesAsync(topImage, bottomImage); + FadeOver(topImage, bottomImage); } } } diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj index 23449e41..e8a62490 100644 --- a/MapControl/UWP/MapControl.UWP.csproj +++ b/MapControl/UWP/MapControl.UWP.csproj @@ -242,6 +242,9 @@ MapGraticule.WinUI.cs + + MapImageLayer.WinUI.cs + MapItem.WinUI.cs @@ -260,9 +263,6 @@ Matrix.WinUI.cs - - OpacityHelper.WinUI.cs - Point.WinUI.cs diff --git a/MapControl/WPF/OpacityHelper.WPF.cs b/MapControl/WPF/MapImageLayer.WPF.cs similarity index 57% rename from MapControl/WPF/OpacityHelper.WPF.cs rename to MapControl/WPF/MapImageLayer.WPF.cs index 0798c7e7..dd2d883c 100644 --- a/MapControl/WPF/OpacityHelper.WPF.cs +++ b/MapControl/WPF/MapImageLayer.WPF.cs @@ -3,30 +3,27 @@ // Licensed under the Microsoft Public License (Ms-PL) using System; -using System.Threading.Tasks; -using System.Windows; +using System.Windows.Controls; using System.Windows.Media.Animation; namespace MapControl { - public static class OpacityHelper + public partial class MapImageLayer { - public static Task SwapOpacitiesAsync(UIElement topElement, UIElement bottomElement) + public static void FadeOver(Image topImage, Image bottomImage) { - topElement.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation + topImage.BeginAnimation(OpacityProperty, new DoubleAnimation { To = 1d, Duration = MapBase.ImageFadeDuration }); - bottomElement.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation + bottomImage.BeginAnimation(OpacityProperty, new DoubleAnimation { To = 0d, BeginTime = MapBase.ImageFadeDuration, Duration = TimeSpan.Zero }); - - return Task.CompletedTask; } } } diff --git a/MapControl/WinUI/MapImageLayer.WinUI.cs b/MapControl/WinUI/MapImageLayer.WinUI.cs new file mode 100644 index 00000000..64da530b --- /dev/null +++ b/MapControl/WinUI/MapImageLayer.WinUI.cs @@ -0,0 +1,45 @@ +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// Copyright © Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using System; +#if UWP +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media.Animation; +#else +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media.Animation; +#endif + +namespace MapControl +{ + public partial class MapImageLayer + { + public static void FadeOver(Image topImage, Image bottomImage) + { + var topImageAnimation = new DoubleAnimation + { + To = 1d, + Duration = MapBase.ImageFadeDuration + }; + + var bottomImageAnimation = new DoubleAnimation + { + To = 0d, + BeginTime = MapBase.ImageFadeDuration, + Duration = TimeSpan.Zero + }; + + Storyboard.SetTargetProperty(topImageAnimation, nameof(Opacity)); + Storyboard.SetTarget(topImageAnimation, topImage); + + Storyboard.SetTargetProperty(bottomImageAnimation, nameof(Opacity)); + Storyboard.SetTarget(bottomImageAnimation, bottomImage); + + var storyboard = new Storyboard(); + storyboard.Children.Add(topImageAnimation); + storyboard.Children.Add(bottomImageAnimation); + storyboard.Begin(); + } + } +} diff --git a/MapControl/WinUI/OpacityHelper.WinUI.cs b/MapControl/WinUI/OpacityHelper.WinUI.cs deleted file mode 100644 index e718c95f..00000000 --- a/MapControl/WinUI/OpacityHelper.WinUI.cs +++ /dev/null @@ -1,47 +0,0 @@ -// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control -// Copyright © Clemens Fischer -// Licensed under the Microsoft Public License (Ms-PL) - -using System; -using System.Threading.Tasks; -#if UWP -using Windows.UI.Xaml; -using Windows.UI.Xaml.Media.Animation; -#else -using Microsoft.UI.Xaml; -using Microsoft.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 Task SwapOpacitiesAsync(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 - }); - - return Task.CompletedTask; - } - } -} diff --git a/MapControl/WinUI/Tile.WinUI.cs b/MapControl/WinUI/Tile.WinUI.cs index 21f972af..66d6d7d3 100644 --- a/MapControl/WinUI/Tile.WinUI.cs +++ b/MapControl/WinUI/Tile.WinUI.cs @@ -18,13 +18,19 @@ namespace MapControl { private void BeginOpacityAnimation() { - OpacityHelper.BeginOpacityAnimation(Image, - new DoubleAnimation - { - From = 0d, - Duration = MapBase.ImageFadeDuration, - FillBehavior = FillBehavior.Stop - }); + var animation = new DoubleAnimation + { + From = 0d, + Duration = MapBase.ImageFadeDuration, + FillBehavior = FillBehavior.Stop + }; + + Storyboard.SetTargetProperty(animation, nameof(UIElement.Opacity)); + Storyboard.SetTarget(animation, Image); + + var storyboard = new Storyboard(); + storyboard.Children.Add(animation); + storyboard.Begin(); } private void AnimateImageOpacity()