diff --git a/_posts/2023-10-30-maps-3.md b/_posts/2023-10-30-maps-3.md
index c55734e..f5a4d9a 100644
--- a/_posts/2023-10-30-maps-3.md
+++ b/_posts/2023-10-30-maps-3.md
@@ -5,7 +5,7 @@ excerpt: |
PMTiles is a cool new technology to serve interactive vector maps from a static file.
image:
-thumbnail:
+thumbnail: /assets/blog/pmtiles/thumbnail.png
head: |
@@ -16,8 +16,12 @@ PMTiles is a new project that lets you serve vector map data from static files t
By following this [blog post][blog] and throwing in a bit of code from [the official examples][official_examples] I've put together this little map below. The vector data is entirely served from a static file on this server. Most interactive web maps work by constantly requesting little map images from an external server at different zoom levels. This approach uses much less data and doesn't require an external server to host all the map data.
+Todo:
+- Figure out how to use [maputnik][maputnik] to generate styles for PMTiles.
+
[blog]: https://til.simonwillison.net/gis/pmtiles
[official_examples]: https://github.com/protomaps/PMTiles/blob/main/js/examples/maplibre.html
+[maputnik]: maputnik.github.io/editor/
@@ -36,7 +40,7 @@ By following this [blog post][blog] and throwing in a bit of code from [the offi
let isDark = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
async function getLayers(isDark) {
- let style_name = isDark ? "dark.json" : "light.json";
+ let style_name = isDark ? "dark.json" : "custom.json";
const base = '{{"/assets/blog/pmtiles/" | relative_url}}';
let resp = await fetch(base + style_name);
let layers = await resp.json();
diff --git a/_projects/lego_adapters.md b/_projects/lego_adapters.md
index a06081f..96b03ab 100644
--- a/_projects/lego_adapters.md
+++ b/_projects/lego_adapters.md
@@ -5,7 +5,7 @@ excerpt: Adapters to use common components with lego technic.
permalink: /projects/lego_adapters
img:
- src: /assets/projects/lego_adapters/bw_thumbnail.svg
+ src: /assets/projects/lego_adapters/thumbnail.svg
alt:
class: invertable
---
\ No newline at end of file
diff --git a/assets/blog/pmtiles/custom.json b/assets/blog/pmtiles/custom.json
new file mode 100644
index 0000000..d20fe67
--- /dev/null
+++ b/assets/blog/pmtiles/custom.json
@@ -0,0 +1,166 @@
+[
+ {
+ "id": "water",
+ "type": "fill",
+ "source": "static_hackney",
+ "source-layer": "water",
+ "filter": ["all"],
+ "layout": {"visibility": "visible"}
+ },
+ {
+ "id": "roads_major",
+ "type": "line",
+ "source": "static_hackney",
+ "source-layer": "roads",
+ "filter": [
+ "all",
+ [
+ "==",
+ "pmap:level",
+ 0
+ ],
+ [
+ "==",
+ "pmap:kind",
+ "major_road"
+ ]
+ ],
+ "paint": {
+ "line-color": "black",
+ "line-width": 1.6
+ }
+ },
+ {
+ "id": "roads_medium",
+ "type": "line",
+ "source": "static_hackney",
+ "source-layer": "roads",
+ "minzoom": 0,
+ "filter": [
+ "all",
+ [
+ "==",
+ "pmap:level",
+ 0
+ ],
+ [
+ "==",
+ "pmap:kind",
+ "medium_road"
+ ]
+ ],
+ "paint": {
+ "line-color": "black",
+ "line-width": 1
+ }
+ },
+ {
+ "id": "roads_minor",
+ "type": "line",
+ "source": "static_hackney",
+ "source-layer": "roads",
+ "minzoom": 0,
+ "filter": [
+ "all",
+ [
+ "==",
+ "pmap:level",
+ 0
+ ],
+ [
+ "==",
+ "pmap:kind",
+ "minor_road"
+ ]
+ ],
+ "paint": {
+ "line-color": "black",
+ "line-width": 1
+ }
+ },
+ {
+ "id": "roads_labels_minor",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "roads",
+ "minzoom": 15,
+ "filter": [
+ "any",
+ [
+ "in",
+ "pmap:kind",
+ "minor_road",
+ "other",
+ "path"
+ ]
+ ],
+ "layout": {
+ "symbol-sort-key": [
+ "get",
+ "pmap:min_zoom"
+ ],
+ "symbol-placement": "line",
+ "text-font": [
+ "Roboto Regular"
+ ],
+ "text-field": [
+ "get",
+ "name"
+ ],
+ "text-size": 12
+ },
+ "paint": {
+ "text-color": "#000000",
+ "text-halo-color": "#ffffff",
+ "text-halo-width": 2
+ }
+ },
+ {
+ "id": "landuse_park",
+ "type": "fill",
+ "source": "static_hackney",
+ "source-layer": "landuse",
+ "filter": [
+ "any",
+ [
+ "in",
+ "pmap:kind",
+ "national_park",
+ "park",
+ "cemetery",
+ "protected_area",
+ "nature_reserve",
+ "forest",
+ "golf_course",
+ "hospital",
+ "industrial",
+ "school",
+ "university",
+ "college"
+ ]
+ ],
+ "paint": {
+ "fill-color": "black",
+ "fill-opacity": 0.1
+ }
+ },
+ {
+ "id": "natural_wood",
+ "type": "fill",
+ "source": "static_hackney",
+ "source-layer": "natural",
+ "filter": [
+ "any",
+ [
+ "in",
+ "pmap:kind",
+ "wood",
+ "nature_reserve",
+ "forest"
+ ]
+ ],
+ "paint": {
+ "fill-color": "black"
+ }
+ }
+]
\ No newline at end of file
diff --git a/assets/blog/pmtiles/thumbnail.png b/assets/blog/pmtiles/thumbnail.png
new file mode 100644
index 0000000..e53bee0
Binary files /dev/null and b/assets/blog/pmtiles/thumbnail.png differ
diff --git a/assets/blog/pmtiles/toner.json b/assets/blog/pmtiles/toner.json
new file mode 100644
index 0000000..3cfaaec
--- /dev/null
+++ b/assets/blog/pmtiles/toner.json
@@ -0,0 +1,434 @@
+[
+ {
+ "id": "background",
+ "type": "background",
+ "paint": {"background-color": "#fff"}
+ },
+ {
+ "id": "landcover_wood",
+ "type": "fill",
+ "source": "static_hackney",
+ "source-layer": "landcover",
+ "filter": ["==", "class", "wood"],
+ "paint": {
+ "fill-color": "rgba(218, 218, 218, 0.51)",
+ "fill-opacity": {"base": 1, "stops": [[8, 0.6], [22, 1]]}
+ }
+ },
+ {
+ "id": "landcover-grass",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1444849388993.3071"},
+ "source": "static_hackney",
+ "source-layer": "landcover",
+ "filter": ["==", "class", "grass"],
+ "paint": {"fill-color": "rgba(236, 235, 235, 1)", "fill-opacity": 1}
+ },
+ {
+ "id": "water",
+ "type": "fill",
+ "source": "static_hackney",
+ "source-layer": "water",
+ "filter": ["all", ["!=", "brunnel", "tunnel"]],
+ "layout": {"visibility": "visible"},
+ "paint": {}
+ },
+ {
+ "id": "building",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1444849364238.8171"},
+ "source": "static_hackney",
+ "source-layer": "building",
+ "layout": {"visibility": "visible"},
+ "paint": {
+ "fill-antialias": true,
+ "fill-color": {
+ "base": 1,
+ "stops": [
+ [15.5, "rgba(241, 240, 240, 1)"],
+ [16, "rgba(212, 212, 212, 1)"]
+ ]
+ }
+ }
+ },
+ {
+ "id": "building-top",
+ "type": "fill",
+ "metadata": {"mapbox:group": "1444849364238.8171"},
+ "source": "static_hackney",
+ "source-layer": "building",
+ "layout": {"visibility": "visible"},
+ "paint": {
+ "fill-color": "rgba(249, 249, 249, 1)",
+ "fill-opacity": {"base": 1, "stops": [[13, 0], [16, 1]]},
+ "fill-outline-color": "rgba(181, 180, 179, 1)",
+ "fill-translate": {"base": 1, "stops": [[14, [0, 0]], [16, [-2, -2]]]}
+ }
+ },
+ {
+ "id": "boundary-admin2_z0-4",
+ "type": "line",
+ "metadata": {},
+ "source": "static_hackney",
+ "source-layer": "boundary",
+ "maxzoom": 5,
+ "filter": ["all", ["==", "admin_level", 2], ["!has", "claimed_by"]],
+ "layout": {"visibility": "visible"},
+ "paint": {"line-width": 0.5}
+ },
+ {
+ "id": "boundary-admin2_z5-",
+ "type": "line",
+ "metadata": {},
+ "source": "static_hackney",
+ "source-layer": "boundary",
+ "minzoom": 5,
+ "filter": ["==", "admin_level", 2],
+ "layout": {"visibility": "visible"},
+ "paint": {"line-width": 0.5}
+ },
+ {
+ "id": "transportation",
+ "type": "line",
+ "metadata": {},
+ "source": "static_hackney",
+ "source-layer": "transportation",
+ "filter": ["all", ["==", "$type", "LineString"], ["!=", "class", "pier"]],
+ "layout": {"visibility": "visible"},
+ "paint": {
+ "line-color": {
+ "stops": [[12, "rgba(212, 209, 209, 1)"], [16, "rgba(8, 8, 8, 1)"]]
+ },
+ "line-width": {"stops": [[12, 0.5], [16, 1], [17, 3]]}
+ }
+ },
+ {
+ "id": "road_area_pier",
+ "type": "fill",
+ "metadata": {},
+ "source": "static_hackney",
+ "source-layer": "transportation",
+ "filter": ["all", ["==", "$type", "Polygon"], ["==", "class", "pier"]],
+ "layout": {"visibility": "visible"},
+ "paint": {
+ "fill-antialias": true,
+ "fill-color": "rgb(242,243,240)",
+ "fill-opacity": 1
+ }
+ },
+ {
+ "id": "road_pier",
+ "type": "line",
+ "metadata": {},
+ "source": "static_hackney",
+ "source-layer": "transportation",
+ "filter": ["all", ["==", "$type", "LineString"], ["in", "class", "pier"]],
+ "layout": {"line-cap": "round", "line-join": "round"},
+ "paint": {
+ "line-color": "rgb(242,243,240)",
+ "line-width": {"base": 1.2, "stops": [[15, 1], [17, 4]]}
+ }
+ },
+ {
+ "id": "place_label_other",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "place",
+ "minzoom": 8,
+ "filter": [
+ "all",
+ ["==", "$type", "Point"],
+ ["!in", "class", "city", "state", "country", "continent"]
+ ],
+ "layout": {
+ "text-anchor": "center",
+ "text-field": "{name:latin}\n{name:nonlatin}",
+ "text-font": ["Noto Sans Regular"],
+ "text-max-width": 6,
+ "text-size": {"stops": [[6, 10], [12, 14]]},
+ "visibility": "visible"
+ },
+ "paint": {
+ "text-color": "hsl(0, 10%, 25%)",
+ "text-halo-blur": 0,
+ "text-halo-color": "hsl(0, 0%, 100%)",
+ "text-halo-width": 2
+ }
+ },
+ {
+ "id": "highway-name-minor",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "transportation_name",
+ "minzoom": 15,
+ "filter": [
+ "all",
+ ["==", "$type", "LineString"],
+ ["in", "class", "minor", "service", "track"]
+ ],
+ "layout": {
+ "symbol-placement": "line",
+ "text-field": "{name:latin} {name:nonlatin}",
+ "text-font": ["Noto Sans Regular"],
+ "text-rotation-alignment": "map",
+ "text-size": {"base": 1, "stops": [[13, 12], [14, 13]]},
+ "visibility": "visible"
+ },
+ "paint": {
+ "text-color": "rgba(0, 0, 0, 1)",
+ "text-halo-blur": 0.5,
+ "text-halo-color": "rgba(255, 255, 255, 1)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "highway-name-major",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "transportation_name",
+ "minzoom": 12.2,
+ "filter": ["in", "class", "primary", "secondary", "tertiary", "trunk"],
+ "layout": {
+ "symbol-placement": "line",
+ "text-field": "{name:latin} {name:nonlatin}",
+ "text-font": ["Noto Sans Regular"],
+ "text-rotation-alignment": "map",
+ "text-size": {"base": 1, "stops": [[13, 12], [14, 13]]}
+ },
+ "paint": {
+ "text-color": "rgba(0, 0, 0, 1)",
+ "text-halo-blur": 0.5,
+ "text-halo-color": "rgba(255, 255, 255, 1)",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "place_label_city",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "place",
+ "maxzoom": 16,
+ "filter": ["all", ["==", "$type", "Point"], ["==", "class", "city"]],
+ "layout": {
+ "text-field": "{name:latin}\n{name:nonlatin}",
+ "text-font": ["Noto Sans Regular"],
+ "text-max-width": 10,
+ "text-size": {"stops": [[3, 12], [8, 16]]}
+ },
+ "paint": {
+ "text-color": "hsl(0, 0%, 0%)",
+ "text-halo-blur": 0,
+ "text-halo-color": "hsla(0, 0%, 100%, 0.75)",
+ "text-halo-width": 2
+ }
+ },
+ {
+ "id": "place-continent",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "place",
+ "filter": ["==", "class", "continent"],
+ "layout": {
+ "text-field": "{name:latin}",
+ "text-font": ["Metropolis Extra Bold Italic"],
+ "text-line-height": 1.5,
+ "text-max-width": 4,
+ "text-size": 13,
+ "visibility": "visible"
+ },
+ "paint": {"text-halo-color": "#fff", "text-halo-width": 2}
+ },
+ {
+ "id": "place-country",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "place",
+ "filter": ["==", "class", "country"],
+ "layout": {
+ "text-field": "{name:latin}",
+ "text-font": ["Noto Sans Bold"],
+ "text-size": 12,
+ "visibility": "visible"
+ },
+ "paint": {"text-halo-color": "#fff", "text-halo-width": 1.5}
+ },
+ {
+ "id": "poi-level-1",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "poi",
+ "minzoom": 14,
+ "filter": [
+ "all",
+ ["==", "$type", "Point"],
+ ["<=", "rank", 14],
+ ["has", "name"]
+ ],
+ "layout": {
+ "text-anchor": "top",
+ "text-field": "{name:latin}\n{name:nonlatin}",
+ "text-font": ["Noto Sans Italic"],
+ "text-max-width": 9,
+ "text-offset": [0, 0.6],
+ "text-padding": 2,
+ "text-size": 12
+ },
+ "paint": {
+ "text-color": "rgba(72, 71, 71, 1)",
+ "text-halo-blur": 0.8,
+ "text-halo-color": "#ffffff",
+ "text-halo-width": 1
+ }
+ },
+ {
+ "id": "waterway-name",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "waterway",
+ "minzoom": 13,
+ "filter": ["all", ["==", "$type", "LineString"], ["has", "name"]],
+ "layout": {
+ "symbol-placement": "line",
+ "symbol-spacing": 350,
+ "text-field": "{name:latin} {name:nonlatin}",
+ "text-font": ["Noto Sans Italic"],
+ "text-letter-spacing": 0.2,
+ "text-max-width": 5,
+ "text-rotation-alignment": "map",
+ "text-size": 14
+ },
+ "paint": {
+ "text-color": "rgba(6, 6, 6, 1)",
+ "text-halo-color": "rgba(245, 242, 242, 0.83)",
+ "text-halo-width": 1.5
+ }
+ },
+ {
+ "id": "water-name-lakeline",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "water_name",
+ "filter": ["==", "$type", "LineString"],
+ "layout": {
+ "symbol-placement": "line",
+ "symbol-spacing": 350,
+ "text-field": "{name:latin}\n{name:nonlatin}",
+ "text-font": ["Noto Sans Italic"],
+ "text-letter-spacing": 0.2,
+ "text-max-width": 5,
+ "text-rotation-alignment": "map",
+ "text-size": 14
+ },
+ "paint": {
+ "text-color": "rgba(255, 255, 255, 1)",
+ "text-halo-color": "rgba(255, 255, 255, 0)",
+ "text-halo-width": 1.5
+ }
+ },
+ {
+ "id": "water-name-ocean",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "water_name",
+ "filter": ["all", ["==", "$type", "Point"], ["==", "class", "ocean"]],
+ "layout": {
+ "symbol-placement": "point",
+ "symbol-spacing": 350,
+ "text-field": "{name:latin}",
+ "text-font": ["Noto Sans Italic"],
+ "text-letter-spacing": 0.2,
+ "text-max-width": 5,
+ "text-rotation-alignment": "map",
+ "text-size": 14,
+ "text-transform": "uppercase"
+ },
+ "paint": {
+ "text-color": "rgba(255, 255, 255, 1)",
+ "text-halo-color": "rgba(255, 255, 255, 0)",
+ "text-halo-width": 1.5
+ }
+ },
+ {
+ "id": "water-name-other",
+ "type": "symbol",
+ "source": "static_hackney",
+ "source-layer": "water_name",
+ "filter": ["all", ["==", "$type", "Point"], ["!in", "class", "ocean"]],
+ "layout": {
+ "symbol-placement": "point",
+ "symbol-spacing": 350,
+ "text-field": "{name:latin}\n{name:nonlatin}",
+ "text-font": ["Noto Sans Italic"],
+ "text-letter-spacing": 0.2,
+ "text-max-width": 5,
+ "text-rotation-alignment": "map",
+ "text-size": {"stops": [[0, 10], [6, 14]]},
+ "visibility": "visible"
+ },
+ "paint": {
+ "text-color": "rgba(255, 255, 255, 1)",
+ "text-halo-color": "rgba(255, 255, 255, 0)",
+ "text-halo-width": 1.5
+ }
+ },
+ {
+ "id": "boundary_state",
+ "type": "line",
+ "metadata": {"mapbox:group": "a14c9607bc7954ba1df7205bf660433f"},
+ "source": "static_hackney",
+ "source-layer": "boundary",
+ "filter": ["==", "admin_level", 4],
+ "layout": {
+ "line-cap": "round",
+ "line-join": "round",
+ "visibility": "visible"
+ },
+ "paint": {
+ "line-blur": 0.4,
+ "line-color": "rgba(72, 70, 70, 1)",
+ "line-dasharray": [0.5, 2],
+ "line-opacity": 1,
+ "line-width": {"base": 1.3, "stops": [[3, 1], [22, 15]]}
+ }
+ },
+ {
+ "id": "boundary_country_z0-4",
+ "type": "line",
+ "metadata": {"mapbox:group": "a14c9607bc7954ba1df7205bf660433f"},
+ "source": "static_hackney",
+ "source-layer": "boundary",
+ "maxzoom": 5,
+ "filter": ["all", ["==", "admin_level", 2], ["!has", "claimed_by"]],
+ "layout": {
+ "line-cap": "round",
+ "line-join": "round",
+ "visibility": "visible"
+ },
+ "paint": {
+ "line-blur": {"base": 1, "stops": [[0, 0.4], [22, 4]]},
+ "line-color": "rgba(82, 81, 81, 1)",
+ "line-opacity": 1,
+ "line-width": {"base": 1.1, "stops": [[3, 1], [22, 20]]}
+ }
+ },
+ {
+ "id": "boundary_country_z5-",
+ "type": "line",
+ "metadata": {"mapbox:group": "a14c9607bc7954ba1df7205bf660433f"},
+ "source": "static_hackney",
+ "source-layer": "boundary",
+ "minzoom": 5,
+ "filter": ["==", "admin_level", 2],
+ "layout": {
+ "line-cap": "round",
+ "line-join": "round",
+ "visibility": "none"
+ },
+ "paint": {
+ "line-blur": {"base": 1, "stops": [[0, 0.4], [22, 4]]},
+ "line-color": "rgba(82, 81, 81, 1)",
+ "line-opacity": 1,
+ "line-width": {"base": 1.1, "stops": [[3, 1], [22, 20]]}
+ }
+ }
+]
\ No newline at end of file
diff --git a/assets/projects/lego_adapters/bw_thumbnail.svg b/assets/projects/lego_adapters/bw_thumbnail.svg
deleted file mode 100644
index ad5399c..0000000
--- a/assets/projects/lego_adapters/bw_thumbnail.svg
+++ /dev/null
@@ -1,795 +0,0 @@
-
-
-
-
diff --git a/assets/projects/lego_adapters/thumbnail.svg b/assets/projects/lego_adapters/thumbnail.svg
new file mode 100644
index 0000000..efb9991
--- /dev/null
+++ b/assets/projects/lego_adapters/thumbnail.svg
@@ -0,0 +1,1822 @@
+
+
+
+