Overpass API >

Open Layers mashup

We demonstrate here how to build a custom POI map with OpenLayers as framework and Overpass API as backend. This is the simplest possible way to get a custom POI map: you only need to serve the assembled JavaScript file from your server. The JavaScript logic is fetched from OpenLayers, the background map is fetched from OpenStreetMap, and the data is fetched from Overpass API.

In a step-by-step explanation, we start first with a simple map of some fixed point POIs. Then we go forward to a map of generic POIs like all schools. Finally, we explain how to show multiple different kinds of objects in one map. All the examples are derived from the OpenLayers example in the OSM Wiki.

OpenLayers is chosen for no particular reason. Leaflet would be another suitable possible JavaScript framework, and there are working examples with Leaflet.

One or few POIs

An example: the bus stop next to my home.

While most of the example is uninteresting boiler plate code, there are two interesting sections in the source code of this example:

  ...
  <script type="text/javascript">
      var lat = 50.7421;
      var lon = 7.0624;
      var zoom = 18;
      var data_url = "http://overpass-api.de/api/interpreter?data=node[name=%22Im Tannenbusch%22][highway=bus_stop];out+skel;";
      var map;
  ...

Here, the defining properties of this map are chosen. lat and lon set the point where the map is located at the beginning. zoom is the initial zoom. And finally, data_url chooses which data to highlight, in this case the bus stop with name "Im Tannenbusch".

The query language for data_url is Overpass QL which is introduced in the language guide. The %22 is just an escaping for a quotation mark ("). It is used to avoid confusing the JavaScript engine of the browser. If you want suggestions for the latitude and longitude or just to test whether your query works, you can run the search with slight modifications:
http://overpass-api.de/api/interpreter?data=[out:custom];node[name="Im Tannenbusch"][highway=bus_stop];out skel;&redirect=no
This shows exactly the results that will be found by the query and therefore get marked on the map.

          ...
          var styleMap = new OpenLayers.StyleMap({
              strokeColor: "blue",
              strokeOpacity: 0.5,
              strokeWidth: 6,
              pointRadius: 10,
              fillColor: "blue",
              fillOpacity: 0.25
          });
          ...

The second block controls the appearance of the markers on the map. We display currently only points, thus only the properties pointRadius and fillColor are relevant to us. pointRadius gives the radius of the point marker, fillColor its color. You can also display icons instead of vector graphics on the map, but because we are concerned with the backend here, we restrict the presentation to vector features.

Generic POIs

An example: all schools around the world.

In this example, we use not a few and locally concentrated features like above, but a basically indefinite number of results from potentially all over the world. To illustrate this, the example shows all schools.

Although the example has a more elaborate source code than the preceeding example, the map is controlled by a similar section like the map above:

  ...
  <script type="text/javascript">
      var lat = 50.727;
      var lon = 7.092;
      var zoom = 15;
      var data_url = "api/interpreter?data=node[amenity=school](bbox);out;(way[amenity=school](bbox);node(w););out;";
      var zoom_data_limit = 13;
      var map;
  ...

The query has one new element: The condition bbox. This is replaced by the bounding box that OpenLayers calculates to be relevant when performing a query. You can use this feature one or more times. You could also not use this features, but then the bounding box computation doesn't make sense and you could better use a map with fixed POIs.

The second new element is zoom_data_limit: this is the highest zoom level where OpenLayers should still attempt to load data from the backend. In general, loading data for the whole world will both be inacceptably slow and overload the browser, therefore you can and are strongly encouraged to limit the zoom level. 13 works fine for schools in Germany. If you have significant denser data, a higher number for the limit would be better. If you have sparser data, a lower number would offer the user more oversight on smaller zoom levels.

Multiple types of POIs

An example: all schools, all universities and all kindergartens.

To show that you can mark multiple features at once, this example contains multiple layers. For this reason, the source code no longer contains the line data_url, but rather the following lines:

          ...
          map.addLayers([
              make_layer("api/interpreter?data=node[amenity=kindergarten](bbox);out;(way[amenity=kindergarten](bbox);node(w););out;", "green"),
              make_layer("api/interpreter?data=node[amenity=school](bbox);out;(way[amenity=school](bbox);node(w););out;", "blue"),
              make_layer("api/interpreter?data=node[amenity=university](bbox);out;(way[amenity=university](bbox);node(w););out;", "orange")
          ]);
          ...

Each of these lines adds another layer to the map. The first layer contains all kindergartens and shows its objects in green, the second layer all schools and shows its objects as before in blue, and the third layer shows all universities in orange. You can of coarse use any query and any color for any number of layers.