I am using mapbox-gl-js to render points from a geojson file onto a map.
For each point I also show a label underneath the marker icon. I currently do this with the following code:
map.addSource("mypoints", {
type: "geojson",
data: "mypoints.geojson",
});
map.addLayer({
"id": "layer-mypoints",
"type": "symbol",
"source": "mypoints",
"layout": {
"icon-image": "marker-15",
"text-field": "{name}",
"text-anchor": "top"
}
});
This works as expected and the points are added to the map and the label is rendered under each point.
To make the map less cluttered I would like to hide the labels when the map is zoomed out past a certain zoom level (and vice versa show the labels when the map is zoomed in). I always want to show the point icons no matter what the zoom level is.
Mapbox GL maps render at a high frame rate. The abbreviation "GL" comes from OpenGL, the industry-standard Open Graphics Library. Mapbox GL allows you to use custom styles designed in Mapbox Studio.
After doing some more thinking/reading/testing I think I have found a solution to the problem.
I now add one layer that only shows the icons, and also add a second layer that only contains the labels. In this second layer I set the 'minzoom' property to the zoom level where I want the labels to appear when the user zooms in the map.
map.addSource("mypoints", {
type: "geojson",
data: "mypoints.geojson",
});
// Layer with icons that should always be visible
map.addLayer({
"id": "layer-mypoints",
"type": "symbol",
"source": "mypoints",
"layout": {
"icon-image": "monument-15",
"icon-allow-overlap": true
}
});
// Layer with just labels that are only visible from a certain zoom level
map.addLayer({
"id": "layer-mypoints-label",
"type": "symbol",
"source": "mypoints",
"minzoom": 12, // Set zoom level to whatever suits your needs
"layout": {
"text-field": "{name}",
"text-anchor": "top",
"text-offset": [0,0.5]
}
});
This seems to work really well for my needs.
If you don't want multiple layers, there's an alternative work-around that I use.
Given your original code, you can use the text-size
property with zoom-dependent stops
:
map.addSource("mypoints", {
type: "geojson",
data: "mypoints.geojson",
});
map.addLayer({
"id": "layer-mypoints",
"type": "symbol",
"source": "mypoints",
"layout": {
"icon-image": "marker-15",
"text-field": "{name}",
"text-anchor": "top",
"text-size": {
"stops": [
[0, 0],
[3, 0],
[4, 10]
]
}
}
});
The value is interpolated between stops, so between zoom 0 and 3 the text-size
is interpolated between 0 and 0, resulting in... 0 (i.e. absent). From zoom 3 it gives the text the effect of enlarging until zoom 4 (I like the effect, but that's personal). From zoom 4 text-size
will just be constant at 10. If you don't want the "embiggening" effect between zoom 3 and 4, you can also specify a fractional zoom: just change 4 to 3.1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With