×
Namespaces

Variants
Actions
(Difference between revisions)

HERE Maps API - How to create a KML data file

From Nokia Developer Wiki
Jump to: navigation, search
jasfox (Talk | contribs)
m (Jasfox - Updated example to use Nokia Maps API 2.2)
jasfox (Talk | contribs)
m (Jasfox - Update code commentary to reflect 2.2)
Line 94: Line 94:
  
 
<code javascript>
 
<code javascript>
searchManager.addObserver("state", function (observedManager, key, value) {
+
var searchManager = nokia.places.search.manager;
// If the search  has finished we can process the results
+
searchManager.geoCode({
if (value == "finished") {
+
                searchTerm : address.value,
// We check that at least one location has been found
+
                onComplete: onSearchComplete});
if (observedManager.locations.length > 0) {
+
</code>
 +
<code javascript>
 +
  var onSearchComplete = function (data, requestStatus) {
 +
        // If the search  has finished we can process the results
 +
          if (requestStatus == "OK") {
 
var markerData = new Object();
 
var markerData = new Object();
                        markerData.coords = observedManager.locations[0].displayPosition;
+
markerData.coords = data.location.position;  
                        markerData.title = map.objects.getLength() + 1;
+
markerData.title = map.objects.getLength() + 1;
                        markerData.description = description.value;
+
markerData.description = description.value;
                        markerData.name = name.value;
+
markerData.name = name.value;
                        markerData.address =  observedManager.locations[0].address.label;
+
                        document.getElementById("address").value =  markerData.address;
+
var address =  data.location.address;
                        addMarker(markerData);
+
                        /// Center the map on the new address.
+
markerData.address = "";
                        map.setCenter(observedManager.locations[0].displayPosition);
+
markerData.address = markerData.address + address.houseNumber + "\n";
}
+
markerData.address =  markerData.address + address.street + "\n";
} else if (value == "failed") {
+
markerData.address =  markerData.address + address.district + "\n";
alert("The search request failed.");
+
markerData.address =  markerData.address + address.city  + "\n";
}
+
markerData.address =  markerData.address + address.postalCode  + "\n";
});
+
markerData.address =  markerData.address + address.country;
 +
 +
addMarker(markerData);
 +
map.setCenter(data.location.position);
 +
 +
} else if (requestStatus == "ERROR") {
 +
alert("The search request failed.");
 +
}
 +
  };
 
</code>
 
</code>
 
The ''addMarkers()'' method actually adds the marker, which itself contains a copy of its own ''&lt;description&gt;'', ''&lt;address&gt;'', ''&lt;name&gt;'' & etc.  The marker has two events:
 
The ''addMarkers()'' method actually adds the marker, which itself contains a copy of its own ''&lt;description&gt;'', ''&lt;address&gt;'', ''&lt;name&gt;'' & etc.  The marker has two events:

Revision as of 13:07, 13 April 2012

This article explains how to create and edit a sample KML file using an online editor

Note.pngNote: in order to load a KML file successfully, the generated KML file should be hosted on the same domain as the JavaScript or the results may be unpredictable. Some browsers will automatically prohibit cross-domain access.

For example, if you are hosting at example.com, the final line of the JavaScript to load the KML will need to be:

kml.parseKML("http://example.com/" + "generated_kml_data_file.kml")
and both the KML loading HTML and the generated_kml_data_file.kml should be placed on http://example.com/

Article Metadata
Code ExampleTested with
Devices(s): Firefox, Internet Explorer, Google Chrome, Opera
Compatibility
Platform(s): Web Browser
Dependencies: Nokia Maps API 2.2.0
Article
Keywords: Nokia Maps, JavaScript, KML
Created: jasfox (10 Jan 2012)
Last edited: jasfox (13 Apr 2012)


Contents

Introduction

Keyhole Markup Language (KML) is an XML notation for geographic applications. The advantages of using KML are numerous, and have been listed in a previous article. The learning curve for KML is quite steep, requires a thorough understanding of both XML and mapping technologies, and since the reference documentation is written for 3d rather than 2d maps, much of it is irrelevant for simple mapping cases. All this means that some web developers are put off using KML, which is a pity, since KML is a standard data format, and the use of KML would result in the faster porting of a mapping applications to other platforms.

