Making Drupal GMap Look Pretty

Recently we built a website that uses the Location and GMap Drupal modules. Our customer is an artist and we wanted to do something slick that matches the style of her site. GMap module offers some basic styling of the map, but what we really wanted was the type of stylized maps shown on snazzymaps.com.

These maps use some JavaScript code similar to the "JavaScript style array" shown on this example, which is the style used in this blog post. Unfortunately the GMap module does not directly support this type of styling at the moment. We will need another way to add this code to a Drupal theme.

Step 1: Modules

Install Location and GMap, and configure them, along with any of the add-on location modules that enables you to attach locations to the various Drupal features such as users, nodes, or taxonomy. Our client is associating the locations with content, so we are using the "Node Locations" module to attach locations and then "GMap Location" to display the map. The example below assumes this; if your setup is different, you might have to adjust the JavaScript code.

Once you have location information attached to a page, visit Drupal's block administration page under Structure -> Blocks and enable the GMap Location block. At this point you should see a working Google map, although with the default styling.

Step 2: JavaScript

Hopefully you are working with a subtheme as explained previously. Open your theme's THEMENAME.info file and add a scripts line if you don't already have a place to put custom site JavaScript code:


scripts[] = site.js

Next create the file site.js in the same directory as THEMENAME.info and paste the following code, replacing REPLACE_WITH_STYLE_FROM_SNAZZYMAPS variable definition with a style array copied from SnazzyMaps or other source. The format is a JavaScript array that begins with "[" and ends with "]".


(function ($) {

  var mapstyle = REPLACE_WITH_STYLE_FROM_SNAZZYMAPS;

  /**
   * Apply styles to a Google map. This function waits until the Drupal GMap
   * module has finished creating the map (when Drupal.gmap.getMap() returns a
   * map instance instead of undefined variable) before applying the styles. If
   * necessary, use window.setInterval to wait for map to be ready.
   *
   * Please note that this is not the best possible solution for styling maps,
   * check back with us later for an improved solution to this issue:
   * http://monkeysatkeyboards.com/making-drupal-gmap-look-pretty
   *
   * @param mapid Map identifier. GMap module outputs it as a class on the map
   *        wrapper div, e.g... 'gmap-auto1map-gmap'. This can be a string with a
   *        single ID or an array with multiple IDs. The function only has any
   *        effect if an element is found in the document with a CSS class that
   *        matches this ID exactly.
   *
   * @param styles JavaScript styles array e.g.. from http://snazzymaps.com
   */
  function styleMaps(mapid, styles) {
    var mapids = (mapid instanceof Array) ? mapid : [ mapid ];
    for (var i in mapids) {
      if ($('.' + mapids[i]).length) {
        var gmap = Drupal.gmap.getMap(mapids[i]);
        if (typeof(gmap.map) != 'undefined') {
          gmap.map.setOptions({styles: styles});
        }
        else {
          var args = {
            gmap: gmap,
            styles: styles
          };
          args.iid = window.setInterval(function(args) {
            if (typeof(args.gmap.map) != 'undefined') {
              window.clearInterval(args.iid);
              args.gmap.map.setOptions({styles: args.styles});
            }
          }, 20, args);
        }
      }
    }
  }

  Drupal.behaviors.site = {
    attach: function (context, settings) {
      var maps = [
        'gmap-auto1map-gmap', // Names used by GMap Location
        'gmap-auto2map-gmap',
        'gmap-auto3map-gmap'
      ];
      styleMaps(maps, mapstyle);
    }
  };
}(jQuery));

Now flush your cache under Configuration -> Development -> Performance and enjoy your newly styled map!

Disclaimer

Please note that this solution ranks pretty low on the list of solutions presented in my last post, Why Drupal? The Coder's Perspective, and I am sure this is not the best way to achieve it. It works for now as a short term solution.

I suspect a better solution for this long term is to add support for this kind of style array to the GMap module itself. When I get some free time (Hah!) I will look at making a patch for GMap that would configure the settings in the admin and store them, and pass it through Drupal's regular JavaScript settings array. I'll update this post when a patch is available.

Please leave a comment if you have any suggestions on improving the above temporary solution or ideas for integrating these styles with GMap.