Introduction
Google provides a JavaScript API for include maps with the same functions of maps.google.com in an HTML page.
The page where Google explains this API is here.
On the version v2, you need to register to obtain an API key for using the library, with the version v3 it's optional but it's recommended because the API has a limitation, you can only generate 25,000 maps per day, if you need more you need to pay so you need register and if you register you can:
- Obtain statistics of the maps generated per day
- Pay for additional maps (more than 25,000 per day)
- Restrict the use of your key to prevent use on unauthorized sites
To create your API key, visit the APIs Console and log in with your Google Account.
Background
The most basic example is the next:
<!--
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript"
src="http://maps.google.com.mx/maps/api/js?sensor=true&language="es""></script>
<script src='http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js'>
</script><script type="text/javascript">
function initialize() {
var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>
With the first line, you enables the HTML local file to fully test their compatibility with users' security settings.
You need 5 elements:
- The label
<meta>
specifies that the map should show in full screen and the user can't modify the size.
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
- The apis of Google:
<script src='http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/src/markerclusterer.js'></script>
<script type="text/javascript"
src="http://maps.google.com.mx/maps/api/js?sensor=true&language="es&key=your_key""></script>
For this example, I use a marker Cluster, with this marker you can display a large number of locations or markers for example 300 markers and the markers are grouped by zones.
The second script is the script for Google maps, the parameter sensor = true
indicates that the application uses a sensor to indentify the location of the user. The parameter of the language specifies the language for the instructions. And in the parameter of the key, you should include your API.
- You need include a location for including the map. Generally it is a
div
. In this example, the size of the map is the size of the page.
<div id="map_canvas" style="width:100%; height:100%"></div>
- The function for initializing and showing the map:
- For ubicate a map, you need the latitude and the longitude for the place that you want to show
- The options for the map, like the zoom, the map type:
ROADMAP
displays the default map of Google Maps
SATELLITE
displays the photographic map
HYBRID
displays a mix of photographic and default map
TERRAIN
displays physical relief tiles for displaying elevation and water features (mountains, rivers, etc.)
- For guaranteeing that the map shows after the page is created and shows correctly, you need load the map in the event load of the page.
<body onload="initialize()">
If the map doesn't show maybe the latitude and the longitude, it's a location in the sea or you could have a JavaScript error.
You can personalize a lot of things of the map, the style of the map, put a marker and an information window for the marker, the directions between 2 points by bicycle, auto, walk, the traffic.
For adding a marker, you can include the following code:
function addMarker( Lat, Long)
{
var latLng = new google.maps.LatLng(Lat, Long);
marker = new google.maps.Marker({
position: latLng,
icon: 'down2.png',
draggable: true,
animation: google.maps.Animation.DROP,
title:"Click for show the data of the client"
});
markers.push(marker);
marker.setMap(map);
}
google.maps.event.addListener(marker, 'dragend', function()
{
eventEndDragMarker(marker)
});
function eventEndDragMarker(shape)
{
var pos = new google.maps.LatLng;
pos = shape.getPosition();
endDragMarkerCS(pos.lat(), pos.lng());
}
You can specify an image for the marker, the animation, and the text that shows when the mouse is over the image. The option draggable : true
means that the user can move the marker to another location.
Next, I add a Listener for the marker to notify when the user end Drag the marker. With this event, I sent the new position to WPF Application.
For adding an info window that shows a text and images for the marker, you can include the following code:
var contentString = '<div id="content">'+
'<h1>[Client]</h1>'+
'<img src="/images/image.jpg width="200"
height="200" style="margin: 0 auto; display:block"/>'+
'<br/><br/>[Direction]'+
'</div>';
var infowindow = new google.maps.InfoWindow({
content: contentString
});
You can view the live example here.
You can show the directions between 2 points, for this you need the <div>
for the map and optionally, you can include a <div>
for the directions. The JavaScript function is:
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
var map;
var origin = new google.maps.LatLng(37.7699298, -122.4469157);
var destination = new google.maps.LatLng(37.7683909618184, -122.51089453697205);
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
var myOptions = {
zoom: 5,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: origin
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
directionsDisplay.setMap(map);
calcRoute();
directionsDisplay.setPanel(document.getElementById("directionsPanel"));
}
function calcRoute() {
var selectedMode = document.getElementById("mode").value;
var request = {
origin: origen,
destination: destino,
travelMode: google.maps.TravelMode[selectedMode]
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
}
You can view the live example here.
For including the map on WPF, I use a WebBrowser
Control, and I load an HTML file that I previously create, and I read the file and replace the latitudes and longitudes, and the text for the info Window.
The application of the demo shows the data of a client, the location of the client on the map, and other option to show the directions for arriving at the location of the client from the location of the company.
In the demo, I use a DockPanel
to automatically resize the map when the windows changes the size. I read the HTML page and find and replace the text like latLng
and origin
and destination
from the example. I set a short Uri because with long path, the WPF shows an error.
if (File.Exists(AppDomain.CurrentDomain.BaseDirectory + "html\\map.html"))
{
StreamReader objReader = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "html\\map.html");
string line = "";
line = objReader.ReadToEnd();
objReader.Close();
line = line.Replace("[Location]", tbLocation.Text);
line = line.Replace("[Client]", "25.520581,-105.40607");
line = line.Replace("[Image]", "client" + tbID.Text + ".png");
line = line.Replace("[Direction]", tbDirection.Text +
"<br />" + tbCity.Text + "," + tbState.Text);
StreamWriter page = File.CreateText(AppDomain.CurrentDomain.BaseDirectory + "html\\map2.html");
page.Write(line);
page.Close();
Uri uri = new Uri(AppDomain.CurrentDomain.BaseDirectory + "html\\map2.html");
webBrowser1.Navigate(uri);
}
Call a JavaScript Function from WPF Application
With the WPF Browser, you can invoke a JavaScript function in your HTML. Here is an example. You can pass parameter to a function in an array of objects.
private void Button_Click_1(object sender, RoutedEventArgs e)<br /> {
webBrowser1.InvokeScript("addMarker", new Object[] { 25.520581, -103.40607);
}
Call a WPF Function from JavaScript
With the instruction windows.external
you can invoke a WPF function from JavaScript, you need create a class with a COMVisibleAttribute
to true
and add the Object
to the WPFBrowser
.
Here is an example in the HTML JavaScript:
function endDragMarkerCS(lat, long) {
window.external.endDragMarkerCS( lat, long);
}
In the WPF application:
<WebBrowser DockPanel.Dock="Right"
Loaded="setupObjectForScripting" Name="webBrowser1" />
private void setupObjectForScripting(object sender, RoutedEventArgs e)
{
((WebBrowser)sender).ObjectForScripting = new HtmlInteropInternalTestClass();
}
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class HtmlInteropInternalTestClass
{
public void endDragMarkerCS(Decimal Lat, Decimal Lng)
{ ((MainWindow)Application.Current.MainWindow).tbLocation.Text = Math.Round(Lat,5) + "," +Math.Round(Lng,5);
}
}
Points of Interest
With the new API V3 of Google maps and a WebBrowser on .NET, you can Add Maps in your applications. The API provides a lot of configuration and with CSS, you can add more design to the maps for integrating in your WPF or Winforms applications. I prefer WPF because I'm learning WPF but it's similar on Winforms.
You can save the data of Latitude and Longitude of your clients in your database and it will be useful to add a map to location, a project of building or for sending articles to your clients.
Also, if you want, you can use the Bing Maps WPF Control with this component you can add the markers with .NET code without JavaScript and HTML page.