Skip to content
This repository has been archived by the owner on Oct 21, 2024. It is now read-only.
tmcw edited this page Dec 7, 2011 · 23 revisions

Modest Maps JS API

We're doing our best to follow Semantic Versioning for version number guidelines. These docs are written against v1.0.0 and should be valid for all v1.x.y versions.

Modest Maps is as much a vocabulary for tiled maps as it is a code library. See ModestMapsNess for a more concise overview.

Please also play with the examples for hints on intended usage.

Map

A Map requires a DOM element, layer and optional dimensions and event handlers. The simplest way to create one is in the window onload handler with a TemplatedMapProvider and the id of a div with width and height set.

// name of a div element:
var parent = 'map';

// defaults to Google-style Mercator projection, so works
// out of the box with OpenStreetMap and friends:
var template = 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png';
var provider = new MM.TemplatedMapProvider(template);

// without a size, it will expand to fit the parent:
var map = new MM.Map(parent, provider);

Alternatively you can specify a fixed size:

// name of a div element:
var parent = 'map';

var template = 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png';
var provider = new MM.TemplatedMapProvider(template);

// Just a way of saying 600px wide by 400px high
var dimensions = new MM.Point(600,400);
var map = new MM.Map(parent, provider, dimensions);

And you can also specify a provider with a more complex method of generating URLs:

// name of a div element:
var parent = 'map';

var provider = new MM.MapProvider(function(c) {
    var img = [ c.zoom, c.column, c.row ].join('/') + '.png';
    return 'http://tile.openstreetmap.org/' + img;
});

var dimensions = new MM.Point(600,400);

var map = new MM.Map(parent, provider, dimensions);

Map: Layers

A map can support multiple Layers, and has an interface to add, remove, and rearrange them.

// Prepare a new layer
var osm = new MM.Layer(new MM.TemplatedMapProvider('http://tile.openstreetmap.org/{Z}/{X}/{Y}.png'+bust))
var mq = new MM.Layer(new mm.TemplatedMapProvider('http://otile1.mqcdn.com/tiles/1.0.0/osm/{Z}/{X}/{Y}.jpg'))

// Insert a layer at index 0
map.insertLayerAt(0, osm);

// Replace that layer with another one
map.setLayerAt(0, mq);

// Remove that layer
map.removeLayerAt(0);

Setting/getting visible area (extent) or center and zoom

To set the Location of the center of the map use setCenter(location). To set the zoom level use setZoom(number). Or use setCenterZoom(location,number) to set both the center and the zoom level at the same time:

map.setCenter(new MM.Location(37.7749295, -122.4194155));
map.setCenterZoom(new MM.Location(37.7749295, -122.4194155), 11);
map.setZoom(11);

To set the map to a location and zoom level that will show a given bounding box (extent) or a set of points, use setExtent(locations) and pass it an array of 2 or more Locations:

var locations = [
    new MM.Location(37.7749295, -122.4194155),
    new MM.Location(37.8043722, -122.2708026),
    new MM.Location(37.8715926, -122.272747)
];
map.setExtent(locations);

You can query the map position using getCenter(), getZoom() and getExtent():

var locations = map.getExtent(); // returns an array of Locations
var loc = map.getCenter() // returns a single Location
var zoomLevel = map.getZoom();

Note that calling map.setCenter(map.getCenter()) should do nothing, but calling map.setExtent(map.getExtent()) could result in a zoom out to ensure that setExtent performs correctly.

Resizing

To set the map size (e.g. in a window.onresize handler) use setSize and pass it a point or two numbers:

// the following are equivalent:
map.setSize(new MM.Point(600,400));
map.setSize(600,400);

Note that the map will automatically resize if you didn't supply initial dimensions in the constructor and your CSS specifies relative sizes such as percentages or ems.

Events / Callbacks

Map can report on several events using a simple callback system. To be notified of map changes subscribe to some or all of the following events: panned, zoomed, extentset, centered, resized, drawn. Each callback will receive the current map as its first argument.

To make overlays that follow the map, or update parts of the page when the map changes, the simplest callback to register is 'drawn':

map.addCallback('drawn', function(m) {
    // respond to new center:
    document.getElementById('info').innerHTML = m.getCenter().toString();
});

Map also exposes a removeCallback method for keeping things tidy, and uses dispatchCallback internally to notify listeners of changes.

We're considering changing to an extremely simple callback model with only one event (perhaps only the 'drawn' event). We'd welcome your feedback on this.

Navigating

Map provides several different ways to change the current center and zoom level, apart from setCenterZoom and setExtent.

