Tuesday 22 December 2009

Updating Google Map Marker's z-index

Lately I've been working on a web application that uses Google's Maps API. It's been an interesting and engaging project.

One of the limitations of the current Maps API is that the z-index of a marker cannot be changed after it has been created. The client requested that the selected marker "popped to the front" as some markers obscured others in certain map areas depending on zoom and closeness of coordinates. This was a reasonable request and would enhance the UI, but was not so easy to implement.


Mike Williams gives a good introduction to this issue and details of how to set the z-index of the marker when it is created with addOverlay() in his Google Maps API Tutorial. Having read this, I attempted to re-create each marker when it was clicked and keep track of the top most z-index. I had some success but had unpredictable z-index results and it was definitely an inefficient way to produce the desired effect.

I decided to browse the DOM and see if I could find a better way to do this. I found a guide to Undocumented Google API features which seems to be mostly out of date, but contained the very important details of how to calculate a Marker's default z-index:

Use marker.setZIndex(Math.round(marker.getLatitude()*-100000)) to get a moved marker to overlap correctly.

Even though setZIndex() and getLatitude() are not valid methods in the current API, it's easy to understand the calculation.

In my application I was already using a unique icon for each marker so that they displayed sequential letters (A,B,C...) and had added an index property to the marker object. I was able to leverage this with a bit of jQuery magic to find each icon in the DOM and alter the CSS z-index value. Since the default z-index is something like -108619296, I created a function to toggle the z-index between normal and front positions by multiplying it by -1.

icon = $("#mapbox div div div img[src='/images/markers/"+marker.index+".png']");
zidx = icon.css('z-index');
icon.css('z-index',zidx*-1);


Just to make sure that no other marker was still in the top position, I looped through my array of markers and reset the z-index with this function.

function reset_zorder(marker) {
$("#mapbox div div div img[src='/images/markers/"+marker.index+".png']").css('z-index',Math.round(marker.getPoint().lat()*-100000));
}


Obviously none of this is a copy+paste solution. but it should give anybody needing to manipulate Google Maps MAP Marker z-index a good example to work from.

1 comment: