Technology

Bing Maps Silverlight - smooth zoom skydive animation

Anthony Marshall
Anthony Marshall
11 Oct 2012
blog post featured image

In 2010 Austrian skydiver Felix Baumgartner teamed up with scientists and Red Bull to form the Red Bull Stratos; a project that aims to see Baumgartner free fall from a height of 120 000 feet; the edge of space; to the surface of planet Earth.

Have you ever wondered what this would feel like ? On Sunday Baumgartner will be making his leap, travelling the 23 miles at eye-watering super-sonic speeds, in his attempt to be the first human to break the sound barrier.

[<a href="http://www.telegraph.co.uk/science/space/9600661/Felix-Baumgartner-to-make-space-jump-attempt-on-Sunday.html">http://www.telegraph.co.uk/science/space/9600661/Felix-Baumgartner-to-make-space-jump-attempt-on-Sunday.html</a>]

If  this isn't something you personally fancy, you could always gain a similar experience by using the Silverlight Bing Maps Control; not quite as glamorous, but, equally not as uncomfortable.

Two years ago when the project was announced we developed a Silverlight application and map that starts zoomed out from your landing point and then smoothly animates the ZoomLevel parameter to mimic ‘plummeting’ to earth.

Read the previous blog post below to find out how we did this, and to take a look at the animation we generated...

... The problem is that the default map animation moves too quickly and you cannot animate the Map controls ZoomLevel property yourself from a Storyboard, as Storyboard animations only operate on DependencyProperties.

ZoomLevel is not the only value that developers have needed to animate in past that has not been a DependencyProperty. The solution is to set the Storyboard animation to target your own class member as a DependencyProperty which in turn can modify your intended object member.

<div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:625f2e16-70aa-4885-9050-34fd1eb81004" class="wlWriterSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;"> <div style="font-family: &amp;amp;amp; color: #000; font-size: 10pt; border: #000080 1px solid;"> <div style="padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana, tahoma, arial, sans-serif; background: #000080; color: #fff; font-weight: bold; padding-top: 2px;">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto;"> <ol style="padding-bottom: 0px; margin: 0px 0px 0px 2em; padding-left: 5px; padding-right: 0px; background: #ffffff; padding-top: 0px;"> <li><span style="color: #a31515;"> </span><span style="color: #0000ff;">&lt;</span><span style="color: #a31515;">Storyboard</span><span style="color: #ff0000;"> x</span><span style="color: #0000ff;">:</span><span style="color: #ff0000;">Name</span><span style="color: #0000ff;">="ZoomIn"&gt;</span></li> <li style="background: #f3f3f3;"> <span style="color: #a31515;"> </span><span style="color: #0000ff;">&lt;</span><span style="color: #a31515;">DoubleAnimation</span><span style="color: #ff0000;"> x</span><span style="color: #0000ff;">:</span><span style="color: #ff0000;">Name</span><span style="color: #0000ff;">="ZoomLevel"</span></li> <li> <span style="color: #ff0000;"> Storyboard.TargetName</span><span style="color: #0000ff;">="MainMap"</span></li> <li style="background: #f3f3f3;"> <span style="color: #ff0000;"> From</span><span style="color: #0000ff;">="3.0"</span></li> <li> <span style="color: #ff0000;"> To</span><span style="color: #0000ff;">="5.0"</span></li> <li style="background: #f3f3f3;"> <span style="color: #ff0000;"> Duration</span><span style="color: #0000ff;">="0:0:9" /&gt;</span></li> <li><span style="color: #a31515;"> </span><span style="color: #0000ff;">&lt;/</span><span style="color: #a31515;">Storyboard</span><span style="color: #0000ff;">&gt;</span></li> </ol> </div> </div> </div> Within your Silverlight control constructor. <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:9eaccda6-33d0-41e9-b980-ad5c36a50bfe" class="wlWriterSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;"> <div style="font-family: &amp;amp;amp; color: #000; font-size: 10pt; border: #000080 1px solid;"> <div style="padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana, tahoma, arial, sans-serif; background: #000080; color: #fff; font-weight: bold; padding-top: 2px;">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto;"> <ol style="padding-bottom: 0px; margin: 0px 0px 0px 2em; padding-left: 5px; padding-right: 0px; background: #ffffff; padding-top: 0px;"> <li><span style="color: #2b91af;">Storyboard</span>.SetTargetProperty(ZoomLevel,</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">PropertyPath</span>(</li> <li> <span style="color: #2b91af;">Attachments</span>.MapZoomLevelProperty</li> <li style="background: #f3f3f3;"> )</li> <li> );</li> </ol> </div> </div> </div> Handy Attachments utility class <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:0d9e5168-53f4-4c08-9240-5eae23f2c779" class="wlWriterSmartContent" style="margin: 0px; display: inline; float: left; padding: 0px;"> <div style="font-family: &amp;amp;amp; color: #000; font-size: 10pt; border: #000080 1px solid;"> <div style="padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana, tahoma, arial, sans-serif; background: #000080; color: #fff; font-weight: bold; padding-top: 2px;">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto;"> <ol style="padding-bottom: 0px; margin: 0px 0px 0px 2.5em; padding-left: 5px; padding-right: 0px; background: #ffffff; padding-top: 0px;"> <li><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> <span style="color: #2b91af;">Attachments</span></li> <li style="background: #f3f3f3;">{</li> <li> <span style="color: #008000;">// Map Zoom level property</span></li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">readonly</span> <span style="color: #2b91af;">DependencyProperty</span></li> <li> MapZoomLevelProperty =</li> <li style="background: #f3f3f3;"> <span style="color: #2b91af;">DependencyProperty</span>.RegisterAttached(<span style="color: #a31515;">"MapZoomLevel"</span>,</li> <li> <span style="color: #0000ff;">typeof</span>(<span style="color: #0000ff;">double</span>), <span style="color: #0000ff;">typeof</span>(<span style="color: #2b91af;">Attachments</span>),</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">PropertyMetadata</span>(</li> <li> <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">PropertyChangedCallback</span>(OnMapZoomLevelChanged)));</li> <li> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> SetMapZoomLevel(<span style="color: #2b91af;">DependencyObject</span> o,</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">double</span> value)</li> <li> {</li> <li style="background: #f3f3f3;"> o.SetValue(MapZoomLevelProperty, value);</li> <li> }</li> <li> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">double</span> GetMapZoomLevel(<span style="color: #2b91af;">DependencyObject</span> o)</li> <li style="background: #f3f3f3;"> {</li> <li> <span style="color: #0000ff;">return</span> (<span style="color: #0000ff;">double</span>)o.GetValue(MapZoomLevelProperty);</li> <li style="background: #f3f3f3;"> }</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> OnMapZoomLevelChanged(<span style="color: #2b91af;">DependencyObject</span> d,</li> <li> <span style="color: #2b91af;">DependencyPropertyChangedEventArgs</span> e)</li> <li style="background: #f3f3f3;"> {</li> <li> <span style="color: #0000ff;">double</span> z = (<span style="color: #0000ff;">double</span>)((<span style="color: #2b91af;">Map</span>)d).ZoomLevel;</li> <li style="background: #f3f3f3;"> z = (<span style="color: #0000ff;">double</span>)e.NewValue;</li> <li> ((<span style="color: #2b91af;">Map</span>)d).ZoomLevel = z;</li> <li style="background: #f3f3f3;"> }</li> <li>}</li> </ol> </div> </div> </div> Most of this was gleaned from [<a href="http://www.conceptdevelopment.net/Silverlight/VEMap05/">http://www.conceptdevelopment.net/Silverlight/VEMap05/</a>] and <a href="[http://bryantlikes.com/archive/2009/03/23/animation-hack-using-attached-properties-in-silverlight.aspx">[http://bryantlikes.com/archive/2009/03/23/animation-hack-using-attached-properties-in-silverlight.aspx</a>]

Just to make things a little more realistic the Map object centre Location property can be animated to provide wind shear.Instead of animating the Latitude and Longitude separately a Point based DependencyProperty can be created.

<div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:8be5bc17-8b0e-445f-9fd7-0b372553c392" class="wlWriterSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;"> <div style="font-family: &amp;amp;amp; color: #000; font-size: 10pt; border: #000080 1px solid;"> <div style="padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana, tahoma, arial, sans-serif; background: #000080; color: #fff; font-weight: bold; padding-top: 2px;">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto;"> <ol style="padding-bottom: 0px; margin: 0px 0px 0px 2em; padding-left: 5px; padding-right: 0px; background: #ffffff; padding-top: 0px;"> <li><span style="color: #a31515;"> </span><span style="color: #0000ff;">&lt;</span><span style="color: #a31515;">Storyboard</span><span style="color: #ff0000;"> x</span><span style="color: #0000ff;">:</span><span style="color: #ff0000;">Name</span><span style="color: #0000ff;">="CenterMap"&gt;</span></li> <li style="background: #f3f3f3;"> <span style="color: #a31515;"> </span><span style="color: #0000ff;">&lt;</span><span style="color: #a31515;">PointAnimation</span></li> <li> <span style="color: #ff0000;"> x</span><span style="color: #0000ff;">:</span><span style="color: #ff0000;">Name</span><span style="color: #0000ff;">="CenterPoint"</span></li> <li style="background: #f3f3f3;"> <span style="color: #ff0000;"> Storyboard.TargetName</span><span style="color: #0000ff;">="MainMap"</span></li> <li> <span style="color: #ff0000;"> From</span><span style="color: #0000ff;">="5.0,50.0"</span></li> <li style="background: #f3f3f3;"> <span style="color: #ff0000;"> To</span><span style="color: #0000ff;">="-8.0,56.0"</span></li> <li> <span style="color: #ff0000;"> Duration</span><span style="color: #0000ff;">="0:0:14" /&gt;</span></li> <li style="background: #f3f3f3;"><span style="color: #a31515;"> </span><span style="color: #0000ff;">&lt;/</span><span style="color: #a31515;">Storyboard</span><span style="color: #0000ff;">&gt;</span></li> </ol> </div> </div> </div> Within your Silverlight control constructor. <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:73ff8289-46d5-4366-8f50-7f43d01de900" class="wlWriterSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;"> <div style="font-family: &amp;amp;amp; color: #000; font-size: 10pt; border: #000080 1px solid;"> <div style="padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana, tahoma, arial, sans-serif; background: #000080; color: #fff; font-weight: bold; padding-top: 2px;">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto;"> <ol style="padding-bottom: 0px; margin: 0px 0px 0px 2em; padding-left: 5px; padding-right: 0px; background: #ffffff; padding-top: 0px;"> <li><span style="color: #2b91af;">Storyboard</span>.SetTargetProperty(CenterPoint,</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">PropertyPath</span>(</li> <li> <span style="color: #2b91af;">Attachments</span>.MapCenterPositionProperty</li> <li style="background: #f3f3f3;"> )</li> <li> );</li> </ol> </div> </div> </div> New property for the Attachments utility class <div id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:fa5477e5-0aab-4072-99df-4b70ff947fc6" class="wlWriterSmartContent" style="margin: 0px; display: inline; float: none; padding: 0px;"> <div style="font-family: &amp;amp;amp; color: #000; font-size: 10pt; border: #000080 1px solid;"> <div style="padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana, tahoma, arial, sans-serif; background: #000080; color: #fff; font-weight: bold; padding-top: 2px;">Code Snippet</div> <div style="background: #ddd; max-height: 300px; overflow: auto;"> <ol style="padding-bottom: 0px; margin: 0px 0px 0px 2.5em; padding-left: 5px; padding-right: 0px; background: #ffffff; padding-top: 0px;"> <li><span style="color: #008000;">// Map Center Position Property as a Point</span></li> <li style="background: #f3f3f3;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">readonly</span> <span style="color: #2b91af;">DependencyProperty</span></li> <li> MapCenterPositionProperty =</li> <li style="background: #f3f3f3;"> <span style="color: #2b91af;">DependencyProperty</span>.RegisterAttached(</li> <li> <span style="color: #a31515;">"MapCenterPosition"</span>,</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">typeof</span>(<span style="color: #2b91af;">Point</span>),</li> <li> <span style="color: #0000ff;">typeof</span>(<span style="color: #2b91af;">Attachments</span>),</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">PropertyMetadata</span>(</li> <li> <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">PropertyChangedCallback</span>(</li> <li style="background: #f3f3f3;"> OnMapCenterPositionChanged)));</li> <li style="background: #f3f3f3;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> SetMapCenterPosition(</li> <li> <span style="color: #2b91af;">DependencyObject</span> o, <span style="color: #2b91af;">Point</span> value)</li> <li style="background: #f3f3f3;">{</li> <li> o.SetValue(MapCenterPositionProperty, value);</li> <li style="background: #f3f3f3;">}</li> <li style="background: #f3f3f3;"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #2b91af;">Point</span> GetMapCenterPosition(</li> <li> <span style="color: #2b91af;">DependencyObject</span> o)</li> <li style="background: #f3f3f3;">{</li> <li> <span style="color: #0000ff;">return</span> (<span style="color: #2b91af;">Point</span>)o.GetValue(MapCenterPositionProperty);</li> <li style="background: #f3f3f3;">}</li> <li style="background: #f3f3f3;"><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> OnMapCenterPositionChanged(</li> <li> <span style="color: #2b91af;">DependencyObject</span> d,</li> <li style="background: #f3f3f3;"> <span style="color: #2b91af;">DependencyPropertyChangedEventArgs</span> e)</li> <li>{</li> <li style="background: #f3f3f3;"> <span style="color: #2b91af;">Location</span> l = (<span style="color: #2b91af;">Location</span>)((<span style="color: #2b91af;">Map</span>)d).GetValue(</li> <li> <span style="color: #2b91af;">Map</span>.CenterProperty);</li> <li style="background: #f3f3f3;"> <span style="color: #2b91af;">Point</span> p = <span style="color: #0000ff;">new</span> <span style="color: #2b91af;">Point</span>(l.Latitude, l.Longitude);</li> <li> p = (<span style="color: #2b91af;">Point</span>)e.NewValue;</li> <li style="background: #f3f3f3;"> <span style="color: #0000ff;">double</span> z = (<span style="color: #0000ff;">double</span>)((<span style="color: #2b91af;">Map</span>)d).ZoomLevel;</li> <li> <span style="color: #008000;">// Y is Latitude, X is Longitude </span></li> <li style="background: #f3f3f3;"> ((<span style="color: #2b91af;">Map</span>)d).SetView(<span style="color: #0000ff;">new</span> <span style="color: #2b91af;">Location</span>(p.Y, p.X), z);</li> <li>}</li> </ol> </div> </div> </div> Now clip the Map to a circle and animate the containers Angle with a regular DoubleAnimation to create a truly sickening spiralling to the ground experience.

<img style="display: inline; border-width: 0px;" title="skydive2" src="http://earthware-website.azurewebsites.net/Content/images/wp-images/2010/06/skydive2.png" border="0" alt="skydive2" width="242" height="242" /> <img style="display: inline; border-width: 0px;" title="skydive3" src="http://earthware-website.azurewebsites.net/Content/images/wp-images/2010/06/skydive3.png" border="0" alt="skydive3" width="242" height="242" />

The smooth zooming and panning was used to great effect to navigate around the South Africa world cup football stadiums in time with HD video in our World Cup map <a href="http://www.theworldcupmap.com">http://www.theworldcupmap.com</a>

<a href="http://www.earthware.co.uk/demos/SkyDive" target="_blank"><img src="http://earthware-website.azurewebsites.net/Content/images/wp-images/postimages/butviewdemo.gif" alt="start skydive demo" /></a> <a href="http://earthware-website.azurewebsites.net/Content/images/wp-images/2010/07/SkyDive.zip" target="_blank"><img src="http://earthware-website.azurewebsites.net/Content/images/wp-images/2010/03/butdownloadcode1.gif" alt="download SkyDive project" /></a>

Close chatbot
Open chatbot
Open chatbot