Recent Blog Posts RSS
ViaWindowsLive on Via Virtual Earth Blog
The new ViaWindowsLive community site has launched and features not only a definitive set of resources on all Live Services from Microsoft but also a special section on Virtual Earth including a new site gallery for you to upload your sites, new articles on Version 6, including getting started guide, an interactive quick guide, location finder and more. Subscribe to the VWL aggregated blog to stay in touch with everything Live Services related. Find all the great content from this site and much, much more. Explore how other Live Services can compliment Virtual Earth and your applications.
Version 5 URL changed - Error: 'VEMap' is undefined on Via Virtual Earth Blog
It has been reported that the old url to access the Version5 javascript for Virtual Earth no longer works. This is effecting sites worldwide.
The correct way to reference the Version 5 javascript is:
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5"></script>
If you have been effected a forum thread has been started here
Silverlight Virtual Earth viewer on Via Virtual Earth Blog
With the launch of silverlight yesterday I was digging around and found this viewer for Virtual Earth by Greg Schechter. It does use the 1.1 alpha of silverlight. It gives some interesting ideas for where Virtual Earth could be headed. Certainly the demo of the performance of silverlight compared to javascript for processing showed a significant increase. This could be very useful.
And of course on the gamer front check this out by Andy Beaulieu and shoot down some UFO's over Birdseye images.
John.
So much new Virtual Earth Imagery Worldwide. on Via Virtual Earth Blog
I subscribe to all the VE blogs and recently the posts about updated imagery has been more and more frequent.
The latest is here and for myself downunder we saw three updates, Canberra, Newcastle and Uluru:


