Silverlight VirtualEarth Map Control - #5 (it works!)
After attempts one, two, three and four,
all the elements pan and zoom in 'real time' AS DOES the course path (now a MapPolyline) AND the animated Ellipse 'runners'.
ALSO, they all scale in 'real time' (from zoomed so far out you can hardly see it to zooming in to street level so that the points are moving very fast indeed).
Making it work...
See #4 for the solutions to most of my problems - the last issue (described below) was animating the Map.Center Location itself.
Animating Map.Center Location (Latitude/Longitude) properties
Unfortunately animating the Map iself was not easy.
Using the same attached properties approach as before to target the Map.Center.Latitude/Longitude properties
didn't seem to work, because only one axis would "move" (seemed like the Changed handler was being called for both, but the 'simultaneous' updates
caused one to get lost). In the end I have 'synchronised' updating the .Center property with a static field (highlighted in the code below).
Basically your Map tag looks the same as always...
<m:Map x:Name="viewMap" Width="600" Height="800">
<m:Map.Children>
<m:MapLayer>
... with the constructor code including the initial Location and a custom Attached Property like this
viewMap.View = new Microsoft.VirtualEarth.MapControl.MapViewSpecification(
new Location(-33.863502543277534, 151.20294570922852), 15.0000);
Storyboard.SetTargetProperty(viewmapanimX, new PropertyPath(Attachments.CenterLatitudeProperty));
Storyboard.SetTargetProperty(viewmapanimY, new PropertyPath(Attachments.CenterLongitudeProperty));
and a seperate static class with the key methods allowing us to animate the otherwise difficult-to-access Latitude/Longitude properties.
#region Map.Center.Latitude
public static readonly DependencyProperty CenterLatitudeProperty =
DependencyProperty.RegisterAttached("CenterLatitude",
typeof(double), typeof(Attachments),
new PropertyMetadata(
new PropertyChangedCallback(OnCenterLatitudeChanged)));
public static void SetCenterLatitude(DependencyObject o, double value)
{
o.SetValue(CenterLatitudeProperty, value);
}
public static double GetCenterLatitude(DependencyObject o)
{
return (double)o.GetValue(CenterLatitudeProperty);
}
private static void OnCenterLatitudeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((double)e.NewValue == 0.0) return;
Location l = (Location)((Map)d).Center;
// l.Latitude = (double)e.NewValue;
myLatitude = (double)e.NewValue;
((Map)d).Center = l;
}
/// <summary>HACK:</summary>
private static double myLatitude = 0.0;
#endregion
#region Map.Center.Longitude
public static readonly DependencyProperty CenterLongitudeProperty =
DependencyProperty.RegisterAttached("CenterLongitude",
typeof(double), typeof(Attachments),
new PropertyMetadata(
new PropertyChangedCallback(OnCenterLongitudeChanged)));
public static void SetCenterLongitude(DependencyObject o, double value)
{
o.SetValue(CenterLongitudeProperty, value);
}
public static double GetCenterLongitude(DependencyObject o)
{
return (double)o.GetValue(CenterLongitudeProperty);
}
private static void OnCenterLongitudeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if ((double)e.NewValue == 0.0 || myLatitude == 0.0) return;
Location l = (Location)((Map)d).Center;
l.Longitude = (double)e.NewValue;
l.Latitude = myLatitude; // HACK:
((Map)d).Center = l;
}
#endregion
and finally your declarative animation would look like this:
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard x:Name="Timeline1">
<!-- MAP -->
<DoubleAnimationUsingKeyFrames x:Name="viewmapanimX"
BeginTime="00:00:00"
Storyboard.TargetName="viewMap">
<LinearDoubleKeyFrame KeyTime="00:00:00.000000" Value="-33.863502543277534" />
<LinearDoubleKeyFrame KeyTime="00:00:01.109022" Value="-33.8594756365014" />
<LinearDoubleKeyFrame KeyTime="00:00:01.570410" Value="-33.8578006724536" />
|