MapLibre GL JS is the standard for open source mapping on the web. Forked in response to Mapbox GL JS’ 2020 change to a proprietary license, MapLibre supports most features of Mapbox without the cost and terms. However, some features require a specific data source.
Bathymetry — ocean depth — data visualization improves aesthetics at low zoom levels by adding detail to what would otherwise be plain ocean. MapTiler makes it easy to add a bathymetry source to your style.
Let’s get started!
Adding the source in MapTiler
You’ll need a free MapTiler account and a custom map.
Open the map in the advanced style editor, click on Data Sources in the toolbar and then scroll down to select Ocean.
You should now see #ocean listed among your Active Sources.
Don’t forget to save and publish your style!
Adding the layer in MapLibre
With the data source in place, we’re ready to display the bathymetry data on our map. Open the source for your MapLibre map or create a new one, and update the style URL to match the MapTiler style you just created.
Add a fill layer with source "ocean”
, and source-layer "contour"
.
map.on("style.load", () => {
map.addLayer({
id: "bathymetry",
type: "fill",
source: "ocean",
"source-layer": "contour",
paint: {
"fill-color": "#111"
},
});
});
Our bathymetry layer is now visible — but it’s all black.
To visualize depth data with different colors, let’s write a step
expression to change the fill-color
property according to the value of the source’s "depth"
field.
paint: {
"fill-color":
[
"step",
["get", "depth"],
"#000",
-6000, "#111",
-5000, "#222",
-4000, "#333",
-3000, "#444",
-2000, "#555",
-1000, "#666",
-500, "#777",
-200, "#888",
],
},
Congrats, you’ve made a bathymetry visualization!
But there’s still two issues. Can you guess what they are before scrolling down? Perhaps if we zoom in around Florida?
Did you notice that the edges of our oceans are missing? That’s because shallow oceans (<50m deep) aren’t included in MapTiler’s "ocean"
source. Less surprisingly, neither are lakes.
We can display both by changing the color of the map’s water
layer, which is visible beneath our added bathymetry
layer. We could use the same color as our most shallow bathymetry layer, but I like to add one more slightly lighter shade:
map.setPaintProperty("water", "fill-color", "#999");
Have you noticed the remaining issue? This is an insidious one — do you see anything different at low zoom levels?
If you noticed that ocean labels have disappeared, you’re right! This is because our new bathymetry
layer has been added above all other layers, including label layers.
To be able to see our bathymetry
layer without obscuring labels, we need to place it directly above the water
layer.map.addLayer
accepts a second optional argument that is the layer that will be above our new layer, so to place our layer directly above the water
layer we pass in the layer currently directly above water
. You can see the layer stack in the sidebar of the MapTiler style editor or with map.getStyle().layers
.
As of June 2023, in MapTiler’s Streets style, this is theaeroway
layer. In the Light style, it is waterway.
Let’s put our layer in its place:
map.on("style.load", () => {
map.addLayer({
id: "bathymetry",
type: "fill",
source: "ocean",
"source-layer": "contour",
paint: {
"fill-color":
[
"step",
["get", "depth"],
"#000",
-6000, "#111",
-5000, "#222",
-4000, "#333",
-3000, "#444",
-2000, "#555",
-1000, "#666",
-500, "#777",
-200, "#888",
],
},
}, "waterway");
});
Labels are back, and there you have it!
Now you’re ready to style your bathymetry to suite your map.
Editing the fill-color
expression can be tedious. But never fear: here’s an Observable page to play around with different color ramps:
Next up: bathymetry in halftone!