Derek Chan posts 3 Articles in a month! on Via Virtual Earth Blog
A big thank you to the efforts of Derek Chan who posted his third VE article today (he actually had it ready weeks ago but had to wait for Mr Bottleneck here at VVE ;) )
The 3 articles are all relivant to Version 5 of Virtual Earth and deal with the Mini Map, debugging javascript and now custom pins in routes.
All these can now be found in our articles section.
If you have something to contribute send us an email.
John (The bottleneck)
Customizing your own Mini-Map RSS
The Virtual Earth 5.0 API includes a mini-map, which allows you to switch between road and hybrid display styles and shows you a zoomed out version of your current view. The purpose of the mini-map is to show you where the specific area that you are looking at is located within a larger geographic region (e.g. where a particular city is located within a state). Figure 1 shows a mini-map within a map in hybrid view, as seen on http://local.live.com.
Figure 1 – The mini-map as shown on http://local.live.com
It is not possible to customize the mini-map that is built into Virtual Earth through the API. You cannot switch the mini-map to aerial view, zoom in or out, resize it, or move it around. In addition, pushpins placed on the main VE map do not show up on the built-in mini-map, as shown in Figure 2.
Figure 2 – A pushpin plotted on a VE map is not reflected on the mini-map provided by the API
However, if you want to use a mini-map and you require additional functionality such as zooming, resizing, or visible pushpins, you can create your own mini-map and customize it as you see fit. By creating your own mini-map you will be able to add in the features missing from the built in version. In addition, you can also give your viewers the ability to view shapes added to the main map and identify road names while in birdseye mode (see Figure 3 and Figure 5).
Figure 3 – A pushpin as displayed on the customized mini-map can be created so that it appears on both main and mini-maps
In this article, I will demonstrate how to create a custom mini-map from scratch and add it to a Virtual Earth application.
Introduction
The Virtual Earth 5.0 API only allows you to turn on the mini-map feature in one way. To turn on the mini-map, you must call the VEMap.ShowMiniMap method, passing in x/y offsets and a VEMiniMapSize enumeration that specifies how large the map is. Unless you want to hack the API, there’s not much else that can be done with the built-in mini-map. The solution to this limitation is to generate your own customized mini-map, which is basically another instance of Virtual Earth running behind the main Virtual Earth map. You can interact with the custom mini-map easily, since the map instance carries over all the same properties as a regular VE map and you have full control over it The idea is quite simple: create a separate <div> tag that holds the mini-map and reflect any changes made to the main map onto the mini-map. The important points that I will cover are:
- Plotting out the mini-map
- Managing VE events
- Dragging the mini-map
- Managing shapes.
- Other possible additions that you may want to consider implementing.
Plotting out the Mini-Map
Start by creating the mini-map within a wrapper, which is a <div> tag that holds all any mini-map features such as zoom buttons including the actual map itself. It is absolutely vital that all the elements inside the wrapper are set with CSS absolute positioning (http://www.w3schools.com/css/pr_class_position.asp), and assigned with a top/left attribute (http://www.w3schools.com/css/pr_pos_top.asp). The <div> element must also be set to use absolute positioning in order to allow the mini-map to overlap the main VE map. Without absolute positioning, the components of the custom mini-map will not display correctly, as shown in Figure 4 .
Figure 4 - A mini-map where the <div> containing the map is not given a top attribute (firing a javascript error) and zoom in/zoom out <div> tags set to relative positioning.
Listing 1 shows the code for a sample <div> wrapped that contains the necessary code to create a custom mini-map, using absolute positioning. I’ve added a few technically unnecessary CSS attributes to improve the aesthetics, but you are free to adjust the code to your preference as long as you maintain the absolute positioning of all components, as mentioned previously.
<div id='MiniMapWrapper' style=" top:50px;left:90px;position:absolute">
<div id='Road' style="position:absolute; top:-22px; left:-10px; font-family:arial;color:black;
background-color:yellow; width:40px; height:10px; border-width: 2px;border-style: solid;"
onclick="minimap.SetMapStyle('r')">Road</div>
<div id='Aerial' style="position:absolute; top:-22px; left:33px; font-family:arial; color:black;
background-color:yellow; width:43px; height:10px; border-width: 2px;border-style: solid;"
onclick="minimap.SetMapStyle('a')">Aerial</div>
<div id='Hybrid' style="position:absolute; top:-22px; left:76px; font-family:arial; color:black;
background-color:yellow; width:45px; height:10px; border-width: 2px;border-style: solid;"
onclick="minimap.SetMapStyle('h')">Hybrid</div>
<div class="MiniHeader" style="position:absolute;left:1px;width:72px;"
onmousedown="dragStart(event, 'MiniMapWrapper')">Mini-Map</div>
<div id='myMiniMap' style="position:absolute; top:22px;left:1px; width:100px; height:100px;
border-width: 2px;border-style: solid;" ></div>
<div id='Close' style="position:absolute; top:1px; left:90px; color:white;"
onclick="document.getElementById('MiniMapWrapper').style.display='none'">X</div>
<div id='ZoomIn' style="position:absolute; top:125px; left:-10px; font-family:arial; color:black;
background-color:yellow; width:60px; height:10px; border-width: 2px;border-style: solid;"
onclick="ZoomIn()">Zoom In</div>
<div id='ZoomOut' style="position:absolute; top:125px; left:51px; font-family:arial; color:black;
background-color:yellow; width:69px; height:10px; border-width: 2px;border-style: solid;"
onclick="ZoomOut()">Zoom Out</div>
</div>
Listing 1 – The user interface for the mini-map
You also need to override some of the default CSS styles in order to remove all the Microsoft logos and copyright information from the mini-map (since those images are on the main map anyway, this shouldn’t be a legal problem). The CSS overrides are shown in Listing 2.
/* Removing the Microsoft logo, scalebar, and copyright logos off of the mini-map */
#myMiniMap .MSVE_PoweredByLogo
{
display:none;
}
#myMiniMap .MSVE_ScaleBar
{
display:none;
}
#myMiniMap .MSVE_ScaleBarLabel
{
display:none;
}
#myMiniMap .MSVE_Copyright
{
display:none;
}
Listing 2 – Removing the Microsoft logos and copyright images from the mini-map
Whenever the main VE map loads, so does the mini-map. You will also need to call the minimap.HideDashboard() method if you want to hide the dashboard on the mini-map, as shown in Listing 3
//Load both main map and mini-map
map = new VEMap('myMap');
map.LoadMap();
minimap = new VEMap('myMiniMap');
minimap.LoadMap(null,null,'h');
//Set the current zoom level of the mini-map
minizoomlevel = map.GetZoomLevel();
//Draw the minimap at its current location and hide dashboard
DrawMiniMap();
minimap.HideDashboard();
Listing 3 – Loading the mini-map and hiding the dashboard
Managing VE Events
When the user interacts with the main map (which has your mini-map on top of it) there are three cases that you must deal with:
a) User pans the main map; mini-map pans to the same location
b) User zooms in or out on the main map; mini-map zooms in or out to the same location (or may not do anything depending on your requirements)
c) User changes the main map style to birdseye – mini-map zooms to correct zoom level in birdseye
For a) and b), I’ve included a function named DrawMiniMap (shown in Listing 4), which re-pans the mini-map based on the center pixel point of the mini-map wrapper.
//Draw the minimap if user finishes panning or zoomed on the main map
map.AttachEvent("onmouseup", DrawMiniMap);
map.AttachEvent("onendzoom", DrawMiniMap);
function DrawMiniMap(e)
{
//Calculate the centroid of the mini-map by adding the left of the wrapper and mini-map <div>
//followed by Adding the top of the wrapper and mini-map <div>.
//Also take into account border of the mini-map <div>
var wrapperleft = parseInt(document.getElementById('MiniMapWrapper').style.left.replace("px",""));
var wrappertop = parseInt(document.getElementById('MiniMapWrapper').style.top.replace("px",""));
var left = parseInt(document.getElementById('myMiniMap').style.left.replace("px",""));
var top = parseInt(document.getElementById('myMiniMap').style.top.replace("px",""));
var width = parseInt(document.getElementById('myMiniMap').style.width.replace("px",""));
var height = parseInt(document.getElementById('myMiniMap').style.height.replace("px",""));
var borderwidth = parseInt(document.getElementById('myMiniMap').style.borderLeftWidth.replace("px",""));
var pixelcenterpoint = new VEPixel(wrapperleft + left + width/2 +
borderwidth * 2,wrappertop + top+height/2 + borderwidth * 2);
//I've set the mini-map to stay at the same zoom level of the main map but you can adjust the
//zoom level below
minimap.SetCenterAndZoom(map.PixelToLatLong(pixelcenterpoint),minizoomlevel);
document.getElementById('MainZoomLevel').innerHTML = "Main Zoom Level: "+ map.GetZoomLevel();
document.getElementById('MiniZoomLevel').innerHTML = "Mini Zoom Level: "+ minizoomlevel;
}
Listing 4 – Drawing the mini-map and maintaining the zoom level
For item c), when the user switches to birdseye view on the main map, you need to have the mini-map to zoom into the same level as the birdseye view, since the mini-map loses a lot of meaning when not at the correct zoom level. Birdseye level is equivalent to zoom level 17 on any other map style (road/aerial/hybrid). Therefore, the code in Listing 5 adds appropriate event handlers and sets the mini-map to zoom level 17 after switching it into birdseye view.
//If Enter into birdseye mode, adjust mini-map to correct level (zoom level 17)
map.AttachEvent("onchangemapstyle", MapChangeStyle);
function MapChangeStyle(e)
{
//have to check if you entered birdseye style on the main map
if(e.mapStyle == "o")
{
minizoomlevel = 17;
DrawMiniMap();
}
//if we change style of main map to anything else, reset the zoom level for mini-map
else
{
minizoomlevel = map.GetZoomLevel();
DrawMiniMap();
}
}
Listing 5 – Adjusting the mini-map to fit birdseye
Figure 5 – Birdseye tiles (main map) closely mirror their road/aerial/hybrid counterparts (mini-map)
Initially, birdseye imagery does not contain road information, so the viewer will not be able to determine the name of the actual street she is viewing. Figure 5 shows an overlay of hybrid tiles on top of birdseye imagery, which reveals a striking similarity.
Finally, to prevent the user from interacting with the mini-map (since it has the same properties of any regular Virtual Earth map), you need to add the following event handlers to disable users from clicking on the map:
//Disable user interaction with the mini-map
minimap.AttachEvent("onmousedown", DisableMiniMap);
minimap.AttachEvent("ondoubleclick", DisableMiniMap);
function DisableMiniMap()
{
return true;
}
Listing 6 – Disabling user interaction with the mini-map
Dragging the Mini-Map
Another useful function that you can add to a custom mini-map is to make it draggable, thereby allowing the user to browse around the map as though the mini-map were a magnifying glass. The main credit for this idea goes to Mike Hall at http://www.brainjar.com (the sample here was taken with permission), who wrote the initial code for making a dragging <div>. I made a couple of modifications in order to apply Mike’s code to the custom mini-map, namely boundary checking and a bit of map redrawing. Without boundary checking, the viewer can actually drag the mini-map past the main map, as shown in 6.
Figure 6 – A draggable mini-map without boundary checking
To prevent the user from experiencing the
behavior in 6, I’ve written some simple boundary checking code that will work
if the main map is located at the top left corner of the browser (Listing 7). If
it is necessary to move the main map away from the top left corner of the browser
you will need to write a much more robust boundary checking algorithm.
if (browser.isIE) {
//You will need more elaborate bound checking than this, but I've set the boundaries to 358/295 for now
if(window.event.clientX <= 358)
{
x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
}
else
{
x = 358;
}
if(window.event.clientY <= 295)
{
y = window.event.clientY + document.documentElement.scrollTop + document.body.scrollTop;
}
else
{
y = 295;
}
}
if (browser.isNS) {
if(event.clientX <= 358)
{
x = event.clientX + window.scrollX;
}
else
{
x = 358;
}
if(event.clientY <= 358)
{
y = event.clientY + window.scrollY;
}
else
{
y = 295;
}
}
Listing 7 – Simple boundary checking
Managing Shapes
Depending on your requirements, managing shapes on the mini-map may or may not be a challenge . Adding a shape to mini-map whenever one is added to the main map has two potential problems:
- High memory usage from having too many shapes on the map
- Properly adding shapes onto the mini-map
The first concern is a limitation with Virtual Earth 5.0 but the second issue, adding shapes onto the mini-map, is one that can be solved. However, the solution isn’t as straightforward as adding a shape to the main map, and then making a call to minimap.AddShape(shape) to insert it onto the minimap. There’s a nasty exception that gets thrown in the API backend when the call to mini.AddShape(shape) is made using the same shape object that was passed to the main map. The exception occurs because the re-used shape was already added to a shapelayer (the default generated one) when it was plotted on the main map, and therefore an exception is thrown when the application tries to re-insert the same shape into a new shapelayer. One solution is to re-generate the entire shape and add to the new shape to the mini-map, as shown in Listing 8
function AddPushpin()
{
var shape = new VEShape(VEShapeType.Pushpin, map.GetCenter());
shape.SetTitle('My pushpin');
shape.SetDescription('This is shape number '+pinid);
pinid++;
map.AddShape(shape);
var shape = new VEShape(VEShapeType.Pushpin, map.GetCenter());
shape.SetTitle('My pushpin');
shape.SetDescription('This is shape number '+pinid);
minimap.AddShape(shape);
}
Listing 8 – Adding a VEShape onto the mini-map
Going beyond simply adding shapes to the mini-map and actually manipulating shapes on both the mini-map and main map is out of the scope of this article.
Figure 7 – You can add shapes onto the mini-map as well as the main map
Future Considerations
It is possible to add a “birdseye” button onto the mini-map, although you must consider the challenges of checking for birdseye tiles and exactly what should happen to the main-map when the user sends the mini-map into birdseye.
Another nice feature would be to prevent the mini-map from overlapping the dashboard, since the mini-map demonstrated in this article completely hides the dashboard it is on top of it.
Other possible additional features include a button to allow the mini-map to go into 3D view (this feature would have serious performance considerations), or having multiple mini-maps up simultanously.
Something you may wish to consider is that while in birdseye mode the orientation can be changed so the mini-map will need to be rotated if the user is allowed to change from the default (north) orientation.
Figure 8 – Changing the orientation (in this case, south) using the sample code below will not be reflected on the mini-map (which is displaying north)
Conclusion
There are many powerful things that you can do with a customized mini-map, provided that that you have a relatively good understanding of CSS and VE events. You can take a look at the sample code here to see the final product (which works both in Firefox 1.5+ and Internet Explorer 6+).
Article contributed by Derek Chan (www.infusion.com). Have you got something to contribute?


