At Interline Technologies, we help make open-source and open-data usable to professionals and hobbyists alike. Interline OSM Extracts, one of our services, provides city-sized chunks of crowdsourced mapping data available for free and easy download. It's up to each person to use their own GIS or web mapping tools to filter, visualize, or analyze the map extract — this requires some prior experience and some computing power. Now, with HERE XYZ Spaces, everyone can follow a simple workflow to download from Interline OSM Extracts and quickly begin to filter and visualize.

In this tutorial, we'll create an interactive web map of Honolulu that highlights some crowdsourced locations relevant to tourists. We'll be combining together Interline OSM Extracts (in GeoJSON format) with HERE XYZ Spaces (basemaps, CLI, and API). This tutorial assumes an intermediate level of skill.

What you'll learn

Prerequisites

OpenStreetMap (also known as OSM) is a crowdsourced, worldwide dataset that changes minute by minute. To work with the entire planet's worth of OSM data is a challenge for beginners. Furthermore, OSM data is typically stored in custom formats (XML or Protocol Buffer), unfamiliar to most users of GIS or mapping software. Instead of using OSM directly, we'll use the Interline OSM Extracts service to download data in the standard GeoJSON format for one region at a time.

We'll show you how to download OSM map data for Honolulu, Hawaii. Following the same instructions, you can then try downloading OSM data for another metropolitan region of your choice.

First, sign up for a free Interline OSM Extracts account. You will soon receive an email with an API token. Copy this API token to your clipboard — you'll use it shortly.

Next, open the Interline OSM Extracts website. Paste your API token into the form:

OSM Extracts screenshot: API token

Now, scroll and click on Honolulu on the list of available extracts. (You can use your web browser's "find in this page" functionality to speed up the process.) Select "GeoJSON" for download format. Click the "Download" button:

OSM Extracts screenshot: download Honolulu

Save the file to your computer. You'll need to open this file in your terminal, so place it in a directory that is memorable and easy to find.

We need to create an XYZ space to store, filter, and visualize our Interline OSM extract.

If you haven't already installed and configured the HERE CLI, follow this tutorial.

Now that you have the XYZ, run the following command to create a new space:

here xyz create -t 'tutorial'

This will return an ID for a new space, which in this example is e9PEZgZg:

xyzspace 'e9PEZgZg' created successfully

Copy and paste the ID into the following command. This will set an "environment variable" that stores the space ID. This will make it easier for us to reuse the space ID as an argument in future commands:

SPACE_ID=<returned space id>

Now that you have both the HERE CLI and an Interline OSM extract for Honolulu, let's upload it to your XYZ space.

OSM data includes hundreds of possible tags. Tags are all crowdsourced and can provide a street address or opening hours for a business. Or tags can be used to mark whether bicycles are allowed on a trail. To explore the wide range of possible OSM tags, see https://taginfo.openstreetmap.org/

Let's explore the amenity, shop and tourism tags around Honolulu. When importing the GeoJSON extract into your XYZ space, you'll mark these three as GeoJSON properties to turn into XYZ tags. Run the following command:

here xyz upload $SPACE_ID -f honolulu_hawaii.geojson -p amenity,shop,tourism

Now that you've uploaded and tagged your GeoJSON file, let's explore the data in the XYZ space. We'll look at the range of tags using the text-based CLI and using the HERE GeoJSON Viewer in your web browser. While exploring the data, we'll think about what we'd like to filter and visualize on a HERE web map.

To describe the tags using the CLI, run:

here xyz describe $SPACE_ID

The output will list counts of the number of features (that is, locations) that have each of the tags and values. Note how there are 1,122 features tagged amenity@parking:

output of here xyz describe command

Let's visualize some of the locations that have the amenity tag with a value of parking. In other words, let's look at parking lots around Honolulu. Run the following command to open the GeoJSON Viewer in your web browser:

here xyz show $SPACE_ID -w --tags=amenity@parking

In your web browser, you should now see an interactive map of parking lots in Honolulu. These are just some of the many locations in the original Interline OSM extract. XYZ Spaces has taken the large GeoJSON file, tagged the many locations, and filtered only the parking lots for display:

GeoJSON Viewer showing parking lots in Honolulu

Here are some other tags you can explore:

You can rerun the previous command with a new value after --tags. Or you can edit the URL in your existing web browser tab like so:

editing the GeoJSON Viewer URL

Now that we've selected a few tags that interest us, we'll use our XYZ space to create a web map. The tutorial will provide all of the necessary HTML and JavaScript code for the web map. We'll point out a few ways that you can customize your map further, to display different types of locations or to change the styling.

For more information on how to create web maps using XYZ, see also this tutorial.

Using your favorite text editor, copy and paste the following code as the index.html file in your project directory. This HTML code provides the basic XYZ Maps JS dependencies and an HTML element to serve as the placeholder for the map. When opened in a browser, this webpage will load the index.js script and turn the placeholder into an interactive map component:

<!DOCTYPE html>
<html>
<head>
    <style type="text/css">
    body {
        margin: 0px;
        padding: 0px;
    }
    #map {
        width: 100%;
        height: 100vh;
    }
    </style>
    <script src="https://xyz.api.here.com/maps/latest/xyz-maps-common.min.js" type="text/javascript" charset="UTF-8" ></script>
    <script src="https://xyz.api.here.com/maps/latest/xyz-maps-core.min.js" type="text/javascript" charset="UTF-8" ></script>
    <script src="https://xyz.api.here.com/maps/latest/xyz-maps-display.min.js" type="text/javascript" charset="UTF-8" ></script>
    <script src="https://xyz.api.here.com/maps/latest/xyz-maps-plugins.min.js" type="text/javascript" charset="UTF-8" ></script>
