Today we released updates to the Microsoft Virtual Earth AJAX control and a new version of the Virtual Earth 3D map control. We’ve added a couple new methods for adding and removing pins (and DIVs) in the AJAX control; added performance improvements for AJAX and 3D; enhanced geocoding and parsing across the board (AJAX and Virtual Earth Web Service) and fixed a few bugs in the AJAX and 3D controls. There are lots of architectural changes behind the scenes that you won’t appreciate unless you’re inside Microsoft, so I will spare you the details of those. Now, that being said, for the AJAX map control we just upgraded Version 6.2, so you already have access to the new features and can start using them today without changing your link to Virtual Earth. Everyone is on 6.2 because we’ve either auto-upgraded you or you made the switch yourself. The Virtual Earth 3D control will require an update! Download the latest bits by going to your favorite Virtual Earth-powered web site (such as Live Search Maps) and click 3D and you will be prompted to install the latest bits.
Here’s a little breakdown of the new features for your reading pleasure:
Native Support for Internet Explorer 8 – with the release of Internet Explorer 8, you can now expect the Virtual Earth AJAX map control to function as expected. Download the latest version of Internet Explorer (8).
New Virtual Earth AJAX Map Control Methods – 2 new methods for advanced users to speed up performance and give control over rendering HTML elements on the map.
Geocoding and Parsing Improvements – our international users will be ecstatic with the geocoding and parsing engine improvements in addition to our new spatial geocoder which helps with accuracy of place name matches for locality queries. The countries / areas where improvements will be noticeable include United Kingdom, Germany, and Spain.
Extended Local Listings – in addition to our current United States local listings available in the Virtual Earth AJAX map control and Virtual Earth Web Service, we’ve extended the indices available in the map control to include listings from France, Italy and Germany.
New 3D Control – an upgrade of the Virtual Earth 3D control will be required to get access to the performance benefits and new features associated with the new 3D control. The performance benefits include compression of building textures for all 1.4 million buildings in the Virtual Earth 3D control (yes, 1.4 million). There are no changes or deletions for the public API for the following assemblies: Microsoft.MapPoint.Data.dll, Microsoft.MapPoint.Geometry.dll, Microsoft.MapPoint.Rendering3D.dll, Microsoft.MapPoint.Rendering3D.Utility.dll, Microsoft.MapPoint.UtilityPartialTrust.dll - redirects are included within so as not to break any applications that may be leveraging them. As always, expect some code samples from the Virtual Earth 3D Team’s Blog. As for new features, here’s an exhaustive list:
Updated Software Developer Kit – the Virtual Earth AJAX map control SDK on MSDN has been updated to reflect all of these changes.
Sample Code for New Virtual Earth AJAX Map Control Methods – the following sample illustrates the speed of rendering 500 pushpins on the AJAX map control using the new AddCustomLayer() method and provides the render time in milliseconds. There’s also a button for removing the DIV from the AJAX map control using the RemoveCustomLayer() method.
<!---Begin Sample Code for AddCustomLayer() and RemoveCustomLayer() -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Virtual Earth v6 API - Custom Layer Sample</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script> <script type="text/javascript">
var map = null; var myLayer = null; var numShapes = 500; //var numShapes = 1; var pinImage = 'http://dev.virtualearth.net/mapcontrol/v6.2/i/bin/6.2.2008082210001.41/pins/poi_usergenerated.gif'; var pinXOffset = -25 / 2; //width of pushpin image divided by 2 var pinYOffset = -30; //height of pushpin image since we want bottom point of image to point to LatLong var mapSurface = null; var previousZoomLevel = null;
var ll = new Array();
//Generate 500 random latlongs 20 degrees around the center function GenerateLatLongs() { ll = new Array(); var i = 0; var center = map.GetCenter(); for (; i < numShapes; ++i) { ll.push(new VELatLong(center.Latitude + Math.random() * 20 - 10, center.Longitude + Math.random() * 20 - 10)); //ll.push(new VELatLong(47.6205198, -122.349280)); } }
//RedrawShapes function RedrawShapes() { var s = new Array(); var i = 0; for (; i < numShapes; ++i) { pixel = map.LatLongToPixel(ll[i]); s.push("<img src='" + pinImage + "' style='position:absolute; left:" + (pixel.x + pinXOffset) + "px; top:" + (pixel.y + pinYOffset) + "px;' +/>"); } myLayer.innerHTML = s.join(''); }
function AddClicked() { var timeOutput = document.getElementById('TimeOutput'); timeOutput.innerHTML = '';
if (myLayer == null) { CreateLayer(); }
//Clear any existing shapes ClearShapes(); //Generate the Random LatLongs GenerateLatLongs();
var startTime = new Date(); //Draw the shapes RedrawShapes(); var totalTime = new Date() - startTime; timeOutput.innerHTML = totalTime + " ms"; }
//View Change Event handler function EventViewChange() { //if zoom level changed, then redraw the shapes, otherwise do nothing -- the map will position the pins on pan properly var currentZoomLevel = map.GetZoomLevel(); if (previousZoomLevel != currentZoomLevel) { previousZoomLevel = currentZoomLevel; ClearShapes(); RedrawShapes(); } }
//Event to respond to Birdseye changes function EventBirdseyeChanged() { //When Birdseye rotation changes, redraw the shapes ClearShapes(); RedrawShapes(); }
//Clear the shapes function ClearShapes() { myLayer.innerHTML = ''; }
//Start Zoom event handler function EventStartZoom() { //When zoom is staretd clear the shapes before zoom since they will need to be redrawn ClearShapes(); }
//Load Map Event Handler function EventMapLoaded() { //Store previous zoom level as current zoom level previousZoomLevel = map.GetZoomLevel();
CreateLayer();
//Register for events to update the custom layer map.AttachEvent("onchangeview", EventViewChange); map.AttachEvent("onstartzoom", EventStartZoom); map.AttachEvent("onobliquechange", EventBirdseyeChanged); } function CreateLayer() { //Create the custom layer for the map dynamically on the map surface myLayer = document.createElement('div'); myLayer.style.position = "absolute"; myLayer.style.top = "0px"; myLayer.style.left = "0px"; myLayer.style.width = "600px"; myLayer.style.height = "400px"; myLayer.style.zIndex = 1000; map.AddCustomLayer(myLayer); }
function CreateMap() { map = new VEMap('myMap'); map.onLoadMap = EventMapLoaded; map.LoadMap(); }
function RemoveClicked() { map.RemoveCustomLayer(myLayer); myLayer = null; } </script> </head> <body onload="CreateMap();"> <div id='myMap' style="position:relative; width:600px; height:400px;"></div> <br/> Click on "Add Shapes" to add 500 random shapes to the map." <br/> <br/> <input type="button" value="Add Custom Layer" onclick="AddClicked();"/> <input type="button" value="Remove Layer" onclick="RemoveClicked();"/> <br/> Time: <span id="TimeOutput"></span> </body> </html>
<!--- End Sample Code for AddCustomLayer() and RemoveCustomLayer() -->
Although, not as feature rich as some previous releases you can see a shifted focus on performance. Enjoy.
CP