basemapkit
Version:
<p align="center"> <img src="./public/logo.svg" alt="Basemapkit logo" width="400px"></img> </p> <p align="center"> Basemaps for <a href="https://maplibre.org/maplibre-gl-js/docs/">Maplibre GL JS</a> + <a href="https://protomaps.com/">Protomaps</a> </p>
370 lines (311 loc) • 11.4 kB
Markdown
<p align="center">
<img src="./public/logo.svg" alt="Basemapkit logo" width="400px"></img>
</p>
<p align="center">
Basemaps for <a href="https://maplibre.org/maplibre-gl-js/docs/">Maplibre GL JS</a> + <a href="https://protomaps.com/">Protomaps</a>
</p>
<p align="center">
<img src="https://img.shields.io/npm/v/basemapkit"></img>
</p>
**Basemapkit** generates customizable styles compatible with **Maplibre GL JS** that relies on the **Protomaps** Planet schemas when it comes to [vector layers and feature properties](https://docs.protomaps.com/basemaps/layers). You can download your own PMtiles copy of the planet on the official [Protomaps build page](https://maps.protomaps.com/builds/).
| | | |
| :----------------: | :------: | ----: |
|  |  |  |
|  | |  |
|  |  |  |
## Getting started
### Install
On an existing ES project:
```bash
npm install basemapkit
```
### Add some style
The following example instantiates a Maplibre `Map`, then initializes the Protomaps protocol and then generates a style with Basemapkit:
```ts
import "maplibre-gl/dist/maplibre-gl.css";
import maplibregl from "maplibre-gl";
import { Protocol } from "pmtiles";
import { getStyle, getStyleList } from "basemapkit";
// Adds the Protomaps protocol:
maplibregl.addProtocol("pmtiles", new Protocol().tile);
// Build the Basemapkit style
const style = getStyle(
// One of the main syle:
"avenue",
{
// URL to the pmtiles
pmtiles: "https://my-s3-bucket.com/planet.pmtiles",
// URL to the sprites (for POIs)
sprite: "https://raw.githubusercontent.com/jonathanlurie/phosphor-mlgl-sprite/refs/heads/main/sprite/phosphor-diecut",
// URL to the glyphs (for labels)
glyphs: "https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf";
// Language (you can ommit to use the platform language)
lang: "en",
});
// Instantiate the Map:
const map = new maplibregl.Map({
container: "map",
center: [0, 0],
zoom: 3,
// Add the Basemapkit style:
style,
});
```
If using a traditional `tile.json` and `z/x/y` tiles instead of http-range-requesting a `pmtiles` file, then replace the option `pmtiles` by `tilejson`, as in the example below:
```ts
const style = getStyle(
// One of the main syle:
"avenue",
{
// URL to the tile.json
tilejson: "https://example.com/tile.json",
// URL to the sprites (for POIs)
sprite: "https://raw.githubusercontent.com/jonathanlurie/phosphor-mlgl-sprite/refs/heads/main/sprite/phosphor-diecut",
// URL to the glyphs (for labels)
glyphs: "https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf";
// Language (you can ommit to use the platform language)
lang: "en",
});
```
This can get particularly handy when using the [Protomaps CLI](https://docs.protomaps.com/pmtiles/cli) or [Martin](https://martin.maplibre.org/) to serve `z/x/y` vector tiles.
## Language
Basemakit styles are compatible with Protomaps languages properties and uses [`/basemaps`](https://docs.protomaps.com/basemaps/flavors) under the hood.
The only addition from **Basemapkit** is the capability to detect the end user's platform language, so if the `lang` option is omitted, it will automatically use the language set by the user at the browser or OS level.
Here is the list of supported languages:
```ts
"ar" | "cs" | "bg" | "da" | "de" | "el" | "en" | "es" | "et" | "fa" | "fi" | "fr" | "ga" | "he" | "hi" | "hr" | "hu" | "id" | "it" | "ja" | "ko" | "lt" | "lv" | "ne" | "nl" | "no" | "mr" | "mt" | "pl" | "pt" | "ro" | "ru" | "sk" | "sl" | "sv" | "tr" | "uk" | "ur" | "vi" | "zh-Hans" | "zh-Hant"
```
## POIs and labels
There are options to hide the points of interests and labels. By default, both are shown, meaning the options goes like this:
```ts
getStyle(
"avenue",
{
pmtiles: "...",
sprite: "...",
glyphs: "...",
hidePOIs: false,
hideLabels: false,
});
```
So by default, London looks like this:

But POIs can be hidden by doing this:
```ts
getStyle(
"avenue",
{
pmtiles: "...",
sprite: "...",
glyphs: "...",
hidePOIs: true,
hideLabels: false,
});
```
Then the same locations looks like this:

Alternatively, the labels can be hidden, this includes POIs' labels, so only POIs' icons will be shown by doing this:
```ts
getStyle(
"avenue",
{
pmtiles: "...",
sprite: "...",
glyphs: "...",
hidePOIs: false,
hideLabels: true,
});
```
here is how it looks like:

And finally, both labels and POIs can be hidden, resulting in a somewhat mysterious map:
```ts
getStyle(
"avenue",
{
pmtiles: "...",
sprite: "...",
glyphs: "...",
hidePOIs: true,
hideLabels: true,
});
```

Note that the corresponding layers are removed from the style and not just made invisible. If hiding POIs or label, the options `sprite` and `glyph` are unnecessary.
## Getting creative with `buildStyle()`
In addition to language and hiding POIs/labels, Basmapkit exposes some methods to modify the colors of the original style (`avenue`) to create *presets*. When the style is generated with some non-default `colorEdit`, a brand new Maplibre style is created and can be directly injected into a Maplibre `Map` instance's `.setStyle()` method, or even written as a static json file.
```ts
buildStyle({
pmtiles: "...",
sprite: "...",
glyphs: "...",
hidePOIs: false,
hideLabels: false,
// At the moment, "avenue" is the only style to start from
baseStyleName: "avenue",
colorEdit: {
// Invert the colors:
negate: false,
// In the range [-1, 1]:
brightness: 0,
// In the range [-1, 1]:
brightnessShift: 0,
// In the range [-1, 1]:
exposure: 0,
contrast: [
// intensity in the range [-1, 1]:
0,
// Midpoint in [0, 255]
127
],
// Rotate around the hue wheel, in range [0, 360]
hueRotation: 0,
// In the range [-1, 1]
// with -1 being gray levels and 1 being extra boosted colors
saturation: 0,
// Color blending with a multiply method
multiplyColor: [
// Color to multiply with
"#ff0000",
// blending factor in [0, 1]
// with 0 being the original color and 1 being the the color above
0
],
// Linear color blending
mixColor: [
// Color to blend with
"#ff0000",
// blending factor in [0, 1]
// with 0 being the original color and 1 being the the color above
0
]
}
}
);
```
For instance, let's create a TMNT toxic N.Y.C. kind of map:
```json
{
"baseStyleName": "avenue",
"lang": "en",
"hidePOIs": true,
"hideLabels": false,
"colorEdit": {
"negate": true,
"brightness": 0.4,
"brightnessShift": 0,
"exposure": 0.8,
"contrast": [
0.4,
160
],
"hueRotation": 80,
"saturation": 0.12,
"multiplyColor": [
"#ff00ff",
0.6
],
"mixColor": [
"#00ff00",
0.3
]
}
}
```
And here is the result:

You can live play with these on [basemapkit.jnth.io](https://s.jnth.io/s/basemapkit) and selecting the style `🖌️ custom 🎨`.
And from this "color editor" were created the built-in styles available below...
## Style presets available
Some custom `colorEdit` recipes are already built in Basemapkit and can be accessed directly from the `getStyle()` function.
### `avenue` ⤵️
This one is the default, with all the `colorEdit` options set to default:
```ts
// Create the style
const style = getStyle("avenue", options);
```





### `avenue-pop` ⤵️
```ts
// Create the style
const style = getStyle("avenue-pop", options);
```





### `avenue-night` ⤵️
```ts
// Create the style
const style = getStyle("avenue-night", options);
```





### `avenue-bright` ⤵️
```ts
// Create the style
const style = getStyle("avenue-bright", options);
```





### `avenue-saturated` ⤵️
```ts
// Create the style
const style = getStyle("avenue-saturated", options);
```





### `avenue-warm` ⤵️
```ts
// Create the style
const style = getStyle("avenue-warm", options);
```





### `avenue-vintage` ⤵️
```ts
// Create the style
const style = getStyle("avenue-vintage", options);
```





### `avenue-bnw` ⤵️
```ts
// Create the style
const style = getStyle("avenue-bnw", options);
```





### `avenue-blueprint` ⤵️
```ts
// Create the style
const style = getStyle("avenue-blueprint", options);
```