In order to remedy this, it would be useful to have a WYSIWYG point and click KML generator, where a map could be edited on screen, and the resultant KML file generated. The coded example below, attempts to fill this gap as shown.

KMLGenerator.png

WSYIWIG Editor

Initialisation

After the usual Map set up, we need to get a reference to each of the text boxes on the right of the screen. This is done by using document.getElementById()

var lat = document.getElementById("lat");
var lng = document.getElementById("lng");
var waypoints = document.getElementById("waypoints");
 
var title = document.getElementById("title");
var name = document.getElementById("name");
var description = document.getElementById("description");
var address = document.getElementById("address");
var icon = document.getElementById("icon");
var styleURL = document.getElementById("styleURL");
var lineStyleURL = document.getElementById('lineStyleURL');


Adding Markers

Markers can be added by pressing and holding down the mouse , this is the longpress event. An event handler has been added to the map to cope with this. The associated values such as <description> and <name> come directly from the text boxes defined above.

eventExEl.addListener("longpress", function(evt) {
var markerData = new Object();
markerData.coords = map.pixelToGeo(evt.targetX , evt.targetY);
markerData.title = map.objects.getLength() + 1;
markerData.description = description.value;
markerData.name = name.value;
markerData.address = address.value;
if (icon.value != ""){
markerData.icon = icon.value;
} else {
markerData.styleURL = styleURL.value;
}
addMarker(markerData);
 
}, false);

An alternative method of adding a marker is by adding an address. This uses the standard geoCoding service, and picks the first address found on the list. If your address is in the "wrong" format, just try making the address more general for now e.g.try the city only. The handler for geo-coding retrieves most of its information from the text boxes on the right hand side of the screen, but the address comes from the callback function.

var searchManager = nokia.places.search.manager;
searchManager.geoCode({
searchTerm : address.value,
onComplete: onSearchComplete});
  var onSearchComplete = function (data, requestStatus) {
// If the search has finished we can process the results
if (requestStatus == "OK") {
var markerData = new Object();
markerData.coords = data.location.position;
markerData.title = map.objects.getLength() + 1;
markerData.description = description.value;
markerData.name = name.value;
 
var address = data.location.address;
 
markerData.address = "";
markerData.address = markerData.address + address.houseNumber + "\n";
markerData.address = markerData.address + address.street + "\n";
markerData.address = markerData.address + address.district + "\n";
markerData.address = markerData.address + address.city + "\n";
markerData.address = markerData.address + address.postalCode + "\n";
markerData.address = markerData.address + address.country;
 
addMarker(markerData);
map.setCenter(data.location.position);
 
} else if (requestStatus == "ERROR") {
alert("The search request failed.");
}
};

The addMarkers() method actually adds the marker, which itself contains a copy of its own <description>, <address>, <name> & etc. The marker has two events:

  • an click event to display the data in text boxes for editing. This will also display an infobubble if the <description> field is set. A reference is kept on the currentMarker i.e. the last one selected.
  • a drag event to remove the infobubble if a marker is repositioned. All markers are defined as draggable so the user can reposition them as necessary.
function addMarker(markerData) {
var marker;
marker = new nokia.maps.map.StandardMarker(markerData.coords, {
text: markerData.title, //small title
draggable: true, //the marker is marked to be draggable
$data: markerData
 
});
 
marker.addListener("click" , function(evt) {
title.value = evt.target.text;
description.value = evt.target.$data.description;
address.value = evt.target.$data.address;
name.value = evt.target.$data.name;
styleURL.value = evt.target.$data.styleURL;
lat.innerHTML = evt.target.coordinate.latitude;
lng.innerHTML = evt.target.coordinate.longitude;
 
if ( evt.target.$data.description != ""){
infoBubbles.addBubble(evt.target.$data.description, evt.target.coordinate);
} else {
infoBubbles.removeBubble();
}
 
currentMarker = evt.target;
}, false);
 
marker.addListener("drag" , function(evt) { infoBubbles.removeBubble();}, false);
map.objects.add(marker);
}

