Overcoming multiple overlapped markers in Google Maps using GMAP3 and OverlappingMarkerSpiderfier

1 August, 2014   |   JavaScript

Google Maps APIRecently we were working on Google Maps API project for a client who wanted to display map markers for each office locations and clicking on it will show overlay window with address and service details. Map was working fine until we face a situation where two or more offices were on the same exact location and the map markers were overlapping each other making only the top marker clickable. We are using GMAP3 jQuery plugin for all Google Maps API coding as it is very easy to use and have robust integration with API version 3. It also supports callback and global get/set methods that is quite useful when integrating it with other jQuery plugins or modules.

We then found a plugin named OverlappingMarkerSpiderfier by George MacKerron that had a very intuitive solution for overlapping markers. What it does is make multiple overlapped markers spring around the clicked marker and allows user to select the otherwise hidden map markers. The idea was taken from Google Earth that uses the same technique but in more animated way.

Overlapped markers on map

Overlapped markers before and after clicking on them using OverlappingMarkerSpiderfier.

Here is how to integrate OverlappingMarkerSpiderfier with GMAP3 for Google Maps API.

<script type="text/javascript">

	jQuery(document).ready(function($)
	{
		var oms;

		var MarkerData = {"lat":0,"lng":0,"data":"Overlay text here."};

		$('#selector').gmap3
		(
			{
				action: 'init',
				options: { scaleControl: false, center: [52.132633,5.291266], zoom: 7, mapTypeControl: false, mapTypeId: google.maps.MapTypeId.ROADMAP },
				callback: function(map)
				{
					oms = new OverlappingMarkerSpiderfier(map, {markersWontMove: true, markersWontHide: true, keepSpiderfied: true, nearbyDistance: 10, legWeight: 5});
				}
			},
			{
				action: 'addMarkers',
				markers: MarkerData,
				marker:
				{
					options: { icon: new google.maps.MarkerImage('http://www.example.com/icon.png') }
				},
				callback: function(markers)
				{
					$.each(markers, function(i, marker)
					{
						marker.data = MarkerData[i].data;

						oms.addMarker(marker);
					});    
				}
			}
		);

		oms.addListener('click', function(marker)
		{
			$('#selector').gmap3
			(
				{ action: 'clear', name: 'overlay' },
				{
					action: 'addOverlay',
					latLng: marker.getPosition(),
					content: '<div class="map-overlay">' + marker.data + '</div>',
					offset: { x: -30, y: 0 }
				},
				{ action: 'panTo', args: [marker.position] }
			);
		});
	});

</script>

First off, we need to define global variable for OverlappingMarkerSpiderfier plugin var oms; so we can integrate it with GMAP3 using callback functions. Then we initialize the plugin within GMAP3 callback call like this oms = new OverlappingMarkerSpiderfier();. Important thing to note here is that we do not attach marker events from GMAP3 but uses callback function to attach it to OverlappingMarkerSpiderfier object. Finally, we add event listener to OverlappingMarkerSpiderfier and add necessary actions to Map API.

Hope this helps someone looking for this complicated issue for overlapping map markers. If you have any queries then don’t hesitate to post comments.

 

Discussion

Viskin 21 March, 2015

In addition, you can make spiderfier markers animate smoothly.
Use marker-animate-unobtrusive library and create MarkerWithGhost instead of google.maps.Marker.
See demo here:
https://github.com/terikon/marker-animate-unobtrusive#integration-with-overlappingmarkerspiderfier

Chris 14 July, 2015

Thank your for this hint, i implemented this in the actual gmap3 Version (6):

var oms;

var allmarker = [];

$(“#gmap”).gmap3({
map:{
options: {
zoom: 5,
minZoom: 3
},
callback: function(map)
{
oms = new OverlappingMarkerSpiderfier(map, {markersWontMove: true, markersWontHide: true, keepSpiderfied: true, nearbyDistance: 10, legWeight: 5});
}
},
marker:{
values: allmarker,
options:{
draggable: false
},
events:{
click: function(marker, event, context){
var map = $(this).gmap3(“get”),
infowindow = $(this).gmap3({get:{name:”infowindow”}});
if (infowindow){
infowindow.open(map, marker);
infowindow.setContent(context.data);
} else {
$(this).gmap3({
infowindow:{
anchor: marker,
options: {content: context.data}
}
});
}
}
},
callback: function(markers){

$.each(markers, function(i, marker)
{
oms.addMarker(marker);
});

}
}
},
“autofit”);

Hai Truong 30 July, 2015

Thanks Chris. Very good, it’s run OK on my website

Leave a Comment