×
Namespaces

Variants
Actions
(Difference between revisions)

HERE Maps API - How to cluster map markers

From Nokia Developer Wiki
Jump to: navigation, search
jasfox (Talk | contribs)
m (Jasfox - Remove banner)
hamishwillee (Talk | contribs)
m (Hamishwillee - Bot update - Fix ArticleMetaData)
Line 1: Line 1:
 
[[Category:Code Examples]][[Category:Nokia Maps]][[Category:JavaScript]]
 
[[Category:Code Examples]][[Category:Nokia Maps]][[Category:JavaScript]]
{{Abstract|This article explains how to create clustered markers and reduce cluttering on the map when dealing with a very large number of markers . }}
+
{{Abstract|This article explains how to create clustered markers and reduce cluttering on the map when dealing with a very large number of markers . }}
 
{{ArticleMetaData <!-- v1.2 -->
 
{{ArticleMetaData <!-- v1.2 -->
|sourcecode= [[Media:ClusterExample.zip|ClusterExample.zip]]
+
|sourcecode= [[Media:ClusterExample.zip
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 
|installfile= <!-- Link to installation file (e.g. [[Media:The Installation File.sis]]) -->
 +
|devices= Internet Explorer, Google Chrome, Firefox
 
|sdk= <!-- SDK(s) built and tested against (e.g. [http://linktosdkdownload/ Qt SDK 1.1.4]) -->
 
|sdk= <!-- SDK(s) built and tested against (e.g. [http://linktosdkdownload/ Qt SDK 1.1.4]) -->
|devices= Internet Explorer, Google Chrome , Firefox
 
 
|platform= Web
 
|platform= Web
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
 
|devicecompatability= <!-- Compatible devices e.g.: All* (must have internal GPS) -->
 
|dependencies= Nokia Maps 2.2.0
 
|dependencies= Nokia Maps 2.2.0
|signing=<!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
+
|signing= <!-- Signing requirements - empty or one of: Self-Signed, DevCert, Manufacturer -->
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
 
|capabilities= <!-- Capabilities required by the article/code example (e.g. Location, NetworkServices. -->
|keywords= Nokia Maps, Marker, Cluster , Large Dataset
+
|keywords= Nokia Maps, Marker, Cluster, Large Dataset
 
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 
|language= <!-- Language category code for non-English topics - e.g. Lang-Chinese -->
 
|translated-by= <!-- [[User:XXXX]] -->
 
|translated-by= <!-- [[User:XXXX]] -->
|translated-from-title= <!-- Title only -->  
+
|translated-from-title= <!-- Title only -->
 
|translated-from-id= <!-- Id of translated revision -->
 
|translated-from-id= <!-- Id of translated revision -->
|review-by=<!-- After re-review: [[User:username]] -->
+
|review-by= <!-- After re-review: [[User:username]] -->
 
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 
|review-timestamp= <!-- After re-review: YYYYMMDD -->
 
|update-by= <!-- After significant update: [[User:username]]-->
 
|update-by= <!-- After significant update: [[User:username]]-->
 
|update-timestamp= <!-- After significant update: YYYYMMDD -->
 
|update-timestamp= <!-- After significant update: YYYYMMDD -->
 
|creationdate= 20120612
 
|creationdate= 20120612
|author= [[User:jasfox]]
+
|author= [[User:jasfox]]
 
}}
 
}}
 
{{SeeAlso|
 
{{SeeAlso|
 
*  [http://api.maps.nokia.com/ Nokia Maps API]  
 
*  [http://api.maps.nokia.com/ Nokia Maps API]  
* [http://api.maps.nokia.com/en/playground/examples/maps/map_objects/customsvgmarker.html Custom SVG graphics]
+
* [http://api.maps.nokia.com/en/playground/examples/maps/map_objects/customsvgmarker.html Custom SVG graphics]
 
* [http://api.maps.nokia.com/en/playground/examples/maps/heatmap/valueheatmap.html Rendering a value based heat map]
 
* [http://api.maps.nokia.com/en/playground/examples/maps/heatmap/valueheatmap.html Rendering a value based heat map]
 
* [http://googlegeodevelopers.blogspot.fi/2009/04/markerclusterer-solution-to-too-many.html Original blog post - "A Solution to too many Markers"]
 
* [http://googlegeodevelopers.blogspot.fi/2009/04/markerclusterer-solution-to-too-many.html Original blog post - "A Solution to too many Markers"]
Line 31: Line 31:
  
 
== Introduction ==
 
== Introduction ==
When displaying a very large number of markers, it is likely that the map display will look very cluttered.  It can be difficult to understand geographical distribution of the given data set, and performance will be reduced as each marker will take time to be rendered. What is required is a method of display the data appropriately at different zooms, showing more details as the user drills down to display a smaller area. Marker '''clustering''' achieves this by summarizing the data at higher zoom levels. An illustration of the problem and its solution can be seen below.
+
When displaying a very large number of markers, it is likely that the map display will look very cluttered.  It can be difficult to understand geographical distribution of the given data set, and performance will be reduced as each marker will take time to be rendered. What is required is a method of display the data appropriately at different zooms, showing more details as the user drills down to display a smaller area. Marker '''clustering''' achieves this by summarizing the data at higher zoom levels. An illustration of the problem and its solution can be seen below.
  
  
Line 47: Line 47:
 
| [[File:ClusterMap1.png]]
 
| [[File:ClusterMap1.png]]
 
|-
 
|-
| Cluster Map at low zoom summarizing 2000 Markers distributed between
+
| Cluster Map at low zoom summarizing 2000 Markers distributed between
 
Texas and the Eastern Seaboard of the U.S.A.
 
Texas and the Eastern Seaboard of the U.S.A.
 
|}
 
|}
Line 61: Line 61:
  
 
== Code Commentary ==
 
== Code Commentary ==
The coded example provided is based upon an [http://googlegeodevelopers.blogspot.fi/2009/04/markerclusterer-solution-to-too-many.html Original Library] for the Google Maps API. Fortunately, the code is available under an [http://www.apache.org/licenses/LICENSE-2.0 Apache License], which means that it can be freely modified provided that an attribution remains. The Nokia Maps example is a derivative work which has been modified to work with the Nokia Maps API.
+
The coded example provided is based upon an [http://googlegeodevelopers.blogspot.fi/2009/04/markerclusterer-solution-to-too-many.html Original Library] for the Google Maps API. Fortunately, the code is available under an [http://www.apache.org/licenses/LICENSE-2.0 Apache License], which means that it can be freely modified provided that an attribution remains. The Nokia Maps example is a derivative work which has been modified to work with the Nokia Maps API.
  
 
The code works by making a re-calculation whenever the view port is moved, or the zoom level changed, this can be achieved by adding in a {{Icode|eventListener}} to the  '''mapviewchangeend''' {{Icode| Event}} and an {{Icode|observer}} to the '''zoomLevel''' property,
 
The code works by making a re-calculation whenever the view port is moved, or the zoom level changed, this can be achieved by adding in a {{Icode|eventListener}} to the  '''mapviewchangeend''' {{Icode| Event}} and an {{Icode|observer}} to the '''zoomLevel''' property,
Line 74: Line 74:
 
</code>
 
</code>
  
When the view port is changed, the array of all {{Icode|markers}} is distributed into two buckets, those withing the current view port and those left outside - Only those which remain on screen are processed further. Each {{Icode|marker}} left on screen is tested to see if it is close to any {{Icode|markers}} processed previously. If so it is added to that cluster, otherwise it is added to its own cluster. Essentially the flow of this code is unchanged form the original example. If a cluster has more than one marker, the cluster is rendered using [http://api.maps.nokia.com/en/playground/examples/maps/map_objects/customsvgmarker.html SVG graphics]
+
When the view port is changed, the array of all {{Icode|markers}} is distributed into two buckets, those withing the current view port and those left outside - Only those which remain on screen are processed further. Each {{Icode|marker}} left on screen is tested to see if it is close to any {{Icode|markers}} processed previously. If so it is added to that cluster, otherwise it is added to its own cluster. Essentially the flow of this code is unchanged form the original example. If a cluster has more than one marker, the cluster is rendered using [http://api.maps.nokia.com/en/playground/examples/maps/map_objects/customsvgmarker.html SVG graphics]
  
 
<code javascript>
 
<code javascript>
Line 95: Line 95:
 
</code>
 
</code>
  
The color and marker count placeholders are filled in when the image is returned:
+
The color and marker count placeholders are filled in when the image is returned:
  
 
<code javascript>
 
<code javascript>
Line 125: Line 125:
 
</code>
 
</code>
 
== How to use the marker clusterer library  ==
 
== How to use the marker clusterer library  ==
The marker clusterer library is available as a separate JavaScript file. To use it, include a link to the file in the {{Icode|&lt;header&gt;}} of your page.
+
The marker clusterer library is available as a separate JavaScript file. To use it, include a link to the file in the {{Icode|&lt;header&gt;}} of your page.
 
<code javascript>
 
<code javascript>
 
<script type="text/javascript" charset="UTF-8" src="./markerclusterer.js"></script>
 
<script type="text/javascript" charset="UTF-8" src="./markerclusterer.js"></script>
Line 135: Line 135:
 
var markers = [];
 
var markers = [];
 
for (var i = 0; i  < size; i++){
 
for (var i = 0; i  < size; i++){
var marker =  new nokia.maps.map.StandardMarker (randomPointNear (lat, long , spread) );
+
var marker =  new nokia.maps.map.StandardMarker (randomPointNear (lat, long, spread) );
 
markers.push(marker);
 
markers.push(marker);
 
}
 
}
Line 143: Line 143:
  
 
== Summary ==
 
== Summary ==
The [[Media:ClusterExample.zip|Code Example]]  adds 7000 random markers to a map and demonstrates the use of the {{Icode|MarkerClusterer}}  on a Nokia Map. This is a '''client''' side library which works reasonably well for a large number of markers,  but performance is reduced when the number of markers reaches the tens of thousands,  where it starts to trigger "slow Script" dialogs in Internet Explorer for example. 'The performance of  '''client''' side libraries is inextricably linked to the performance of the web browser used. For even larger numbers of markers the only solution would be to trigger the calculations '''server''' side instead, to introduce view port based {{Icode|marker}} management.
+
The [[Media:ClusterExample.zip|Code Example]]  adds 7000 random markers to a map and demonstrates the use of the {{Icode|MarkerClusterer}}  on a Nokia Map. This is a '''client''' side library which works reasonably well for a large number of markers,  but performance is reduced when the number of markers reaches the tens of thousands,  where it starts to trigger "slow Script" dialogs in Internet Explorer for example. 'The performance of  '''client''' side libraries is inextricably linked to the performance of the web browser used. For even larger numbers of markers the only solution would be to trigger the calculations '''server''' side instead, to introduce view port based {{Icode|marker}} management.

Revision as of 03:26, 14 June 2012

This article explains how to create clustered markers and reduce cluttering on the map when dealing with a very large number of markers . {{ArticleMetaData |sourcecode= [[Media:ClusterExample.zip |installfile= |devices= Internet Explorer, Google Chrome, Firefox |sdk= |platform= Web |devicecompatability= |dependencies= Nokia Maps 2.2.0 |signing= |capabilities= |keywords= Nokia Maps, Marker, Cluster, Large Dataset |language= |translated-by= |translated-from-title= |translated-from-id= |review-by= |review-timestamp= |update-by= |update-timestamp= |creationdate= 20120612 |author= jasfox }}

Contents

Introduction

When displaying a very large number of markers, it is likely that the map display will look very cluttered. It can be difficult to understand geographical distribution of the given data set, and performance will be reduced as each marker will take time to be rendered. What is required is a method of display the data appropriately at different zooms, showing more details as the user drills down to display a smaller area. Marker clustering achieves this by summarizing the data at higher zoom levels. An illustration of the problem and its solution can be seen below.


UnClusteredMap.png
Map at low zoom displaying 2000 Markers distributed between

Texas and the Eastern Seaboard of the U.S.A.


ClusterMap1.png
Cluster Map at low zoom summarizing 2000 Markers distributed between

Texas and the Eastern Seaboard of the U.S.A.


ClusterMap2.png
Cluster map at a higher zoom, showing the Eastern Seaboard only


Code Commentary

The coded example provided is based upon an Original Library for the Google Maps API. Fortunately, the code is available under an Apache License, which means that it can be freely modified provided that an attribution remains. The Nokia Maps example is a derivative work which has been modified to work with the Nokia Maps API.

The code works by making a re-calculation whenever the view port is moved, or the zoom level changed, this can be achieved by adding in a eventListener to the mapviewchangeend Event and an observer to the zoomLevel property,

 var eventHandler = function (evt) {     
me_.resetViewport();
};
 
map_.addListener("mapviewchangeend", eventHandler);
map_.addObserver("zoomLevel", eventHandler);

When the view port is changed, the array of all markers is distributed into two buckets, those withing the current view port and those left outside - Only those which remain on screen are processed further. Each marker left on screen is tested to see if it is close to any markers processed previously. If so it is added to that cluster, otherwise it is added to its own cluster. Essentially the flow of this code is unchanged form the original example. If a cluster has more than one marker, the cluster is rendered using SVG graphics

var markerIcon = createIcon(this.getTotalMarkers());
clusterMarker_ = new nokia.maps.map.Marker(center_ ,
{icon: markerIcon}
);
map_.objects.add ( clusterMarker_);

The SVG graphic consists of three concentric circles with the marker count within it.

'<svg width="39" height="39" xmlns="http://www.w3.org/2000/svg">' +
'<circle stroke="#FFF" fill="__MAINCOLOR__" cx="19" cy="19" r="19" stroke-width="2" />' +
'<circle stroke="#FFF" fill="__MAINCOLOR__" cx="19" cy="19" r="15" stroke-width="2"/>' +
'<circle stroke="#FFF" fill="__MAINCOLOR__" cx="19" cy="19" r="11" stroke-width="2"/>' +
'<text x="19" y="23" font-size="10pt" font-family="arial" font-weight="bold" text-anchor="middle" fill="#FFF" textContent="__TEXTCONTENT__">__TEXT__</text>' +
'</svg>

The color and marker count placeholders are filled in when the image is returned:

var stops = {
"0": "#8A8A8A", //Grey for 0-10
"10": "#CACA00", //Yellow for 11-50
"50": "#00CC00", //Green for 51-100
"100": "#0000CC", //Blue for 101-200
"200": "#CC00CC", //Purple for 201-500
"500": "#FF0000" //Red for over 500
};
var svgParser = new nokia.maps.gfx.SvgParser();
 
createIcon = function (count, mainColor) {
 
[...]
for (var i in stops) {
if (count > i){
color = stops[i];
}
}
 
var svg = iconSVG[digit]
.replace(/__TEXTCONTENT__/g, count)
.replace(/__TEXT__/g, count)
.replace(/__MAINCOLOR__/g, color);
return new nokia.maps.gfx.GraphicsImage(svgParser.parseSvg(svg));
};

How to use the marker clusterer library

The marker clusterer library is available as a separate JavaScript file. To use it, include a link to the file in the <header> of your page.

<script type="text/javascript" charset="UTF-8" src="./markerclusterer.js"></script>

To add the markers place them into an array, and then create the MarkerClusterer as shown, passing in the MapDisplay and the array.

var markers = [];
for (var i = 0; i < size; i++){
var marker = new nokia.maps.map.StandardMarker (randomPointNear (lat, long, spread) );
markers.push(marker);
}
 
var markerCluster = new MarkerClusterer(display, markers);

Summary

The Code Example adds 7000 random markers to a map and demonstrates the use of the MarkerClusterer on a Nokia Map. This is a client side library which works reasonably well for a large number of markers, but performance is reduced when the number of markers reaches the tens of thousands, where it starts to trigger "slow Script" dialogs in Internet Explorer for example. 'The performance of client side libraries is inextricably linked to the performance of the web browser used. For even larger numbers of markers the only solution would be to trigger the calculations server side instead, to introduce view port based marker management.

569 page views in the last 30 days.