How to create your own vector tile web maps
Hi. Welcome to exciting maze.yuiseki.icon
Nowadays, there has been an industry standard process for creating your own vector tile web maps.
This document show that process as step by step.
TL;DR
Abstruct
3. Generate *.mbtiles -> /{z}/{x}/{y}/*.pbf
4. Deploy /{z}/{x}/{y}/*.pbf to server
5. Write TileJSON file of your vector tile server and deploy to server 7. Write HTML/CSS/JS that load and draw the maps based on style.json
Befor to begin
What is vector tile? What is so convenient about it? How should I make it? There is a good document on GitHub repository of tilemaker Point is below
Vector tile is a binary data format for digital maps
Vector tile has just only data of geometry and attributes
Maps based on vector tile will rendering by browser (or application), based on those geometry and attributes data with style definition
That means vector tile has capability to flexibly customize appearance at rendering time
Digital maps based on image can not change appearance after once generated images
When we want to provide multiple appearance maps, It will require a huge amount of image data
This is advantage of vector tile
Basically, Vector tile has no detailed rule about the data attributes, But there is industry standard data scheme
We need standard data scheme, Because vector tile file format is too flexible to styling maps by ourself
There is a lot of open source style difinition based on OpenMapTiles scheme We should be riding on the shoulders of giants
Reference
Select region you want to create maps
Download *.pbf file
NOTE:
What is this site?
download.geofabrik.de is, Amazingly, provide the free download server of snapshot data of OpenStreetMap of whole Earth scale What is the pbf file?
Refecence
code:bash
git clone git@github.com:systemed/tilemaker.git
cd tilemaker
If you can successfully make tilemaker, the command you should run is below: code:bash
tilemaker --input tmp/region.pbf --output tmp/region.mbtiles
I know that make tilemaker is quite difficult... code:bash
make clean # dont forget clean if you have tried to make tilemaker on host machine!
docker build . -t tilemaker
docker run --rm --mount type=bind,source=$(CURDIR)/tmp,target=/tmp tilemaker --input /tmp/region.pbf --output /tmp/region.mbtiles
If you want to more customize your maps, read the docs of tilemaker NOTE:
Reference
Generate *.mbtiles -> /{z}/{x}/{y}/*.pbf
code:bash
git clone git@github.com:mapbox/tippecanoe.git
cd tippecanote
If you can successfully make tippecanoe, the command you should run is below: code:bash
tile-join --force --no-tile-compression --no-tile-size-limit --no-tile-stats --output-to-directory=docs/zxy path/to/region.mbtiles
code:bash
make clean
docker build -t tippecanoe .
docker run -it --rm --mount type=bind,source=$(CURDIR)/tmp,target=/tmp tippecanoe tile-join --force --no-tile-compression --no-tile-sizelimit --no-tile-stats --output-to-directory /tmp/zxy /tmp/region.mbtiles
cp -r tmp/zxy docs/
NOTE:
What is this step?
In fact, you can serve directory MBTiles file as vector tile server But that will require keep running some application server that dynamically convert MBTiles to /{z}/{x}/{y}/*.pbf Deploy /{z}/{x}/{y}/*.pbf to server
For simplify, you might be generate zxy files under the directory that named like docs/zxy/{z}/{x}/{y}/*.pbf
docs directory has special meanings on GitHub
You can directly deploy contents of this directory as a GitHub Pages
Dont forget: You must change settings of Pages section of your GitHub repository to publish docs directory
Write TileJSON file of your vector tile server and deploy to server code:bash
npm i -g mbtiles2tilejson
I'm using osm-bright-gl-style based style.json that has fixed glyphs issue
I recommend copy this style.json
Write HTML/CSS/JS that load and draw the maps based on style.json
code:docs/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vector tile builder Demo</title>
<link
rel="stylesheet"
/>
<style>
html,
body,
width: 100vw;
height: 100vh;
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
(async () => {
let map;
const res = await fetch("./tiles.json");
const tilejson = await res.json();
const bounds = tilejson.bounds;
const center = tilejson.center
? tilejson.center
: [(bounds0 + bounds2) / 2, (bounds1 + bounds3) / 2]; const zoom = (tilejson.minzoom + tilejson.maxzoom) / 2;
console.log(center, zoom);
map = new maplibregl.Map({
container: "map",
style: "./style.json",
center: center,
zoom: 5,
});
map.addControl(new maplibregl.NavigationControl());
map.addControl(
new maplibregl.AttributionControl({
compact: false,
customAttribution:
})
);
})();
</script>
</body>
</html>