×
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 - links)
jasfox (Talk | contribs)
m (Jasfox - Update links)
 
(16 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Code Examples]][[Category:Nokia Maps]][[Category:JavaScript]]
+
[[Category:Code Examples]][[Category:HERE Maps]][[Category:JavaScript]]
 
{{Abstract|This article explains how to create and style clustered markers and reduce cluttering on the map when dealing with a very large number of markers . }}
 
{{Abstract|This article explains how to create and style 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]]
+
|sourcecode= [https://github.com/heremaps/examples/blob/master/maps_api_for_javascript/advanced-examples/700-markers-simple-clustering.html 700-markers-simple-clustering.html] [https://github.com/heremaps/examples/blob/master/maps_api_for_javascript/advanced-examples/700-markers-clustering-with-zoom.html 700-markers-clustering-with-zoom.html] [https://github.com/heremaps/examples/blob/master/maps_api_for_javascript/advanced-examples/700-markers-clustering-with-theme.html 700-markers-clustering-with-theme.html]
 
|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
 
|devices= Internet Explorer, Google Chrome, Firefox
Line 8: Line 8:
 
|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.3
+
|dependencies= HERE Maps 2.5.3 or higher
 
|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= HERE 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]] -->
Line 24: Line 24:
 
}}
 
}}
 