Some of them are useful when wiring up map controls such as zoomIn and zoomOut, that go in and out by whole zoom levels, and panLeft, panRight, panDown and panUp that move in 100px increments.

When responding to mouse-wheel or gesture zooming events you'll probably want to use zoomByAbout:

// Madrid
var madridLocation = new MM.Location(40.4, -3.7);

// Madrid on screen:
var madridPoint = map.locationPoint(madridLocation);

// zoom in by one step, keeping SF in the same place on screen:
map.zoomByAbout(1, madridPoint);

When responding to mouse events, or scripting animation, you'll probably want to use the relative functions zoomBy and panBy:

// zoom in by one step:
map.zoomBy(1);

// scroll by 50,50:
map.panBy(50,50);

Converting Point/Location/Coordinate

To convert from geographic Locations to on screen Points, use map.pointLocation and map.locationPoint:

// Dijbouti
var l1 = new MM.Location(11.7, 42.5);

// Dijbouti on screen:
var p1 = map.locationPoint(l1);

// some pixels in the map:
var p2 = new MM.Point(100, 100);

// the geographic location of p2:
var l2 = map.pointLocation(p2);

There are also equivalent internal functions for converting to/from coordinates: coordinatePoint(coord) and pointCoordinate(point).

Internal Map functions

At time of writing, Map also exposes several functions which are only for internal use. We're working on moving the javascript patterns we use for these objects so that these internal APIs don't leak into your work. For the record, we don't expect you to use any of the following methods (unless you're doing work on the Modest Maps internals yourself, of course): getStats, enforceLimits, draw, getTileComplete, requestRedraw, getRedraw, createOrGetLayer, checkCache, getCenterDistanceCompare.

Layers and Providers

If you're supplying your own image tiles for your map, you'll need to know how to create layers and providers. Usually these are supplied to the Map constructor.

Layers are levels of tiles that can be added, removed, and rearranged on a map. Each layer has one provider, which delivers specific data to the layer, like tile URLs, based on map coordinates.

If you want to switch layers in response to a button press, you can call map.setLayerAt with a new layer instead.

MapProvider

The MapProvider class expects a callback function that can turn a Coordinate into a URL string:

var provider = new MM.MapProvider(function(c) {
    var img = [ c.zoom, c.column, c.row ].join('/') + '.png';
    return 'http://tile.openstreetmap.org/' + img;
});

TemplatedMapProvider

The TemplatedMapProvider is an easier interface to MapProvider which takes a string with attractive mustache syntax to generate tile URLs:

var template = 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png';
var provider = new MM.TemplatedMapProvider(template);

The TemplatedMapProvider also takes a template argument {S}, that replaces part of the URL with one of an array of strings. You can use this for subdomains of a tile server.

var template = 'http://{S}tile.openstreetmap.org/{Z}/{X}/{Y}.png';
var subdomains = [ '', 'a.', 'b.', 'c.' ];
var provider = new MM.TemplatedMapProvider(template, subdomains);

The TemplatedMapProvider is similar to the OpenLayers.Layer.XYZ class, or Leaflet's L.TileLayer

Providers also implement a few properties and functions that alter how Modest Maps loads tiles (or does not load tiles) such as outerLimits and sourceCoordinate, and the functions used by map to convert to and from Locations and Coordinates: locationCoordinate(location) and coordinateLocation(coord).

Layer

new in 1.0.0

Layers wrap Providers and do much of the work of requesting and manages the tiles that Providers suggest.

Constructor

// Create a new layer with OpenStreetMap tiles
var osmProvider = new MM.TemplatedMapProvider('http://{S}tile.openstreetmap.org/{Z}/{X}/{Y}.png');
var osmLayer = new MM.Layer(osmProvider);

Instance Methods

// Change a layer's provider
layer.setProvider(newProvider);

Projections

Projections are used internally by Modest Maps providers to convert from Locations to Coordinates.

Internally, the rawProject and rawUnproject functions are the pure mathematics of the operation (we use Wolfram Mathworld and Wikipedia to find interesting projections). These are the only ones that need overriding by subclasses. The project and unproject functions use these, and in turn are used by locationCoordinate and coordinateLocation which are then used by providers. You'll probably just want to use the versions offered by Map.

Modest Maps offers two projections out of the box: LinearProjection and MercatorProjection. The built-in providers all assume Mercator is what you want, but this is easily overridden.

Transformations

Transformations are used internally by Modest Maps projections to convert from one projection space to another, and apply any needed translations, rotations and scales to get everything lined up.

e.g. to transform from a Mercator projected Location in radians to a map Coordinate at zoom level 26, you could use the following Transformation:

