Skylines in 3D
Midtown Manhattan, Chicago's Loop, and three more downtowns, with every building raised to its height in OpenStreetMap and shaded from low to tall. Drag with the right mouse button, or two fingers, to tilt and turn the map, and click a building for its height.
Build it yourself
The tiles carry OpenStreetMap's building heights, so one fill-extrusion layer on top of Mapricot's light style turns a flat city into a 3D one. It was tested with MapLibre GL JS 6.15 in Chromium.
What you need
Nothing but a web server to serve the page: the map tiles need no key.
Make the page
Make a folder, and in it index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Buildings in 3D</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@6.15.0/dist/maplibre-gl.css">
</head>
<body style="margin: 0">
<div id="map" style="height: 100vh"></div>
<script type="module">
import * as maplibregl from "https://cdn.jsdelivr.net/npm/maplibre-gl@6.15.0/+esm";
const map = new maplibregl.Map({
container: "map",
style: "https://tiles.mapricot.com/styles/light.json",
center: [-73.9845, 40.7536],
zoom: 15.4,
pitch: 55,
bearing: -28,
});
map.addControl(new maplibregl.NavigationControl({ visualizePitch: true }));
await map.once("load");
const labels = map.getStyle().layers.find((layer) => layer.type === "symbol").id;
const height = ["coalesce", ["get", "height"], 10];
map.addLayer(
{
id: "buildings-3d",
type: "fill-extrusion",
source: "protomaps",
"source-layer": "buildings",
paint: {
"fill-extrusion-height": height,
"fill-extrusion-base": ["coalesce", ["get", "min_height"], 0],
"fill-extrusion-color": ["interpolate", ["linear"], height, 0, "#cde2fb", 61, "#6da7ec", 152, "#256abf", 305, "#0d366b"],
"fill-extrusion-opacity": 0.9,
},
},
labels,
);
</script>
</body>
</html>
pitchtilts the map andbearingturns it, so the buildings show their sides. The navigation control's compass shows the tilt too, withvisualizePitch.- The new layer reads the
buildingslayer of the style's ownprotomapssource, so it needs no source of its own. heightandmin_heightare in meters. A building with no height in OpenStreetMap is drawn 10 meters tall, about three floors.min_heightlifts parts that start above the ground, such as a tower on a podium.- The color goes from pale blue for low buildings to navy at 305 meters, 1,000 feet.
- Adding the layer before the style's first label layer keeps the street and place names on top of the buildings.
Open it
Serve the folder with npx serve or python3 -m http.server, and open the address it prints. Opened straight from the file, the map stays blank, as Open the page explains. You should see Midtown Manhattan from the south, tilted. Drag with the right mouse button, or two fingers, to turn it.
To fly between cities like the map above, call map.flyTo({ center, zoom: 15.4, pitch: 55, bearing }) from a button. The map tiles docs list the tiles' other layers.
Data
- Buildings and their heights: OpenStreetMap contributors (ODbL), in Mapricot's map tiles