</head>
<body>
    <div id="map"></div>
    <script src="index.js" type="text/javascript" charset="UTF-8"></script>
</body>
</html>

Using your favorite text editor, copy and paste the following code into a file in your project directory. Save it as index.js. This sets up a basic web map using the XYZ Maps JS library:

// Provide your access token
var ACCESS_TOKEN = "REPLACE-WITH-YOUR-ACCESS-TOKEN";
var mapZoomLevel = 12;
var mapCenter = {longitude: -157.85915, latitude: 21.31629};

// Base layer
var layers = [];
// Base layer
// MVT example and styling from: https://xyz.api.here.com/maps/latest/playground/index.html#core_MVTLayer
var baseLayer = new here.xyz.maps.layers.MVTLayer({
    name: 'mvt-world-layer',
    remote: {
        url: 'https://xyz.api.here.com/tiles/osmbase/256/all/{z}/{x}/{y}.mvt',
        credentials: { access_token: ACCESS_TOKEN }
    },
    min: 1,
    max: 20,
    style: {
        backgroundColor: '#555555',
        strokeWidthZoomScale: function (level) {
            return level > 17 ? 1 : level > 14 ? .5 : .25
        },
        styleGroups: {
            'earth': [{ zIndex: 1, type: 'Polygon', fill: '#555555' }],
            'water': [{ zIndex: 2, type: 'Polygon', fill: '#353535' }],
            'landuse': [{ zIndex: 3, type: 'Polygon', fill: '#666666' }],
            'roads': [{ zIndex: 4, type: 'Line', stroke: '#ffffff', strokeWidth: 4 }],
            'roadshighway': [{ zIndex: 5, type: 'Line', stroke: '#ffffff', strokeWidth: 6 }],
            'buildings': [{ zIndex: 7, type: 'Polygon', fill: '#999999' }]
        },
        assign: function (feature, level) {
            var props = feature.properties;
            var kind = props.kind;
            var layer = props.layer; // the data layer of the feature
            var geom = feature.geometry.type;

            if (layer == 'water') {
                if (geom == 'LineString' || geom == 'MultiLineString') {
                    return;
                }
            }
            if (layer == 'roads') {
                if (kind == 'rail' || kind == 'ferry') {
                    return;
                }
                if (kind == 'highway') {
                    return layer + kind;
                }
            }
            return layer;
        }
    }
});
layers.push(baseLayer);

// Display map on #map
window.display = new here.xyz.maps.Map(document.getElementById("map"), {
    zoomLevel: mapZoomLevel,
    center: mapCenter,
    layers: layers
});

Where the scripts says REPLACE-WITH-YOUR-ACCESS-TOKEN, copy and paste your HERE XYZ access token. For more information on how to manage tokens, see the XYZ Hubs APIs documentation. Don't forget to save the file after making this edit. Additionally, the initial zoom level and map location are set as parameters to the here.xyz.maps.Map constructor, and can be changed if desired.

Add provider and space with tags

Next, we'll add more code to index.js. Copy and paste the following, making sure to change REPLACE-WITH-YOUR-SPACE-ID with your XYZ space ID (it should be the same value as when you ran the command SPACE_ID=...):

