Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Maps: Render marker above markerclusterer

I have a set of markers that get clustered on my map. Another set of markers are displayed individually, and i happen to need these to be displayed above the clusters. I have tried setting zIndex in the clusters options object, lower than that of the 2nd set of markers, but to no avail. Any idea how to go about this?

like image 552
cv87 Avatar asked Apr 20 '12 09:04

cv87


1 Answers

It can be done, but it's a pretty bumpy way until you get there... As Rick says, the problem is that the MarkerClusterer adds an own OverlayView with its cluster icons on a higher pane as the regular markers. The only way to add a marker above the clusters is to beat the clusterer with his own weapons and add an own OverlayView and add the marker icon markup to an even higher pane (read about panes here). I don't really like it - but it's the only way I found.

To do this you have to create a custom overlay implementing google.maps.OverlayView (reference), a good example can be found here (with explanations, I used a bit of code from it).

Here is a rough CustomOverlay prototype:

// build custom overlay class which implements google.maps.OverlayView
function CustomOverlay(map, latlon, icon, title) {
    this.latlon_ = latlon;
    this.icon_ = icon;
    this.title_ = title;
    this.markerLayer = jQuery('<div />').addClass('overlay');
    this.setMap(map);
};
CustomOverlay.prototype = new google.maps.OverlayView;
CustomOverlay.prototype.onAdd = function() {
    var $pane = jQuery(this.getPanes().floatPane); // Pane 6, one higher than the marker clusterer
    $pane.append(this.markerLayer);
};
CustomOverlay.prototype.onRemove = function(){
    this.markerLayer.remove();
};
CustomOverlay.prototype.draw = function() {
    var projection = this.getProjection();
    var fragment = document.createDocumentFragment();

    this.markerLayer.empty(); // Empty any previous rendered markers

    var location = projection.fromLatLngToDivPixel(this.latlon_);
    var $point = jQuery('<div class="map-point" title="'+this.title_+'" style="'
                            +'width:32px; height:32px; '
                            +'left:'+location.x+'px; top:'+location.y+'px; '
                            +'position:absolute; cursor:pointer; '
                        +'">'
                        +'<img src="'+this.icon_+'" style="position: absolute; top: -16px; left: -16px" />'
                    +'</div>');

    fragment.appendChild($point.get(0));
    this.markerLayer.append(fragment);
};

This overlay gets the map, a LatLng object and the URL of an icon. The good thing is that you can write your own HTML to the layer, the bad thing is that you have to handle all the stuff the Maps API does for you (like marker image anchor handling) by your own. The example only works good with 32x32px images where the anchor is in the middle of the image, so it's still pretty rough.

To use the CustomOverlay, just instantiate it like this:

// your map center / marker LatLng
var myLatlng = new google.maps.LatLng(24.247471, 89.920990);

// instantiate map
var map = new google.maps.Map(
    document.getElementById("map-canvas"),
    {zoom: 4, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP}
);  

// create the clusterer, but of course with markers
//var markerClusterer = new MarkerClusterer(map, []);

// add custom overlay to map
var customCustomOverlay = new CustomOverlay(map, myLatlng, 'http://www.foo.bar/icon.png');

I hope this works for you.

like image 56
rkallensee Avatar answered Sep 28 '22 05:09

rkallensee