diff --git a/MapControl/Shared/Map.cs b/MapControl/Shared/Map.cs
new file mode 100644
index 00000000..68a416a7
--- /dev/null
+++ b/MapControl/Shared/Map.cs
@@ -0,0 +1,45 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2020 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+#if WINDOWS_UWP
+using Windows.UI.Xaml;
+#else
+using System.Windows;
+#endif
+
+namespace MapControl
+{
+ ///
+ /// MapBase with default input event handling.
+ ///
+ public partial class Map : MapBase
+ {
+ public static readonly DependencyProperty MouseWheelZoomDeltaProperty = DependencyProperty.Register(
+ nameof(MouseWheelZoomDelta), typeof(double), typeof(Map), new PropertyMetadata(1d));
+
+ ///
+ /// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
+ /// The default value is 1.
+ ///
+ public double MouseWheelZoomDelta
+ {
+ get { return (double)GetValue(MouseWheelZoomDeltaProperty); }
+ set { SetValue(MouseWheelZoomDeltaProperty, value); }
+ }
+
+ private Vector translation;
+ private double rotation;
+ private double scale = 1d;
+ private bool transformPending;
+
+ private void ResetTransform()
+ {
+ translation.X = 0d;
+ translation.Y = 0d;
+ rotation = 0d;
+ scale = 1d;
+ transformPending = false;
+ }
+ }
+}
diff --git a/MapControl/UWP/Map.UWP.cs b/MapControl/UWP/Map.UWP.cs
index 95c723c9..f8f0d50d 100644
--- a/MapControl/UWP/Map.UWP.cs
+++ b/MapControl/UWP/Map.UWP.cs
@@ -3,72 +3,48 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-using Windows.UI.Xaml;
+using Windows.UI.Core;
using Windows.UI.Xaml.Input;
namespace MapControl
{
- ///
- /// MapBase with default input event handling.
- ///
- public class Map : MapBase
+ public partial class Map
{
- public static readonly DependencyProperty MouseWheelZoomDeltaProperty = DependencyProperty.Register(
- nameof(MouseWheelZoomDelta), typeof(double), typeof(Map), new PropertyMetadata(1d));
-
- private bool transformPending;
- private Vector transformTranslation;
- private double transformRotation;
- private double transformScale = 1d;
-
public Map()
{
- ManipulationMode = ManipulationModes.Scale |
- ManipulationModes.TranslateX | ManipulationModes.TranslateY | ManipulationModes.TranslateInertia;
+ ManipulationMode = ManipulationModes.Scale
+ | ManipulationModes.TranslateX
+ | ManipulationModes.TranslateY
+ | ManipulationModes.TranslateInertia;
ManipulationDelta += OnManipulationDelta;
PointerWheelChanged += OnPointerWheelChanged;
}
- ///
- /// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
- ///
- public double MouseWheelZoomDelta
+ private async void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
- get { return (double)GetValue(MouseWheelZoomDeltaProperty); }
- set { SetValue(MouseWheelZoomDeltaProperty, value); }
- }
-
- protected virtual void OnPointerWheelChanged(object sender, PointerRoutedEventArgs e)
- {
- var point = e.GetCurrentPoint(this);
- var zoomChange = MouseWheelZoomDelta * point.Properties.MouseWheelDelta / 120d;
-
- ZoomMap(point.Position, TargetZoomLevel + zoomChange);
- }
-
- protected virtual async void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
- {
- transformTranslation.X += e.Delta.Translation.X;
- transformTranslation.Y += e.Delta.Translation.Y;
- transformRotation += e.Delta.Rotation;
- transformScale *= e.Delta.Scale;
+ translation.X += e.Delta.Translation.X;
+ translation.Y += e.Delta.Translation.Y;
+ rotation += e.Delta.Rotation;
+ scale *= e.Delta.Scale;
if (!transformPending)
{
transformPending = true;
- await Dispatcher.RunIdleAsync(a =>
- {
- TransformMap(e.Position, transformTranslation, transformRotation, transformScale);
+ await Dispatcher.RunAsync(CoreDispatcherPriority.Low,
+ () => TransformMap(e.Position, translation, rotation, scale));
- transformPending = false;
- transformTranslation.X = 0d;
- transformTranslation.Y = 0d;
- transformRotation = 0d;
- transformScale = 1d;
- });
+ ResetTransform();
}
}
+
+ private void OnPointerWheelChanged(object sender, PointerRoutedEventArgs e)
+ {
+ var point = e.GetCurrentPoint(this);
+ var zoomDelta = MouseWheelZoomDelta * point.Properties.MouseWheelDelta / 120d;
+
+ ZoomMap(point.Position, TargetZoomLevel + zoomDelta);
+ }
}
}
diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj
index 803cc78b..14a0acb6 100644
--- a/MapControl/UWP/MapControl.UWP.csproj
+++ b/MapControl/UWP/MapControl.UWP.csproj
@@ -86,6 +86,9 @@
LocationEx.cs
+
+ Map.cs
+
MapBase.cs
diff --git a/MapControl/WPF/Map.WPF.cs b/MapControl/WPF/Map.WPF.cs
index ae255ede..36d0a446 100644
--- a/MapControl/WPF/Map.WPF.cs
+++ b/MapControl/WPF/Map.WPF.cs
@@ -2,21 +2,21 @@
// © 2020 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
+using System;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
+using System.Windows.Threading;
namespace MapControl
{
- ///
- /// MapBase with default input event handling.
- ///
- public class Map : MapBase
+ public partial class Map
{
public static readonly DependencyProperty ManipulationModeProperty = DependencyProperty.Register(
nameof(ManipulationMode), typeof(ManipulationModes), typeof(Map), new PropertyMetadata(ManipulationModes.All));
- public static readonly DependencyProperty MouseWheelZoomDeltaProperty = DependencyProperty.Register(
- nameof(MouseWheelZoomDelta), typeof(double), typeof(Map), new PropertyMetadata(1d));
+ public static readonly DependencyProperty TransformDelayProperty = DependencyProperty.Register(
+ nameof(TransformDelay), typeof(TimeSpan), typeof(Map), new PropertyMetadata(TimeSpan.FromMilliseconds(50)));
private Point? mousePosition;
@@ -25,6 +25,16 @@ namespace MapControl
IsManipulationEnabledProperty.OverrideMetadata(typeof(Map), new FrameworkPropertyMetadata(true));
}
+ public Map()
+ {
+ ManipulationStarted += OnManipulationStarted;
+ ManipulationDelta += OnManipulationDelta;
+ MouseLeftButtonDown += OnMouseLeftButtonDown;
+ MouseLeftButtonUp += OnMouseLeftButtonUp;
+ MouseMove += OnMouseMove;
+ MouseWheel += OnMouseWheel;
+ }
+
///
/// Gets or sets a value that specifies how the map control handles manipulations.
///
@@ -35,36 +45,57 @@ namespace MapControl
}
///
- /// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
+ /// Gets or sets a delay interval between adjacent calls to TranslateMap or TransformMap during mouse pan and manipulation.
+ /// The default value is 50 milliseconds.
///
- public double MouseWheelZoomDelta
+ public TimeSpan TransformDelay
{
- get { return (double)GetValue(MouseWheelZoomDeltaProperty); }
- set { SetValue(MouseWheelZoomDeltaProperty, value); }
+ get { return (TimeSpan)GetValue(TransformDelayProperty); }
+ set { SetValue(TransformDelayProperty, value); }
}
- protected override void OnMouseWheel(MouseWheelEventArgs e)
+ private async Task InvokeTransformAsync(Action action)
{
- base.OnMouseWheel(e);
+ if (!transformPending)
+ {
+ transformPending = true;
- var zoomDelta = MouseWheelZoomDelta * e.Delta / 120d;
- ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomDelta);
+ if (TransformDelay > TimeSpan.Zero)
+ {
+ await Task.Delay(TransformDelay);
+ }
+
+ await Dispatcher.InvokeAsync(action);
+
+ ResetTransform();
+ }
}
- protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
+ private void OnManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
- base.OnMouseLeftButtonDown(e);
+ Manipulation.SetManipulationMode(this, ManipulationMode);
+ }
+ private async void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
+ {
+ translation.X += e.DeltaManipulation.Translation.X;
+ translation.Y += e.DeltaManipulation.Translation.Y;
+ rotation += e.DeltaManipulation.Rotation;
+ scale *= (e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2d;
+
+ await InvokeTransformAsync(() => TransformMap(e.ManipulationOrigin, translation, rotation, scale));
+ }
+
+ private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+ {
if (CaptureMouse())
{
mousePosition = e.GetPosition(this);
}
}
- protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
+ private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
- base.OnMouseLeftButtonUp(e);
-
if (mousePosition.HasValue)
{
mousePosition = null;
@@ -72,32 +103,23 @@ namespace MapControl
}
}
- protected override void OnMouseMove(MouseEventArgs e)
+ private async void OnMouseMove(object sender, MouseEventArgs e)
{
- base.OnMouseMove(e);
-
if (mousePosition.HasValue)
{
var position = e.GetPosition(this);
- TranslateMap(position - mousePosition.Value);
+ translation += position - mousePosition.Value;
mousePosition = position;
+
+ await InvokeTransformAsync(() => TranslateMap(translation));
}
}
- protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
+ private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
- base.OnManipulationStarted(e);
+ var zoomDelta = MouseWheelZoomDelta * e.Delta / 120d;
- Manipulation.SetManipulationMode(this, ManipulationMode);
- }
-
- protected override void OnManipulationDelta(ManipulationDeltaEventArgs e)
- {
- base.OnManipulationDelta(e);
-
- TransformMap(e.ManipulationOrigin,
- e.DeltaManipulation.Translation, e.DeltaManipulation.Rotation,
- (e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2d);
+ ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomDelta);
}
}
}