Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working with Google Maps, Stamen Tiles (an existing tile library) and Require.js?

I am trying to write a module`to load a Stamen tile map under Require.js, but I'm unsure how to best use it with Require.

If you haven't seen Stamen maps before, their site is at Stamen Maps.

This is the code for the map view, view.js

define([
  'jquery',
  'underscore',
  'backbone',
  'maps',
  'text!templates/map/view.html'
], function($, _, Backbone, maps, mapTemplate){
  var mapView = Backbone.View.extend({
    el: $(".map"),
    displayMap: function() {
      this.options = {
        center: new maps.LatLng(-37.8, 144.9),
        zoom: 11,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scrollwheel: false
      };
      this.render();
    },
    render: function(){
      var compiledTemplate = _.template(mapTemplate);
      var $el = $(this.el);
      $el.html(compiledTemplate);
      this.map = new maps.Map($el.find('.map').get(0), this.options);
    }
  });
  return new mapView;
});

I am loading the maps API following modules:

map.js

define(['google!maps/3/sensor=false'], function() { 
  return google.maps;
});

Which has the dependency of google.js

define(['http://www.google.com/jsapi?key=THE_API_KEY&callback=define'], { 
  load: function( name, req, load, config ) { 
    if (config.isBuild) {
      onLoad(null);
    } else {
      var request = name.split('/'); 
      google.load(request[0], request[1], { 
        callback: load, 
        language: 'en', 
        other_params: ((typeof request[2] === 'string')?request[2]:'') 
      });
    }
  } 
});

The issue is that the Stamen maps layers appear to edit the Google Maps instance directly. You can see the Stamen maps implementation here: http://maps.stamen.com/js/tile.stamen.js?v1.1.1

google.maps.StamenMapType = function(name) {
  //Implementation
}

It seems to rely on the global google.maps object, which is where I believe the issue is coming from.

I'm unsure how to best rewrite the Stamen plugin to be require.js friendly, or if I need to, and I am really keen on using it. Unless I take Google Maps and Stamen out of Require.js and load them normally (like I do with Modernizr) but I'd much prefer to try and do it the Require.js way. If there is such a thing.

Any advice or tips would be much appreciated.

like image 335
superhighfives Avatar asked Feb 20 '23 23:02

superhighfives


1 Answers

I'm responsible for tile.stamen.js. Sorry for the headache.

The problem here is that our script needs access to the Google Maps namespace (google.maps) so that it can create the StamenMapType class and have it inherit methods from Google's ImageMapType. If you absolutely need to use RequireJS (which I wouldn't suggest, exactly because it makes simple stuff like this awkward), you'll need to rewrite the whole Google-specific portion of tile.stamen.js (lines 155-177) to look something like this:

exports.makeStamenMapType = function(name, gmaps) {
    if (!gmaps) gmaps = google.maps;
    var provider = getProvider(name);
    return new gmaps.ImageMapType({
        "getTileUrl": function(coord, zoom) {
            var index = (zoom + coord.x + coord.y) % SUBDOMAINS.length;
            return [
                provider.url
                    .replace("{S}", SUBDOMAINS[index])
                    .replace("{Z}", zoom)
                    .replace("{X}", coord.x)
                    .replace("{Y}", coord.y)
            ];
        },
        "tileSize": new gmaps.Size(256, 256),
        "name":     name,
        "minZoom":  provider.minZoom,
        "maxZoom":  provider.maxZoom
    });
};

Then you'd use:

var toner = makeStamenMapType("toner", gmaps);

where gmaps is your required Google Maps API object.

like image 87
Shawn Allen Avatar answered Apr 10 '23 09:04

Shawn Allen