The most mature, portable, and stable API for browser-based map applications is OpenLayers. OpenLayers is an API that renders a map in a <div> tag on your HTML page, and allows you to manipulate all the minutia of adding data to the map, interacting with it, getting data out of it, and so forth. In this post, you will be introduced to OpenLayers, learn about how to develop interactive applications with it, and learn a little bit about adding data.
Getting a base map on the page
I usually start by including the most up-to-date development snapshot of OpenLayers. The OpenLayers development snapshots are stable within reason, and contain a few features that are well above and beyond those you can find in the stable branch.
<html> <head> <script src="http://dev.openlayers.org/nightly/OpenLayers.js"> </script> <!-- the next line is needed if you intend to use Google Maps --> <script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script> </head> <body> <div id=‘map’></div> </body> </html>
This gives you a blank page to work with that includes everything you need to get started with OpenLayers. To actually add a map to the page, you will need to add an OpenLayers.Map object and a base layer. Practically any kind of layer can be used as a base layer, but the more common base layers are from widely used tile mapping services: Google, Bing, and Open Streetmaps.
When these are not used, it is common to use an OGC WMS or TMS (Tile Mapping Service) feed to populate the base map of OpenLayers. The advantage to a WMS or TMS service, especially if you deploy them yourself, is that you can get them on more than one map projection. All the popular tiling map services use the same map projection and are locked into that projection, known as “Spherical Mercator”. Spherical Mercator, despite its name, is a cylindrical projection, which gives increasing distortion of area near the poles and cannot display the poles themselves at all. Additionally, you must be able to retrieve any layers added onto a Spherical Mercator layer in Spherical Mercator. This is not normally a problem, as most WMS and WFS map servers are capable of reprojecting to the Spherical Mercator coordinate system. Older services and static feeds may not, however.
Google maps are the most popular maps on the web both because they were available to make mashup-apps early, and because they are highly readable. Google’s provides separate tilesets for satellite imagery, terrain bumpmaps, roads and cities, and finally a road/satellite hybrid tileset.
Which one to use depends largely on the application you are writing. The terrain map provides the most neutral background, however it shows the least detail. The road map tells you nothing about what kind of terrain a feature is found on, but gives accurate information about roads, parks, military installations (in the US), cities, towns, and landmarks. The satellite and hybrid maps have great variability in background, limiting the color palette and size of features that you can display legibly, but they also show whether or not the data you’re overlaying is in the middle of the forest or in the middle of the desert – an important distinction in some cases!
So let’s look at how to create a map and add a Google layer to it. All this code would be enclosed in a <script> tag or be stored in a separate Javascript file to be loaded after OpenLayers:
var map = new OpenLayers.Map(‘map’ // the id of the <div> tag {maxExtent: new OpenLayers.Bounds( -20037508, -20037508, 20037508, 20037508.34), } ); // The terrain map var terrain = new OpenLayers.Layer.Google(“Google Terrain”, {type: google.maps.MapTypeId.TERRAIN, sphericalMercator: true}); // The roads map var roads = new OpenLayers.Layer.Google(“Google Maps”, {sphericalMercator: true}); // no maptype needed since this is default. // The hybrid map var hybrid = new OpenLayers.Layer.Google(“Google Maps”, {type: google.maps.MapTypeId.HYBRID, sphericalMercator: true }); //The satellite imagery map. var satellite = new OpenLayers.Layer.Google(“Google Satellite”, {type: google.maps.MapTypeId.SATELLITE, sphericalMercator: true }); // This control is one way to raise or lower base layers. map.addControl(new OpenLayers.Control.LayerSwitcher()); // Layers are stacked from bottom to top, with the leftmost at the bottom. map.addLayers([terrain, roads, hybrid, satellite]);
Any one of these layers could have been added individually. Here we add them all and a layer switcher control (shown as the little blue tab with a plus sign on it at the top right of the map. The layer switcher lets us switch between them at will. Note that sphericalMercator is set to “true”. This is always a good practice, as layering other maps or drawing your own features on top of a Google (or any commercially provided) map will require that this is set to “true”.
The map object we created is very basic; we will come to more complex map objects later on, however note the maxExtent parameter. This is often essential when adding multiple layers. If this is omitted, some versions of OpenLayers can fail to display data at all zoom levels. The maxExtent used here covers the entire world in the spherical Mercator projection. These values, although arcane, are safe to use and copy wholesale into your project.
Bing
Bing maps are perhaps the strongest commercial alternative to Google. If you want to give your application a look that distinguishes it from other applications, Microsoft’s Bing might just be the way to go. Bing’s maps are still fairly readable. Their default map looks a bit like a combined view of Google’s road and terrain maps. At its most detailed level it is still a little sparser than Google, which may appeal depending on your application. Finally the licensing terms are different. Licensing turns out to be a key issue when dealing with a commercial map provider, be it Google, Yahoo, or Microsoft, and each providers terms are enough different that if you find yourself unable to develop the application you want (for instance, Google doesn’t let you track vehicles as of this writing), you may look at another company’s map product.
To get the Bing map, you will need to add another script tag to the page in the area before your source code is included or written:
<script src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&mkt=en-us"></script>
Then the map creation procedure is very similar to the procedure we followed for Google:
var map = new OpenLayers.Map(‘map’ // the id of the <div> tag. {maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34) }); // API key for http://openlayers.org. Please get your own at // http://bingmapsportal.com/ and use that instead. var apiKey = "AqTGBsziZHIJYYxgivLBf0hVdrAk9mWO5cQcb8Yux8sW5M8c8opEC2lZqKR1ZZXf"; var roads = new OpenLayers.Layer.Bing(“Roads”, {type: "Road", apiKey:apiKey, sphericalMercator:true }); var hybrid = new OpenLayers.Layer.Bing("Hybrid", {type: "AerialWithLabels", apiKey:apiKey, sphericalMercator:true}); var aerial = new OpenLayers.Layer.Bing("Aerial", {type: "Aerial", apiKey:apiKey, sphericalMercator:true}); map.addControl(new OpenLayers.Control.LayerSwitcher()); map.addLayers([shaded, hybrid, aerial]);
OpenStreetMap
OpenStreetMap is a crowd-sourced mapping project similar in scope and intent to Wikipedia, but for navigation. Its strength lies in two areas: licensing and coverage. OpenStreetMaps is released via a Creative Commons Share-alike license. You can develop turn-by-turn directions, vehicle tracking, and all kinds of other applications that the commercial providers restrict you from. You can download the data, which is vector formatted, and render your own map tiles to your liking. Additionally, in countries where US Trade restrictions abound, OpenStreetMaps commonly has whole towns that Google, Yahoo, and Bing just don’t have. For instance, you might go to the Haitian port of Legoane in Google and OpenStreetMaps and compare notes. Or try rural Cuba. OpenStreetMap was used to great effect in the early days of the Haitian earthquake relief effort.
There is only one possible view to the openstreetmap.org’s OpenStreetMap, so creating an OpenStreetMap layer is perhaps the simplest of all. No extra script tag to include APIs is required:
var map = new OpenLayers.Map(‘map’ // the string is the id of the <div> tag. {maxExtent: new OpenLayers.Bounds( -20037508, -20037508,20037508, 20037508.34)}); layer = new OpenLayers.Layer.OSM( "Simple OSM Map”, {sphericalMercator: true}); map.addLayer(layer);
WMS
WMS stands for Web Map Service, and is a standard produced by the OGC. We will go into detail into WMS in a couple of posts, but for now, we’ll stick to showing how to add a WMS service to a base map, and why you would want to. WMS is by far the most versatile mapping solution. The open source Geoserver and MapServer projects are just two examples of servers you can setup for yourself to serve WMS tiles. RENCI’s Geoanalytics Framework contains a highly flexible implementation of WMS for Python/Django, which operates on top of any of the supported data models.
WMS has its drawbacks. Many WMS servers render tiles on the fly, so many require an additional caching service to run on the server to keep up performance. WMS servers may also be quite varied in the projections they support, so it would be good to do a little research on the service you intend to use before you actually go about using it. We will go into how to do this programmatically later, but for now, let’s stay focused on getting the data into the map:
var map = new OpenLayers.Map(‘map’,{ // the string is the id of the <div> tag. maxExtent: new OpenLayers.Bounds(-180,-90,180,90), projection: “EPSG:4326” }); var layer = new OpenLayers.Layer.WMS("OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0", { layers: ‘basic’, }); map.addLayer(layer);
Here we see a couple of new parameters: layers and srs. Layers describes to the WMS what layers to composite together into a single image. Compositing in WMS is done server side, so if you are sure you always want a few layers composited together, you can save client side performance and have the server do it. This parameter is required. The second parameter is optional, but without it you are at the mercy of whatever the projection the layer has set as default. It should generally be the map projection.
To use a WMS layer as the base layer, be sure to set the projection and extents, and then add “baseLayer: true” to the options object.
The srs parameter stands for spatial reference system, and is usually but not always a code like that seen above. “EPSG:4326” is a common, (but often misused) basic latitude-longitude projection. “EPSG:3785” (or “EPSG:900913” on older systems) is the Google/Bing/Yahoo/OSM Spherical Mercator projection. There are a number of common ones, and not all may be supported by your particular map server. We will cover in detail in a future post how to find out for your server which spatial reference systems are supported. A full search engine and large database of spatial reference systems can be found online at SpatialReference.org. This is a crowdsourced wiki for spatial reference systems, and not all spatial reference systems may be found there.