In usability we trust

UX and all things web

Dynamically Toggle Markers in Google Maps

This article explains how to dynamically toggle the visibility of markers in Google Maps as well as how to deal with an annoying bug that occurs when trying to do this while using an utility library, like the MarkerManager.

Using the MarkerManager

The MarkerManager is a very useful Open Source Utility Library for Google Maps with the sole purpose to manage larger amounts of Markers. If you add markers with the MarkerManager you can control at which zoom-levels they will appear. And you can also hide and show them dynamically.

If you want to learn more about the MarkerManager and other libraries out there that deals with markers, read my article Handling Large Amounts of Markers in Google Maps.

Adding markers with the MarkerManager

Now the most effective way to add markers to the MarkerManager is to first add them to an array that you then add to the MarkerManager with the addMarkers() method. The code to do this would be something like this.

// Init the MarkerManager
var mgr = new MarkerManager();
//Defining the array that will contain all markers
var markers = [];
// Creating a marker
var marker = new GMarker(new GLatLng(57.8, 14.0));
// Add marker to the array
markers.push(marker);
// Add the array to the MarkerManager
mgr.addMarkers(markers, 1);
mgr.refresh();

Obviously it’s kind of useless to add only one marker this way. It would only be useful if you had at least a few of them, but I think you get the point.

Hiding and showing markers

In the Google Maps API there are two handy methods to toggle the visibility of markers. These are GMarker.show() and GMarker.hide(). They both work as expected, you call hide() and the markers disappears and then you call show() and the marker is displayed again.

So to hide all markers in this example you simply do this:

// Loop through all markers and hide each of them
for (var i = 0; i < markers.length; i++) {
  var marker = markers[i];
  marker.hide();
}

A bug

There is however one caveat and that is when you zoom the map the markers will magically appear again. This is an annoying bug that only appears when you use it on markers added with an utility library.

bug_description

Click the image to enlarge

The solution

So far I've only found one solution for this and that is to extend the hide method and tweak the code to place the marker outside the map, thereby making it sort of invisible.

// Saving the position of the marker and then place it outside the map
GMarker.prototype.hide = function() {
  if (this.getPoint().lat() < 90) {
    try {
        this.savePoint = this.getPoint();
        this.setPoint(new GLatLng(90, 0));
    } catch (e) { }
  }
}

Subsequently you need to prototype the show method as well so that it moves the marker into the correct position again.

// Restoring the position of the marker
GMarker.prototype.show = function() {
  if (this.getPoint().lat() == 90) {
    if (this.savePoint) {
      try {
        this.setPoint(this.savePoint);
        this.savePoint = null;
      } catch (e) { }
    }
  }
}

It's a dirty solution I know, but so far it's the best solution I've found and it works really well.

Note: I haven't come up with this solution myself but haven't been able to find where I saw it. So if you know who did come up with it, please tell me so I can give credit where credit is due.

isHidden()

The Google Maps API also offers a method to determain if a marker is hidden or not, GMarker.isHidden(). If you want to be able to use that you have to prototype it as well.

GMarker.prototype.isHidden = function() {
  if (this.getPoint().lat() == 90) {
    return true;
  } else {
    return false;
  }
}

Live examples

I've put together a few examples of different scenarios using this, so that you will see the problem as well as the solution to it.

Other libraries

There are several other libraries for dealing with markers out there, and in at least one of them, Clusterer, I've noticed the same bug as in MarkerManager. The fix proposed in this article will work just fine on that one as well and possibly on other libraries where you might also find this bug.

If you've encountered this problem in other libraries please let me know. It would also be interesting to see other, and possibly more elegant solutions to this problem.

My Google Maps book

If you found this article useful you might be interested in my book Beginning Google Maps API 3. It covers everything you need to know to create awesome maps on your web sites. Buy it on Amazon.com

9 Comments

  1. Thank you for sharing that. The same problem occurs with MarkerClusterer by Xiaoxi Wu.

  2. Ok, I suspected that it would occur in other libraries as well. Thanks for letting me know!

  3. Thank you so much! I was getting pretty frustrated before stumbeling on your solution. Works just perfect.

    /Pär

  4. Hi,

    I have found an easy solution for this issue and hope it may help. I also tested thoroughly. The fix is given below.

    private var mgr:MarkerManager;

    if(mgr==null)
    {
    mgr = new MarkerManager(map,{});
    }else
    {
    map.clearOverlays()
    mgr.clearMarkers();
    map.clearOverlays()
    }

    NOTE: I have pasted below the complete code for viewing a sample example implemented with the fix for markermanager utitlity bug.

    //*****************************************************

    <![CDATA[
    import mx.controls.Alert;
    import com.google.maps.MapEvent;
    import com.google.maps.Map;
    import com.google.maps.overlays.Marker;
    import com.google.maps.MapType;
    import com.google.maps.LatLng;
    import com.google.maps.LatLngBounds;
    import com.google.maps.extras.markermanager.MarkerManager;

    public var markerArr:Array = [];
    private var mgr:MarkerManager;

    private function createMarkers():void
    {

    var bounds:LatLngBounds = map.getLatLngBounds();
    var southWest:LatLng = bounds.getSouthWest();
    var northEast:LatLng = bounds.getNorthEast();
    var lngSpan:Number = northEast.lng() – southWest.lng();
    var latSpan:Number = northEast.lat() – southWest.lat();
    markerArr=[]
    for (var i:int = 0; i

    //*****************************************************

  5. Hi Sven,

    may you allow me – as an up to date follow up on this topic – to refer to my blog post about dynamically toggling markers with the Google Maps JavaScript v3 API and how to apply as many custom filters, as you may need. The article can be found at: http://bexton.net/2011/06/03/the-setvisible-method-for-the-google-maps-marker-class-or-how-to-toggle-marker-icons-with-the-google-maps-v3-javascript-api/

    Thank you and kind regards,
    Stephan

  6. Great script! Extremely useful thanks so much for posting!

    Is it possible however to have certain items in the legend checked and appear on default, and others that do not appear on default and must be clicked in order to be displayed? Help in this would really be a lifesaver!

  7. Nice article, but I have an other method. Might be ‘hacky’ but it works fine.

    I hide the map with:
    marker.setMap(null);

    And make it apear again with:
    marker.setMap(map);

    Only requirement is to have the google map object stored in a variable. I haven’t found any bugs with this. Are there other reasons for not using this method?

    • Hi,

      That’s not at all a hacky way to do it but in fact exactly how you should do it with version 3 of the Google Maps API. This article however, describes how to do it in version 2 of the Google Maps API.

      Google redesigned the entire API with a totally new syntax in version 3.

Leave a Reply to NSairam Cancel reply

Your email address will not be published.

*