Bing Maps is a very powerful mapping platform that is often used for creating engaging user experiences. The fluid interactive maps make for a great canvas when visualizing location based data. In this blog post we are going to take a look at how to make the user experience a little more engaging by adding custom animations that can be used in both web and Windows Store apps.
Full source code for this blog post can be found in the MSDN Code Samples here.
Setting up the base project
Creating a Web based Project
If you would like to create a web based app open Visual Studio and create a new ASP.NET Web Application called AnimatedMaps.
Next, select the Empty template. We will be creating a basic web app to keep things simple.
Creating a Windows Store Project
Setting up the UI
If you are creating a web based application update the default.html file with the following HTML:
If you are creating a Windows Store app update the default.html file with the following HTML:
Next open the default.css file and update it with the following styles:
If you try to run the application at this point you won’t see too much as the map hasn’t been loaded. We will add the code to load the map to the AnimatedMap.js file. In addition to this we will also include a couple of global variables that we will use later and event handlers for all of the buttons. We will add the logic for the clearing the map as well. When we clear the map we will also stop any current animations that might be running. Update the AnimatedMap.js file with the following code:
If you run the application you will see the map load up and a bunch of buttons appearing in a panel like this:
Creating Animations using CSS
You can create fairly complex animations in web based apps using CSS3 animations and transitions. However there are some limitations. The first is that only modern browsers support CSS3. Older browsers will ignore these CSS styles. The second one limitation is that we can only modify CSS properties.
There are two ways you can make use of CSS3 to animate pushpins in Bing Maps. The first method consists of creating a standard pushpin and setting the typeName property to the name of a CSS class. By doing this Bing Maps will use the typeName value to set the class property of the generated pushpin HTML. For example, if we had a CSS style called “scaleStyle” we could assign this to a pushpin like so:
The second method is to create a custom HTML pushpin and set the CSS class on one f the elements way. For example:
To try this out default.css file and add the following CSS style. This CSS style is designed to scale an HTML element to twice its size when the mouse hovers over it.
Next open the AnimatedMaps.js file and update the ScalingPin function with the following code:
If you run the app and press the “Scale on Hover” button a pushpin will appear in the center of the map. If you then hover your mouse over the pushpin you will notice that it grows to be twice its size. When you hover off the pushpin it goes back to its original size. Here is an animated gif that demonstrates this animation:
Creating an Animation Module
Now if you looked through all the HTML in the default.html file we created earlier you may have noticed that we registered the module and loaded in the code using a script reference like this:
You may have also noticed in the GetMap function in the AnimatedMap.js file the following code:
This code loads the module if it wasn’t already loaded. We can also add a callback as an option to this function that will be fired after the module is loaded. Since we don’t need to worry about code possibly running before the module is loaded we don’t need to worry about using a callback. At this point we have the base module created, however it’s doesn’t do much at the moment as we haven’t exposed any public functions yet. We will add a number of different functions to this module as we take a look at different types of animations.
Now that we have a nice reusable function to help us create simple animations it’s time to create an actual animations. To start off with we will look at simple pushpin animations. The first animation we will create will drop the pushpin from a specified pixel height above the map to its location on the map. Here is an animated gif of how this animation will look.
When using Bing Maps the HTML that is generated for the map and pushpins is not directly accessible through the API. It might be tempting to us a trick or two to grab the pushpin DOM element but it’s not needed. The Pushpin class has an anchor property which is used to specify the offset used to align the point of the pushpin to the proper location on the map. To create a drop animation we simply need to animate the y value of the anchor. Since this is a linear animation we can easily decrease the y value as progress of the animation increases.
The second animation we will be very similar to the first but instead of just dropping the pushpin we will have it bounce a couple of times to rest. To accomplish this we need to calculate different values for the height as the progress increases to create this bounce effect. After a bit of playing around with a graphing calculator I came up with the following formula:
This then generates a graph that looks like this:
Using this formula to animate the pushpins position results in a nice bounce effect as demonstrated in this animated gif:
To help keep things clean we will create the Bing.Maps.Animations.PushpinAnimations namespace for these animations. To do this, add the following code to the animation module.
We can now update our button handlers to make use of these new animations. Open the AnimatedMap.js file and update the DropPin, BouncePin, and Bounce4Pins functions with the following code.
If you run the application and press the buttons to drop or bounce a pushpin you will see a pushpin that falls to the center of the map just like the animated gif’s we saw before. If you press the button to animate 4 pushpins you will see 4 pushpins added to the map, one after another with a 500ms delay between them. This will look like this animated gif.
Creating Path Animations
The animations we have seen so far have been fairly simple and only run once. Before we dive into path animations it would be useful if we could not only play the animation but also pause or stop it. With a little work we can create a modified version of our simpleAnimation function that supports for play, pause and stop. The following code shows how to do this. Add this to the animation module.
We can now use this BaseAnimation class to power our more complex animations. One common type of animation I see developers struggle with when working with maps is animating along a path. To get a sense of the complexity involved consider the path between two locations on the map. If asked you to draw the shortest path between these two locations your first instinct might be to draw straight line, and visually you would be correct. However, the world is not flat and is actually an ellipsoid, yet most online maps show the world as a flat 2d rectangle. In order to accomplish this the map projects the 3D ellipsoid to this 2D map using what is called a Mercator projection. This ends up stretching the map out at the poles. So what does this all mean, well it means that the shortest distance between two locations on the map is rarely a straight line and is actually a curved path, commonly referred to as a geodesic path. Here is an image with a path connecting Seattle, New York, London and Italy. The red line connects these locations using straight lines while the purple line shows the equivalent geodesic path.
So which type of line do you want to animate with? Straight line paths are great for generic animations where you want to move things across the screen and only really care about the start and end point. Whereas geodesic lines are great for when you want the path to be spatially accurate, such as when animating the path of an airplane. It’s worth noting that when you are working with short distances the differences between are very minor.
Animating along a straight path is fairly easy. One method is to calculate the latitude and longitude differences between two locations and then divide these values by the number of frames in the animation to get a single frame offset values for latitude and longitude. Then when each frame is animated we take the last calculate coordinate and add these offsets to the latitude and longitude properties to get the new coordinate to advance the animation to.
Animating along a geodesic path is a bit more difficult. One of our Bing Maps MVP’s, Alastair Aitchison, wrote a great blog post on creating geodesic lines in Bing Maps. The process of creating a geodesic line consists of calculating a several midpoint locations that are between two points. This can be done by calculating the distance and bearing between the two locations. Once you have this you can divide the distance by the number of mid-points you want to have and then use the distance to each midpoint and the bearing between the two end points to calculate the coordinate of the mid-point location. To help us with this type of animation we will create some helper functions to do these calculations. Add the following code to the animation module. These functions allow you to calculate the Haversine distance between two locations (distance along curvature of the earth), bearing and a destination coordinate.
For the path animation we will create a class that extends from the base animation class we created earlier. When creating the path animation we will have this class take in four parameters;
- path - The path and consist of an array of Microsoft.Maps.Location objects.
- intervalCallback - A callback function that will be triggered on each frame interval. The interval callback function will receive three parameters; a midpoint location, the last path location that has been passed, and the frame index of the animation.
- isGeodesic - A Boolean value that indicates if the path animation should follow the geodesic path or a straight path.
- duration – The length of time the animation should take to complete.
When the path animation is created it will pre-calculate all the midpoint locations that the animation passes through. As a result little to no calculations needing to be performed when the animation advances a frame and thus should create a smooth animation. Add the following code for the path animation class to the animation module.
Now that the path animation class is created we can start implementing it. The first animation will move a pushpin along either a straight or geodesic the path. Update the MovePinOnPath function in the AnimatedMap.js file with the following code.
If you run the application and press the "Move Pin Along Path" button you will see a pushpin follow a straight line between the path locations. The following animated gif shows what this animation will look like. I’ve added in a red line as a reference of the straight line path.
If you press the "Move Pin Along Geodesic Path" button you will see a pushpin follow a geodesic path between the locations as you can see in the following animated gif. I’ve also included the straight line between the locations as a reference.
The next path animation we will implement will move the map along either a straight or geodesic path. Update the MovePinOnPath function in the AnimatedMap.js file with the following code.
Pressing the "Move Map Along Path" or "Move Map Along Geodesic Path" buttons you will see the map pan from one location to another, while changing zoom levels when it passes one of the path points. I have not included animated gif’s for this animation as they ended up being several megabytes in size.
The final path animation we will implement will animate the drawing of the path line. Update the DrawPath function in the AnimatedMap.js file with the following code.
If you run the application and press the "Draw Path" button you will see a pushpin follow a straight line between the path locations. The following animated gif shows what this animation will look like.
If you run the application and press the "Draw Geodesic Path" button you will see a pushpin follow a straight line between the path locations. The following animated gif shows what this animation will look like.
In this blog we have seen a number of different ways to animate data on Bing Maps. Let your imagination go wild and create some cool animations. As mentioned at the beginning of this blog post the full source code can be found in the MSDN Code Samples here.