Skip to content

Vector Tiles

Overview

This example displays Mapbox Vector Tiles for a simplified countries dataset from Natural Earth.

Mapfile Configuration

The Mapbox Vector Tile (MVT) output format is available if MapServer is built with MVT support enabled, as in the case of the MapServer Docker image used by the workshop. No particular changes are required in a Mapfile to serve vector tiles.

Adding Vector Tiles to OpenLayers

There are two ways to request vector tiles from MapServer:

  1. Using Tile Mode, as in the Image Tiles example. The only change is to add &map.imagetype=mvt to the request string.

  2. Using a WMS interface, and adding the following to the request strings - &FORMAT=application/x-protobuf.

In this example we are using the tile mode approach, based on the OpenLayers vector tile example. We supply a template URL, and make sure we include &map.imagetype=mvt as part of the querystring:

new VectorTileLayer({
    source: new VectorTileSource({
        format: new MVT(),
        url:
            mapserverUrl + mapfilesPath + 'vector-tiles.map&MODE=tile&TILE={x}+{y}+{z}&LAYERS=countries&map.imagetype=mvt',
    }),
    style: function (feature) {
        return new Style({
            stroke: new Stroke({
                color: 'rgb(66, 133, 244)', // Light blue border color
                width: 2, // Border width
            })
        });
    },
}),

Code

Example

vector-tiles.js
import '../css/style.css';
import MVT from 'ol/format/MVT.js';
import Map from 'ol/Map.js';
import VectorTileLayer from 'ol/layer/VectorTile.js';
import VectorTileSource from 'ol/source/VectorTile.js';
import View from 'ol/View.js';
import { Fill, Stroke, Style } from 'ol/style.js';

// https://openlayers.org/en/latest/examples/mapbox-vector-tiles.html

const mapserverUrl = import.meta.env.VITE_MAPSERVER_BASE_URL;
const mapfilesPath = import.meta.env.VITE_MAPFILES_PATH;

const map = new Map({
    layers: [
        new VectorTileLayer({
            source: new VectorTileSource({
                format: new MVT(),
                url:
                    mapserverUrl + mapfilesPath + 'vector-tiles.map&MODE=tile&TILE={x}+{y}+{z}&LAYERS=countries&map.imagetype=mvt',
            }),
            style: function (feature) {
                return new Style({
                    stroke: new Stroke({
                        color: 'rgb(66, 133, 244)', // Light blue border color
                        width: 2, // Border width
                    }),
                    // fill: new Fill({
                    //    color: 'rgba(66, 133, 244, 0.4)' // semi-transparent blue fill
                    //})
                });
            },
        }),
    ],
    target: 'map',
    view: new View({
        center: [-472202, 7530279],
        zoom: 2,
    }),
});
vector-tiles.map
MAP
    NAME "Vector Tiles"
    EXTENT -20037508.34 -20048966.1 20037508.34 20048966.1
    SIZE 256 256
    PROJECTION
        "epsg:3857"
    END
    LAYER
        NAME "countries"
        TYPE POLYGON
        PROJECTION
            "epsg:4326"
        END
        EXTENT -180.0 -90.0 180.0 90
        STATUS OFF
        # If want to include attributes in the tiles add
        # the METADATA block
        METADATA
            "gml_include_items" "all"
            "gml_types" "auto"
        END
        CONNECTIONTYPE FLATGEOBUF
        DATA "data/naturalearth/ne_110m_admin_0_countries.fgb"
    END
END

Exercises

  1. Update the layer to use the data/naturalearth/ne_110m_lakes dataset.
  2. Update the OpenLayers style to use a blue fill for the lakes. In the Style function you will need to uncomment the fill JavaScript. Experiment with different colour values for the fill and stroke.