Leaflet layer for vector tiles
Leaflet.VectorTileLayer
=======================
This module provides a [Leaflet][L] layer that displays [vector tiles][VT].
It is very similar to [Leaflet.VectorGrid][LVG].
The biggest difference to VectorGrid is the styling.VectorTileLayer also supports two options min/maxDetailZoom which are
subtly different from VectorGrid's min/maxNativeZoom. Both provide the
possibility to specify a range of zoom levels that offer an optimal
trade-off between detail and size. When using the native variants, tiles
above or below the zoom range are scaled, changing the stroke weight. Thedetail settings offer the same trade-off while still rendering the tiles
at the correct zoom levels, meaning stroke weight is visually consistent
across all zoom levels.
Furthermore, VectorTileLayer gives clients full control over the SVG DOM
created for vector tile features. The layer option featureToLayer accepts
a function that can return any graphics for visualising a given feature
while making it easy to fall back to the default implementation.
In contrast to VectorGrid, this class has been designed as much as
possible in terms of Leaflet's public API. This makes it more likely to
continue working with future versions of Leaflet.
Use
---
Loads vector tiles from a URL template like
https://{s}.example.com/tiles/{z}/{x}/{y}.pbf
The URL template also supports the undocumented {-y} option for
»[inverted Y][Y]« if the map's [coordinate reference system][CRS] is finite
(the default).
This pacakge can be used as an ES6 module.
``js
import vectorTileLayer from 'leaflet-vector-tile-layer';
const tileLayer = vectorTileLayer(url, options);
`
The AMD build comes with all dependencies included. If imported as an ES6
module, the dependencies need to be made available to the build system, for
example:
`sh`
$ npm install @mapbox/vector-tile pbf
See this package's development dependencies for version information.
Layer options
-------------
The main difference to VectorGrid is that VectorTileLayer takes aVectorGrid
different approach to styling. Whereas only supports styling a
previously known set of vector-tile layer names, this class allows
specifying a single style for all layers irrespective of their names. When
specifying a function, it is called with the vector-tile feature, the layer
name and the current zoom level, enabling clients can handle layer names
dynamically or ignore them altogether.
Another feature not supported by VectorGrid is a setStyle() call which
allows changing the style of the entire layer.
For compatibility, support for the vectorTileLayerStyles option andset/resetFeatureStyle() method is also provided.
VectorTileLayer also supports ordering the layers based on their nameslayers: ["a", "b", "c"]
using an option like .
Another added feature of VectorTileLayer is a getBounds() function.load
After the event, it returns the bounds occupied by the features on
all currently loaded tiles.
VectorTileLayer allows clients to create their own DOM representation forfeatureToLayer
any given layer. A function provided to the option takes aLeaflet.Layer
vector-tile feature, the layer name, the number of SVG coordinate units per
vector-tile unit and the feature's style object. It should return an object
that eventually delegates to [][LYR] and provides thebbox()
following:
- a function that returns the feature's bounding box in SVGgraphics
coordinate units.
- a property that holds the top-level SVG DOM element.setStyle(style)
- a function that takes a style object and applies it
to the generated SVG elements.
VectorTileLayer supports all options provided by [GridLayer][GL].
Additionally, the following options are provided:
`js
const url = 'https://{s}.example.com/tiles/{z}/{x}/{y}.pbf';
const options = {
// A function that will be passed a vector-tile feature, the layer
// name, the number of SVG coordinate units per vector-tile unit
// and the feature's style object to create each feature layer.
featureToLayer, // default undefined
// Options passed to the fetch function when fetching a tile.
fetchOptions, // default undefined
// A function that will be used to decide whether to include a
// feature or not. If specified, it will be passed the vector-tile
// feature, the layer name and the zoom level. The default is to
// include all features.
filter, // default undefined
// A function that receives a list of vector-tile layer names and
// the zoom level and returns the names in the order in which they
// should be rendered, from bottom to top. The default is to render
// all layers as they appear in the tile.
layerOrder, // default undefined
// An array of vector-tile layer names from bottom to top. Layers
// that are missing from this list will not be rendered. The
// default is to render all layers as they appear in the tile.
layers, // default undefined
// Specify zoom range in which tiles are loaded. Tiles will be
// rendered from the same data for Zoom levels outside the range.
minDetailZoom, // default undefined
maxDetailZoom, // default undefined
// Either a single style object for all features on all layers or a
// function that receives the vector-tile feature, the layer name
// and the zoom level and returns the appropriate style options.
style, // default undefined
// This works like the same option for Leaflet.VectorGrid.
// Ignored if style is specified.
vectorTileLayerStyles, // default undefined
};
const layer = vectorTileLayer(url, options);
`
The style can be updated at any time using the setStyle() method.
`js`
layer.setStyle({ weight: 3 });
All omitted options will be substituted by the default options for
[L.CircleMarker][CM], [L.Polyline][PL] or [L.Polygon][PG], as
appropriate.
Style options
-------------
Style options are interpreted by the individual feature layers. For points,
these are L.CircleMarker options, or the icon property supplies anL.Icon to determine the appearance. For polylines or polygons, these areL.Path options. If the options.style property is a function, it will be
passed the vector-tile feature, the layer name and the zoom level as
parameters.
If the style option interactive is true, the created SVG elements will
listen to mouse events.
The style option hidden permits any feature to be hidden. It operates byvisibility
setting the SVG attribute to hidden.
Feature layer helpers
---------------------
A few functions are made available to simplify creating custom layers for
individual features:
- defaultFeatureLayer(feature, layerName, pxPerExtent, options). ThisfeatureToLayer
function is used if the option is unset. It takes thefeatureCircleLayer(feature, layerName, pxPerExtent, options)
vector-tile feature, the layer name, the number of SVG coordinate units
per vector-tile unit and a style object and returns an appropriate layer
object to visualise it.
- returns afeatureIconLayer(feature, layerName, pxPerExtent, options)
layer object that visualises a vector-tile point feature.
- returns aLeaflet.Icon
layer object that visualises a vector-tile point feature using the
[][ICO] specified by options.icon.featurePathLayer(feature, layerName, pxPerExtent, options)
- returns afeatureLayerBase(feature, layerName, pxPerExtent, options)
layer object to visualise a vector-tile line or polygon feature.
- can be usedLeaflet.Layer
to create a layer object for a vector-tile feature. It returns an object
that eventually delegates to a [][LYR] instantiated with
the given options. The delegating object must provide:
- a graphics property that holds the top-level SVG DOM element.setStyle(style)
- a method that applies the given style to the
layer's DOM after enhancing it with the feature layer's default
options.
Objects created by this function provide the following:
- An applyOptions(style) function that should be called by agraphics
delegating object once the property is initialised. Itstyle.className
applies the option to it and then invokessetStyle({})
to allow the delegating object to apply its defaultbbox()
style.
- A function that returns the feature's bounding box in SVGVectorTileLayer.getBounds()
coordinate units and is used by .scalePoint(point)
- A function converts from vector-tile coordinates
to SVG coordinates.
A few functions are provided to simplify the implementation of
setStyle(style) functions:
- applyBasicStyle(element, style) applies the style.interactive andstyle.hidden
options to the given SVG DOM element.applyImageStyle(element, style)
- applies the height, width andhref
proprties from the [Leaflet.Icon][ICO] object in style.icon
to the SVG element.applyPathStyle(element, style)
- applies [Leaflet.Path][PT] style
properties to the SVG element.
Feature layer example
---------------------
The featureToLayer option on VectorTileLayer accepts a function that
can render custom SVG elements depending on feature properties, options,
layer names and zoom level.
Example drawing a thickened transparent overlay for polyline interaction:
`js
import {SVG} from "leaflet";
import {defaultFeatureLayer, featureLayerBase} from "leaflet-vector-tile-layer";
function interactiveLinesLayer(feature, layerName, pxPerExtent, options) {
// Construct a base feature layer.
const self = featureLayerBase(feature, layerName, pxPerExtent, options);
// Compose this feature layer of two sub-layers, one for the visible
// line controlled by options and a second controlled by the pathoptions.interaction
// options contained in . Both will share the same
// path geometry.
self.visibleLine = defaultFeatureLayer(
feature,
layerName,
pxPerExtent,
options
);
self.interactionLine = defaultFeatureLayer(
feature,
layerName,
pxPerExtent,
options.interaction
);
// Place the two layers in an SVG group.
const group = SVG.create("g");
group.appendChild(self.visibleLine.graphics);
group.appendChild(self.interactionLine.graphics);
self.graphics = group;
// Setting of style is delegated to the sub layers.
self.setStyle = function setStyle(style) {
self.visibleLine.setStyle(style);
self.interactionLine.setStyle(style.interaction);
};
// Initial setup of this feature layer.
self.applyOptions(options);
return self;
}
// Example options for the above custom renderer:
const interactiveLineOptions = {
color: "red",
weight: 2,
interaction: {
opacity: 0.0,
weight: 10
}
};
`
Events
------
Events attached to this layer provide access to the vector-tile featurelayerName
and the through their layer attribute. For compatibility withVectorGrid, the feature's properties are also made directly available.
Installing and building
-----------------------
You can install this package using
`sh`
$ npm install leaflet-vector-tile-layer
It can be built by
`sh`
$ npm run build
Limitations
-----------
At this time, only SVG rendering and vector tiles in [protobuf`][PBF]
format are supported, but support for other renderers or formats may be
added through options in the future.
[CM]: https://leafletjs.com/reference.html#circlemarker
[CRS]: https://leafletjs.com/reference#crs
[ICO]: https://leafletjs.com/reference.html#icon
[GL]: https://leafletjs.com/reference.html#gridlayer
[LVG]: https://github.com/Leaflet/Leaflet.VectorGrid
[LYR]: https://leafletjs.com/reference.html#layer
[L]: http://leafletjs.com/
[PBF]: https://developers.google.com/protocol-buffers/
[PG]: https://leafletjs.com/reference.html#polygon
[PL]: https://leafletjs.com/reference.html#polyline
[PT]: https://leafletjs.com/reference.html#path
[VT]: https://github.com/mapbox/vector-tile-spec
[Y]: https://github.com/Leaflet/Leaflet/issues/4284