{{SeeAlso|
 
{{SeeAlso|
* [http://developer.here.net/javascript_api Nokia Maps API]
+
* [http://developer.here.net/javascript_api HERE Maps API]
* [[Nokia Maps API - Short introduction to observable lists|Introduction to observable lists]]
+
* [[HERE Maps API - Short introduction to observable lists|Introduction to observable lists]]
 
* [http://developer.here.net/apiexplorer/examples/api-for-js/markers/svg-marker.html Custom SVG graphics]
 
* [http://developer.here.net/apiexplorer/examples/api-for-js/markers/svg-marker.html Custom SVG graphics]
 
* [http://developer.here.net/apiexplorer/examples/api-for-js/data-visualization/map-with-value-heat-map.html Rendering a value based heat map]
 
* [http://developer.here.net/apiexplorer/examples/api-for-js/data-visualization/map-with-value-heat-map.html Rendering a value based heat map]
Line 31: Line 31:
  
  
* [http://developer.here.net/apiexplorer/examples/api-for-js/data-visualization/custom-cluster-theme.html Cluster Themes]
+
* [http://developer.here.com/apiexplorer/examples/api-for-js/markers/cluster-markers.html Cluster Example]
* [[Nokia Maps API - How to create a custom overlay|How to create a custom map overlay]]
+
* [[HERE Maps API - How to create a custom overlay]]
 
* [http://developer.here.net/apiexplorer/examples/api-for-js/demos/overlay.html Custom overlay tile provider example]
 
* [http://developer.here.net/apiexplorer/examples/api-for-js/demos/overlay.html Custom overlay tile provider example]
 
  }}
 
  }}
  
 
{{Note |
 
{{Note |
Marker clustering has been supported within the Nokia Maps API for JavaScript itself since version 2.2.3 of the library. See the following link for examples
+
Marker clustering has been supported within the HERE Maps API for JavaScript itself since version 2.2.3 of the library. See the following link for examples
* [http://developer.here.net/apiexplorer/examples/api-for-js/data-visualization/custom-cluster-theme.html Cluster Themes]
+
* [http://developer.here.com/apiexplorer/examples/api-for-js/markers/cluster-markers.htmll Cluster Example]
 
}}
 
}}
  
Line 49: Line 49:
 
| [[File:UnClusteredMap.png]]
 
| [[File:UnClusteredMap.png]]
 
|-
 
|-
| Map at low zoom displaying 2000 Markers distributed between
+
| Map at low zoom displaying 7000 Markers distributed between
Texas and the Eastern Seaboard of the U.S.A.
+
Europe, Mexico, Texas and the Eastern Seaboard of the U.S.A.
 +
|-
 +
| Working Example illustrating the issue:
 +
 
 +
http://rawgithub.com/heremaps/examples/master/maps_api_for_javascript/advanced-examples/700-markers-unclustered.html
 
|}
 
|}
  
 +
== Simple Clustering Example ==
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 58: Line 63:
 
| [[File:ClusterMap1.png]]
 
| [[File:ClusterMap1.png]]
 
|-
 
|-
| Cluster Map at low zoom summarizing 2000 Markers distributed between
+
| Cluster Map at low zoom summarizing 7000 Markers distributed between
Texas and the Eastern Seaboard of the U.S.A.
+
Europe, Mexico, Texas and the Eastern Seaboard of the U.S.A.
 
|}
 
|}
  
Line 67: Line 72:
 
| [[File:ClusterMap2.png]]
 
| [[File:ClusterMap2.png]]
 
|-
 
|-
| Cluster map at a higher zoom, showing the Eastern Seaboard only
+
| Cluster map at a higher zoom, showing Washington DC only
 
|}
 
|}
  
== Standard Nokia Maps library Code Commentary ==
+
The simplest clustering example creates a {{Icode|nokia.maps.clustering.ClusterProvider}}, adds the data points (i.e.  points in the form of latitude, longitude) and directly attach the {{Icode|ClusterProvider}} to the map. The cluster algorithm is fired by calling {{Icode|clusterProvider.cluster();}}
 
+
The Nokia Maps example uses the standard clustering library, and offers a simple custom theme based on SVG graphics. The key to the using custom themes is to include is to add the reference {{Icode| theme: myTheme}} when  instansitating the {{Icode|ClusterProvider}}
+
  
 
<code javascript>
 
<code javascript>
var ClusterProvider = nokia.maps.clustering.ClusterProvider,
+
function clusterDataPoints(data){
clusterProvider = new ClusterProvider(display, {
+
clusterProvider = new nokia.maps.clustering.ClusterProvider(map, {
 
eps: 16,
 
eps: 16,
 
minPts: 1,
 
minPts: 1,
dataPoints: [],
+
dataPoints: data
theme : myTheme
+
 
});
 
});
 
+
clusterProvider.cluster();
// Data Points in the form off latitude, longitiude
+
}
....
+
clusterProvider.addAll(dataPoints);
+
clusterProvider.cluster();
+
 
</code>
 
</code>
  
{{Icode|myTheme}} itself holds two functions:
+
Working Example:
 +
 
 +
* [http://rawgithub.com/heremaps/examples/master/maps_api_for_javascript/advanced-examples/700-markers-simple-clustering.html Standard Clustering]
 +
 
 +
 
 +
== Adding functionality to the clusters ==
 +
 
 +
To add further functionality to the cluster provider, a theme must be provided. The theme consists of two functions {{Icode|getClusterPresentation()}} and {{Icode|getNoisePresentation()}}. The default marker presentation can be accessed by using the methods from {{Icode|nokia.maps.clustering.MarkerTheme}}. The code below reads in the data for the clusters and noise points and add an additional attribute to the standard presentation.
 +
 
  
 
<code javascript>
 
<code javascript>
// Set up a theme.
+
function ZoomToTheme(){
var myTheme ={
+
 
  getClusterPresentation :  getClusterPresentation ,
+
var baseTheme = new nokia.maps.clustering.MarkerTheme();
  getNoisePresentation getNoisePresentation
+
this.getClusterPresentation= function(dataPoints){
};
+
var cluster = baseTheme.getClusterPresentation(dataPoints);
 +
cluster.$boundingBox = dataPoints.getBounds();
 +
  return cluster;
 +
}
 +
this.getNoisePresentation = function(dataPoint){
 +
var noisePoint = baseTheme.getNoisePresentation(dataPoint);
 +
noisePoint.$text = dataPoint.text;
 +
return noisePoint;
 +
}
 +
}
 
</code>
 
</code>
  
Where the {{Icode|getClusterPresentation()}} and getNoisePresentation - the functions style the data from the cluster. The former is displayed using SVG Graphics (see below), and the latter using a {{Icode|StandardMarker}}
+
A Map listener can be created which checks for the presence of these custom attributes, and fires accordingly. In this case the clicking the cluster will zoom the map onto it.
 +
<code javascript>
 +
function addZoomToListener(map){
 +
map.addListener("click", function(evt) {
 +
if ( evt.target.$boundingBox !== undefined){
 +
evt.display.zoomTo(evt.target.$boundingBox, false);
 +
$("#ticker").text("");
 +
} else if ( evt.target.$text !== undefined){
 +
$("#ticker").text(evt.target.$text + " noise point was clicked.");
 +
}
 +
} );
 +
}
 +
</code>
  
 +
The example is wired up as follows:
 
<code javascript>
 
<code javascript>
// This is called for a cluster of points...
+
function clusterDataPoints(data){
var getClusterPresentation = function (dataPoints) {
+
clusterProvider = new nokia.maps.clustering.ClusterProvider(map, {
 +
eps: 16,
 +
minPts: 1,
 +
dataPoints: data,
 +
theme : new ZoomToTheme()
 +
});
 +
clusterProvider.cluster();
 
 
if (dataPoints.getSize() > 0){
+
addZoomToListener(map);
return new nokia.maps.map.StandardMarker (dataPoints.getBounds().getCenter(),
+
}
+
</code>
text:  dataPoints.getSize(), 
+
brush: {color: '#FF0000'}           
+
}
+
);
+
}
+
};
+
  
 +
Working Example:
  
// This is called for an individual point which is outside of a cluster.
+
* [http://rawgithub.com/heremaps/examples/master/maps_api_for_javascript/advanced-examples/700-markers-clustering-with-zoom.html Clustering with Zoom]
var getNoisePresentation = function (dataPoint) {
+
return new nokia.maps.map.StandardMarker ([dataPoint.latitude, dataPoint.longitude]);
+
};
+
</code>
+
  
 +
== Adding a Custom Presentation Theme ==
  
 +
{| class="wikitable"
 +
|-
 +
| [[File:Clustered-custom-theme.png]]
 +
|-
 +
| Cluster map with a custom theme at a higher zoom, showing Washington DC only
 +
|}
 +
 +
A custom theme can also be used to alter the presentation of the Clusters - in this case we will use SVG Graphics. As before {{Icode|svgTheme }} itself holds two functions:
 +
 +
<code javascript>
 +
var svgTheme ={
 +
// Add a SVG Marker for Clusters.
 +
getClusterPresentation :  function (dataPoints) {
 +
if (dataPoints.getSize() > 0){
 +
var markerIcon = createIcon(dataPoints.getSize());
 +
return new nokia.maps.map.Marker(dataPoints.getBounds().getCenter() ,
 +
{icon: markerIcon}
 +
);
 +
}
 +
},
 +
// Add a Standard Marker for Noise Points.
 +
getNoisePresentation :  function (dataPoint) {
 +
return new nokia.maps.map.StandardMarker ([dataPoint.latitude, dataPoint.longitude]);
 +
}
 +
};
 +
</code>
 +
 +
Where the {{Icode|getClusterPresentation()}} and {{Icode|getNoisePresentation()}} - the functions style the data from the cluster. The former will eventually be displayed using SVG Graphics (see below), and the latter using a {{Icode|StandardMarker}}
  
 
=== Using SVG Graphic Markers ===
 
=== Using SVG Graphic Markers ===
Line 133: Line 188:
 
'<circle stroke="#FFF" fill="__MAINCOLOR__" cx="19" cy="19" r="15" 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"/>' +
 
'<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>' +
+
'<text x="19" y="23" font-size="10pt" font-family="arial" font-weight="bold" ' +
 +
        ' text-anchor="middle" fill="#FFF" textContent="__TEXTCONTENT__">__TEXT__</text>' +
 
'</svg>
 
'</svg>
 
</code>
 
</code>
Line 167: Line 223:
 
</code>
 
</code>
  
 +
The SVG Marker can be chained from the {{Icode|getClusterPresentation()}} method  by altering the code as shown:
 +
<code javascript>
 +
// This is called for a cluster of points...
 +
var getClusterPresentation = function (dataPoints) {
 +
 +
if (dataPoints.getSize() > 0){
 +
  var markerIcon = createIcon(dataPoints.getSize());
 +
return new nokia.maps.map.Marker(dataPoints.getBounds().getCenter() ,
 +
{icon: markerIcon}
 +
);
 +
}
 +
};
  
 +
</code>
  
 +
* [http://rawgithub.com/heremaps/examples/master/maps_api_for_javascript/advanced-examples/700-markers-clustering-with-theme.html Clustering with a Custom Theme]
  
 
== Alternative Google library Code Commentary ==
 
== Alternative Google library Code Commentary ==
The coded example provided also offers a version 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 [[Media:ClusterExample.zip|coded example]] provided also offers a version 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 HERE Maps example is a derivative work which has been modified to work with the HERE Maps API.
  
 
=== When to trigger the cluster function  ===
 
=== When to trigger the cluster function  ===
Line 270: Line 340:
  
 
== Summary ==
 
== Summary ==
The [[Media:ClusterExample.zip|Code Example]]  adds 7000 random markers to a map and demonstrates the use of both the standard clustering library and the alternative the {{Icode|MarkerClusterer}} component 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 or to introduce a [[Nokia Maps API - How to create a custom overlay|map overlay]]
+
The [http://rawgithub.com/heremaps/examples/master/maps_api_for_javascript/advanced-examples/700-markers-simple-clustering.html Standard ClusteringExample]  adds 700 random markers to a map and demonstrates the use of both the standard clustering library and the alternative the {{Icode|MarkerClusterer}} component on a HERE 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 or to introduce a [[HERE Maps API - How to create a custom overlay|map overlay]]

Latest revision as of 13:27, 28 November 2013

This article explains how to create and style clustered markers and reduce cluttering on the map when dealing with a very large number of markers .

Article Metadata
Code ExampleTested with
Devices(s): Internet Explorer, Google Chrome, Firefox
Compatibility
Platform(s): Web
Dependencies: HERE Maps 2.5.3 or higher
Article
Keywords: HERE Maps, Marker, Cluster, Large Dataset
Created: jasfox (12 Jun 2012)
Last edited: jasfox (28 Nov 2013)

Note.pngNote: Marker clustering has been supported within the HERE Maps API for JavaScript itself since version 2.2.3 of the library. See the following link for examples

Contents

[edit] 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 displaying 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 7000 Markers distributed between

Europe, Mexico, Texas and the Eastern Seaboard of the U.S.A.

Working Example illustrating the issue:

http://rawgithub.com/heremaps/examples/master/maps_api_for_javascript/advanced-examples/700-markers-unclustered.html

[edit] Simple Clustering Example

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

Europe, Mexico, Texas and the Eastern Seaboard of the U.S.A.


ClusterMap2.png
Cluster map at a higher zoom, showing Washington DC only

The simplest clustering example creates a nokia.maps.clustering.ClusterProvider, adds the data points (i.e. points in the form of latitude, longitude) and directly attach the ClusterProvider to the map. The cluster algorithm is fired by calling clusterProvider.cluster();

function clusterDataPoints(data){
clusterProvider = new nokia.maps.clustering.ClusterProvider(map, {
eps: 16,
minPts: 1,
dataPoints: data
});
clusterProvider.cluster();
}

Working Example:


[edit] Adding functionality to the clusters

To add further functionality to the cluster provider, a theme must be provided. The theme consists of two functions getClusterPresentation() and getNoisePresentation(). The default marker presentation can be accessed by using the methods from nokia.maps.clustering.MarkerTheme. The code below reads in the data for the clusters and noise points and add an additional attribute to the standard presentation.


function ZoomToTheme(){
 
var baseTheme = new nokia.maps.clustering.MarkerTheme();
this.getClusterPresentation= function(dataPoints){
var cluster = baseTheme.getClusterPresentation(dataPoints);
cluster.$boundingBox = dataPoints.getBounds();
return cluster;
}
this.getNoisePresentation = function(dataPoint){
var noisePoint = baseTheme.getNoisePresentation(dataPoint);
noisePoint.$text = dataPoint.text;
return noisePoint;
}
}

A Map listener can be created which checks for the presence of these custom attributes, and fires accordingly. In this case the clicking the cluster will zoom the map onto it.

function addZoomToListener(map){
map.addListener("click", function(evt) {
if ( evt.target.$boundingBox !== undefined){
evt.display.zoomTo(evt.target.$boundingBox, false);
$("#ticker").text("");
} else if ( evt.target.$text !== undefined){
$("#ticker").text(evt.target.$text + " noise point was clicked.");
}
} );
}

The example is wired up as follows:

function clusterDataPoints(data){
clusterProvider = new nokia.maps.clustering.ClusterProvider(map, {
eps: 16,
minPts: 1,
dataPoints: data,
theme : new ZoomToTheme()
});
clusterProvider.cluster();
 
addZoomToListener(map);
}

Working Example:

[edit] Adding a Custom Presentation Theme

Clustered-custom-theme.png
Cluster map with a custom theme at a higher zoom, showing Washington DC only

A custom theme can also be used to alter the presentation of the Clusters - in this case we will use SVG Graphics. As before svgTheme itself holds two functions:

var svgTheme ={
// Add a SVG Marker for Clusters.
getClusterPresentation : function (dataPoints) {
if (dataPoints.getSize() > 0){
var markerIcon = createIcon(dataPoints.getSize());
return new nokia.maps.map.Marker(dataPoints.getBounds().getCenter() ,
{icon: markerIcon}
);
}
},
// Add a Standard Marker for Noise Points.
getNoisePresentation : function (dataPoint) {
return new nokia.maps.map.StandardMarker ([dataPoint.latitude, dataPoint.longitude]);
}
};

Where the getClusterPresentation() and getNoisePresentation() - the functions style the data from the cluster. The former will eventually be displayed using SVG Graphics (see below), and the latter using a StandardMarker

[edit] Using SVG Graphic Markers

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));
};

The SVG Marker can be chained from the getClusterPresentation() method by altering the code as shown:

// This is called for a cluster of points...
var getClusterPresentation = function (dataPoints) {
 
if (dataPoints.getSize() > 0){
var markerIcon = createIcon(dataPoints.getSize());
return new nokia.maps.map.Marker(dataPoints.getBounds().getCenter() ,
{icon: markerIcon}
);
}
};

[edit] Alternative Google library Code Commentary

The coded example provided also offers a version 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 HERE Maps example is a derivative work which has been modified to work with the HERE Maps API.

[edit] When to trigger the cluster function

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 an 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_);

[edit] Adding an OList wrapper

The code for the addition/removal of the markers for clustering is held in the addMarkers(), addMarker(), clearMarkers(), removeMarker() methods, these are taken from the original library, and have only been converted as necessary. To update these methods to use the familiar nokia.maps.util.OList() interface for adding/removing markers, the original methods have been wrapped as shown:

function MarkerClusterer(map, opt_markers) {
...
ExtendedOList.prototype = new nokia.maps.util.OList();
function ExtendedOList (){
this.addAll = function (elements){
ExtendedOList.prototype.addAll.call(this, elements);
addMarkers(elements);
}
this.add = function (element){
ExtendedOList.prototype.add.call(this, element);
addMarker(element);
}
this.clear= function (){
clearMarkers();
ExtendedOList.prototype.clear.call(this);
}
this.remove= function (element){
removeMarker(element)
ExtendedOList.prototype.remove.call(this);
}
this.removeAt= function (idx){
removeMarker( ExtendedOList.prototype.get.call(this,idx));
ExtendedOList.prototype.removeAt.call(this,idx);
}
 
this.removeAll= function (elements){
for (var i = 0; i < elements.length; ++i) {
removeMarker( elements[i]);
}
ExtendedOList.prototype.removeAll.call(this,elements);
}
}
this.objects = new ExtendedOList();
etc...

[edit] How to use the alternative marker clusterer library

The MarkerClusterer 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 cluster the markers place them into an array, and create the MarkerClusterer as shown, and and call MarkerClusterer.objects.addAll()

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();
markerCluster.objects.addAll(markers);

The MarkerClusterer class has been written as a nokia.maps.map.component.Component . To display the clustered markers on a map, attach the component to the MapDisplay.

display.addComponent(markerCluster);

The MarkerClusterer exposes a single objects property for manipulating the markers. As expected this ordered list of objects exposes an nokia.maps.util.OList interface, and markers can be added, removed and queried in the same familar manner as objects in a nokia.maps.map.Container

  • clusterer.objects.add(marker); to add a single marker to the MarkerClusterer
  • clusterer.objects.addAll(markers); to add an Array of markers
  • clusterer.objects.clear(); to empty all markers from the MarkerClusterer
  • clusterer.objects.getLength(); to find the total number of markers clustered.
  • clusterer.objects.remove(marker); to remove a single marker from the MarkerClusterer
  • clusterer.objects.removeAll(markers); to remove an Array of markers from the MarkerClusterer
  • clusterer.objects.removeAt(index); to remove a specified marker at the given index from the MarkerClusterer


[edit] Summary

The Standard ClusteringExample adds 700 random markers to a map and demonstrates the use of both the standard clustering library and the alternative the MarkerClusterer component on a HERE 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 or to introduce a map overlay

This page was last modified on 28 November 2013, at 13:27.
397 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×