var t = new MM.Transformation(1.068070779e7, 0, 3.355443185e7,
    0, -1.068070890e7, 3.355443057e7);

These magic numbers can be derived from three control points using some simple linear algebra. Modest Maps provides helpers for these. For example, to derive a similar Transformation to the above, but for a Coordinate at zoom level 0, use:

var pi = Math.PI;
var t = MM.deriveTransformation(-pi, pi, 0, 0, pi, pi, 1, 0, -pi, -pi, 0, 1);

The Transformation class then offers transform and untransform methods that operate on Points.

Point, Location, Coordinate

Point

Constructor

var point = new MM.Point(x, y)

Class Methods

// Get a point between two other points, biased by `t`.
var p3 = MM.Point.interpolate(p1, p2, t)

// Get the euclidean distance between two points
var d = MM.Point.distance(p1, p2);

Point is a simple data object with x and y properties. It's most often used to represent pixel positions on screen or within the map.

var p1 = new MM.Point(10, 20);
var p2 = new MM.Point(20, 20);

// d is 10
var d = MM.Point.distance(p1,p2);

// p3 is half way between p1 and p2: (15,20)
var amount = 0.5;
var p3 = MM.Point.interpolate(p1,p2,amount);

Location

Constructor

var loc = new MM.Location(latitude, longitude);

Class Methods

// Get the distance between two points, in
// meters, with a sphere of radius r meters (default 6378000)
var d = MM.Location.distance(l1, l2, r)

// Get the interpolation of two points, biased by f,
// along the great circle
var l3 = MM.Location.interpolate(l1, l2, f)

Location is similar to Point, but for geographic coordinates. It has lat and lon properties (and expects them in that order, unlike Point which works the other way around). It represents locations on the surface of the earth in degrees latitude and longitude. You can use a site like getlatlon.com to find the latitude and longitude of places by name.

// Create a new location at 30 latitude, 114 longitude (Xinjiezhen)
var loc = new MM.Location(30, 114);

Coordinate

Constructor

var coord = new MM.Coordinate(row, column, zoom);

Instance Methods

// Get a string key to refer to this coordinate
var key = coord.toKey();

// Get the whole-number coordinate that contains a potentially
// in-between coordinate
var container = coord.container();

// Get a copy of this coordinate
var copy = coord.copy();

// Navigation with coordinates
var zoomedTo = coord.zoomTo(5);
var zoomedIn = coord.zoomTo(1);
var pannedLeft = coord.left(1);

Coordinate is used internally to represent tiles, and the map state - so they have instance functions that let you do all of the navigation that you'd expect out of a map. It has row, column and zoom properties.

It also has several methods that help you navigate from one coordinate to another: up, right, down, left, zoomTo and zoomBy. All return a new Coordinate. Additionally, copy can be used to clone a Coordinate and container can be used to obtain a Coordinate with floored row, column and zoom for generating tile URLs.

Interaction, Mouse Handling/Events

Modest Maps assumes you want an interactive map for use in a desktop web browser and automatically creates a MM.MouseHandler for dealing with mouse drag, double click and wheel events.

If you create a map with an empty array in the fourth parameter it is then up to you to write the interaction code and use functions like map.panBy and map.zoomBy to move the map in response to events:

// fourth argument is null, map will be static (no mouse actions):
var map = new MM.Map(parent, provider, dimensions, null);

Event handlers are currently properties of the map (hence they are passed into the constructor) but this will probably change with future versions since they can exist quite happily away from the Map internals.

Utility Functions

MM.extend

Used internally for inheritance, MM.extend is sometimes useful for implementing new projections and map providers. For example, to implement

var LinearProjection = function(zoom, transformation) {
    // this is a bit like 'super'
    MM.Projection.call(this, zoom, transformation);
};

LinearProjection.prototype = {
    rawProject: function(point) {
        return new MM.Point(point.x, point.y);
    },
    rawUnproject: function(point) {
        return new MM.Point(point.x, point.y);
    }
};

MM.extend(LinearProjection, MM.Projection);

DOM Events, CSS

These are likely to change or be replaced with an existing toolkit but are currently available for helping manage cross browser DOM event handling and CSS style querying. For the record, they are cancelEvent, addEvent, removeEvent and getStyle.

To respond to events in the map such as panning, zooming, see addCallback.

Callbacks and Queues

The CallbackManager and RequestManager classes are used internally and should not considered stable APIs.

Namespace

The official Modest Maps namespace is com.modestmaps, which is used in these examples for correctness. This is aliased to MM. If another object wants to occupy MM, one can call MM.noConflict() and Modest Maps will only inhabit its extended name, com.modestmaps.

Clone this wiki locally