// HERE spaces
var space_id = 'REPLACE-WITH-YOUR-SPACE-ID';
var tags = ['amenity@bank,amenity@parking'];
var amenityStyle = null;
var provider = new here.xyz.maps.providers.SpaceProvider({
    name: 'HERE XYZ',
    level: 10,
    space: space_id,
    tags: tags,
    credentials: { access_token: ACCESS_TOKEN }
});
var layer = new here.xyz.maps.layers.TileLayer({
    name: space_id,
    min: 10,
    max: 20,
    provider: provider,
    style: amenityStyle
});
layers.push(layer);

The above code adds an overlay to your web map. It filters for locations with tags of amenity@bank and amenity@parking. In other words, it will display bank locations and parking lots from the crowdsourced Interline OSM extract. You can modify the tags in your script to display different locations instead.

Style map

Finally, let's apply styling to make sure that the ATM and bank locations are visible and attractive. For more on how on styling using the XYZ Maps JS library, see https://xyz.api.here.com/maps/latest/documentation/here.xyz.maps.layers.TileLayer.Style.html

Paste the following style definition into index.js, replacing the previous var amenityStyle = null:

var amenityStyle = {
    styleGroups: {
        parking: [
            {zIndex:0, type:"Line", stroke:"#1b9e77", strokeWidth:5}
        ],
        bank: [
            {zIndex:1, type:"Circle", radius:5, fill:"#d95f02", opacity: 0.8},
            {zIndex:2, type:"Line", stroke:"#d95f02", strokeWidth:5},
        ]
    },
    assign: function (feature, zoomlevel) {
        return feature.properties.amenity;
    }
};

The map style has two ingredients. First, a set of styleGroups that define how features will be drawn on the map, and second, an assign function that associates each feature to a key in styleGroups.

In this example, the style is determined by the value of the amenity tag. Parking features will be drawn with a simple green outline, and bank features will be drawn with an orange outline as well as small circles at each corner or as a single point. If the assign function returns null — if the feature is not an amenity — the feature will not be drawn.

If you want to display different tags on the map, you'll have to modify both the stylesGroups and the assign function.

Full index.js

For reference, here is what your complete index.js file should look like now:

// Provide your access token
var ACCESS_TOKEN = "REPLACE-WITH-YOUR-ACCESS-TOKEN";
var mapZoomLevel = 12;
var mapCenter = {longitude: -157.85915, latitude: 21.31629};

// Base layer
var layers = [];
var baseLayer = new here.xyz.maps.layers.TileLayer({
    name: 'Image Layer',
    min: 1,
    max: 20,
    provider: new here.xyz.maps.providers.ImageProvider({
        name: 'Live Map',
        url: 'https://{SUBDOMAIN_INT_1_4}.mapcreator.tilehub.api.here.com/tilehub/wv_livemap_bc/png/sat/256/{QUADKEY}?access_token=' + ACCESS_TOKEN
    })
});
layers.push(baseLayer);

// HERE spaces
var space_id = 'REPLACE-WITH-YOUR-SPACE-ID';
var tags = ['amenity@bank,amenity@parking'];
var amenityStyle = {
    styleGroups: {
        parking: [
            {zIndex:0, type:"Line", stroke:"#1b9e77", strokeWidth:5}
        ],
        bank: [
            {zIndex:1, type:"Circle", radius:5, fill:"#d95f02", opacity: 0.8},
            {zIndex:2, type:"Line", stroke:"#d95f02", strokeWidth:5},
        ]
    },
    assign: function (feature, zoomlevel) {
        return feature.properties.amenity || 'default';
    }
};
var provider = new here.xyz.maps.providers.SpaceProvider({
    name: 'HERE XYZ',
    level: 10,
    space: space_id,
    tags: tags,
    credentials: { access_token: ACCESS_TOKEN }
});
var layer = new here.xyz.maps.layers.TileLayer({
    name: space_id,
    min: 10,
    max: 20,
    provider: provider,
    style: amenityStyle
});
layers.push(layer);

// Display map on #map
window.display = new here.xyz.maps.Map(document.getElementById("map"), {
    zoomLevel: mapZoomLevel,
    center: mapCenter,
    layers: layers
});

Finally, let's open your index.html file in your web browser. Go to the File menu, select Open File, navigate to your project directory, and select index.html.

Here's what your map should look like:

screenshot of web map

Banks are outlined in orange. Parking lots are outlined in green.

This map will be a useful tool for any tourist traveling to Honolulu with a rental car and an errand to run at a bank!

In this tutorial, you've learned:

Using your new skills, here are some activities that you can do next: