I want to create a smooth animated drag effect just like Google Maps (if you know what I am talking about).
I warped
In order to implement smooth drag like Google I created
__The problem is that
Is there another way to create a smooth drag?
What basically I am doing in order to have a smooth drag when the user releases the mouse, is saving the last mouse movement by saving the last 10 move messages. After that I calculate the speed of the movement and using the speed in the animation.
I warped
GMapControl
class and successfully implemented smooth zoom by overriding the OnMouseWheel
method and applying a DoubleAnimation
using exponential easing on the Zoom
property every time the wheel is turned.In order to implement smooth drag like Google I created
MapOffset
property, which on every value change will call Offset
function from the MapControl
class with the new offset point. Creating the MapOffset
granted me the ability to animate map movement.__The problem is that
Offset
function only accept integer values which is not accurate enough for making smooth animations.__Is there another way to create a smooth drag?
publicclass SmoothMap : GMapControl { publicstaticreadonly DependencyProperty MapOffsetProperty = DependencyProperty.Register("MapOffset", typeof(Point), typeof(SmoothMap), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnM_OffsetPropertyChanged))); private Storyboard movementSb; private PointAnimation movementAnimation; public SmoothMap() { movementSb = new Storyboard(); movementAnimation = new PointAnimation(); movementAnimation.From = new Point(0, 0); movementAnimation.Duration = new Duration(TimeSpan.FromSeconds(1)); movementAnimation.FillBehavior = FillBehavior.HoldEnd; ExponentialEase ease = new ExponentialEase(); ease.EasingMode = EasingMode.EaseOut; ease.Exponent = 6; movementAnimation.EasingFunction = ease; movementSb.Children.Add(movementAnimation); Storyboard.SetTarget(movementAnimation, this); Storyboard.SetTargetProperty(movementAnimation, new PropertyPath(MapOffsetProperty)); } privatestaticvoid OnMapOffsetPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) { SmoothMap sm = source as SmoothMap; Point p = (Point)e.NewValue; sm.Offset((int)p.X, (int)p.Y); } privateconstint OffsetConstant = 3; bool isDragging = false; Queue<Tuple<Point, int>> lastPos = new Queue<Tuple<Point, int>>(); protectedoverridevoid OnMouseMove(System.Windows.Input.MouseEventArgs e) { base.OnMouseMove(e); if(e.LeftButton == System.Windows.Input.MouseButtonState.Pressed) { isDragging = true; lastPos.Enqueue(new Tuple<Point, int>(e.GetPosition(this), e.Timestamp)); if (lastPos.Count == 10) { lastPos.Dequeue(); } } elseif(e.LeftButton == System.Windows.Input.MouseButtonState.Released && isDragging) { Tuple<Point, int> first = lastPos.First(); Tuple<Point, int> last = lastPos.Last(); if (e.Timestamp - last.Item2 < 200) { long deltaT = last.Item2 - first.Item2; double deltaX = (last.Item1.X - first.Item1.X); double deltaY = (last.Item1.Y - first.Item1.Y); double velocity_X = deltaX / (double)deltaT; double velocity_Y = deltaY / (double)deltaT; movementSb.Stop(); Debug.WriteLine("To: " + velocity_X); movementAnimation.To = new Point(velocity_X * OffsetConstant , velocity_Y * OffsetConstant ); lastPos.Clear(); isDragging = false; movementSb.Begin(); } } } }