Editing Marker Data

The editMarker() method, removes the currentMarker and adds another one with the current data from the text fields.

function editMarker() {
map.objects.remove(currentMarker);
infoBubbles.removeBubble();
var markerData = new Object();
markerData.coords = currentMarker.coordinate;
markerData.title = title.value;
markerData.description = description.value;
markerData.name = name.value;
markerData.address = address.value;
addMarker(markerData);
if ( description.value != ""){
infoBubbles.addBubble(markerData.description, markerData.coords );
}
}

Adding Polylines

It is impossible to create Polylines without first having some defined waypoints. The waypoints are merely geoCoordinates, so a button has been added to take the coordinates of the currentMarker and add them to an array. The marker is then removed to "tidy up" the display. When the create line from Waypoints button is pressed, the Polyline is created.

Warning.pngWarning: There is currently no method to delete waypoints or Polylines, this must be done by editing the KML directly.

var currentWaypoints = new Array();
map.objects.remove(currentMarker);
currentWaypoints.push( currentMarker.coordinate);
function createLineFromWaypoints() {
var lineData = new Object();
lineData.lineNo = map.objects.getLength() + 1;
lineData.waypoints = currentWaypoints ;
if( lineStyleURL.value != ""){
lineData.styleURL = lineStyleURL.value;
}
map.objects.add(new nokia.maps.map.Polyline(
lineData.waypoints,
{
color: "#22CA" ,
width: 5,
$data: lineData
}
));
currentWaypoints = new Array();
waypoints.innerHTML = "";
}

KML Generator

The saveMapObjects() method has been taken from the converting from JavaScript to KML article. All the map Objects currently on screen are iterated through and added as KML equivalents. In order to discourage the use of inline styles, a <styleURL> element has been added. This should refer to a <Style> somewhere else in the document, but obviously the <Style> has not been created, and must be added manually. An example of how to add a <styleURL> and an associated <Style> is shown below:

<Style id='smallIcon'>
<IconStyle>
<Icon>
<href>http:www.example.com/Icon-Small.png</href>
</Icon>
</IconStyle>
</Style>
<Placemark>
<Point><coordinates>-0.12759880162775517,51.50320703163743,0</coordinates></Point>
<styleUrl>#smallIcon</styleUrl>
</Placemark>

Since KML is just a form of XML, the generated file can be read using jQuery and applying the technique found in the Create map markers from XML data, the KML is in a known format, it is merely an excerise to extract the name from the <name> element, the address from the <address> element and so on. Two problems do need to be solved however. Firstly the geocoordinates are held as comma separated text, rather than individual <longitude> and <latittude> elements and secondly the description in the <description> element can contain formatted HTML and is held in a CDATA section. The first problem is dealt with my splitting the text by using the search() function:

var lng = coord.substring( 0 , coord.search(","));
coord = coord.substring(coord.search(",")+ 1);
var lat = coord.substring( 0 , coord.search(","));
markerData.coords = new nokia.maps.geo.Coordinate(parseFloat(lat), parseFloat(lng));

The CDATA section is deal with by stripping out the marker characters, and safely encoding the HTML data within it. The HTML is re-inflated using the escape() function when it is read.

while ( kml.search ("<!\\[CDATA\\[")  > - 1){
var from = kml.search ("<!\\[CDATA\\[");
var to= kml.search ("\\]\\]>");
kml = kml.substring(0, from) + escape(kml.substring(from + 9, to)) + kml.substring(to+ 3);
}
markerData.description =  unescape($(this).find('description').text());

Summary

It should be easy to create a simple KML file using the technique described above. Editing can be done either directly on the source KML or by moving elements around on the map. The generated file is valid KML, and can be displayed using the standard technique described in the How to display KML file data on the map. The generated KML could also be added to an existing file (provided that the header and <Document> lines are not included.

248 page views in the last 30 days.