Mapbox GL JS unclustered point icon-image - mapbox-gl-js

I'm trying to display a clustered map with Mapbox GL JS.
Using this example from the documentation: https://www.mapbox.com/mapbox-gl-js/example/cluster/, I'd like to show a marker icon instead of a circle for unclustered points.
I modified the last addLayer call like this :
map.addLayer({
id: "unclustered-point",
type: "symbol",
source: "companies",
filter: ["!has", "point_count"],
layout: {
"icon-image": "marker-15", // THIS SHOULD BE A MARKER
"icon-size": 5 // ZOOMED FOR DEMO
},
});
Here is the result I got :
Why can't I get access to Maki Icons like it is suggested here : Mapbox GL js available icons

Without a link to your (non) working example, it's hard to diagnose fully, but one possibility is that that icon is not included in your style.
You could try starting from a style that definitely includes them, like these: https://github.com/mapbox/mapbox-gl-styles

Related

How can I use a custom font in Mapbox GL JS?

I am using Mapbox GL JS (v2.8.0) to programmatically add a Style layer to my map, and I am trying to use a set of fonts that I have uploaded to my map via the Mapbox Studio.
I currently have this inside my code for my Style layer:
const layer = {
id: this.getLayerId(),
type: 'symbol',
layout: {
'text-field': ['get', 'name'],
'text-font': [
"Chakra Petch Italic", // My custom font inside Mapbox
"Arial Unicode MS Regular" // Fallback font
]
},
paint: {
'text-color': '#ffffff',
}
}
However when it comes to rendering my map, I am getting 404 errors in relation to trying to fetch my font.
It is trying to fetch the font from the following url:
https://api.mapbox.com/fonts/v1/mapbox/Chakra%20Petch%20Italic,Arial%20Unicode%20MS%20Regular/0-255.pbf?access_token={access_token}
And I believe this issue here is that instead of /mapbox/ it should be /{username}/ as when I go to the following url in the browser:
https://api.mapbox.com/fonts/v1/{username}/Chakra%20Petch%20Italic,Arial%20Unicode%20MS%20Regular/0-255.pbf?access_token={access_token}
I correctly get the .pbf data.
How am I able to specify that it should look under my username, rather than the public mapbox user, in my style layer json?
Additionally, as a test, if I create a simple layer inside Mapbox Studio - and set a label to use the custom font, in the Network tab in devtools I can see it fetching the font using the username url above. And unfortunately the "code inspector" in the Studio for this label shows the same two string array as I have inside my code.
You need to set the glyphs property of your style:
}, glyphs: 'mapbox://fonts/yourusername/{fontstack}/{range}.pbf'
}
More info: https://docs.mapbox.com/mapbox-gl-js/style-spec/glyphs/

Markers in the same position don't work properly with Vue3 + Leaflet Markercluster

The problem is that the leaflet map inside the vue3 App loads perfectly and looks great. Also, when you click on a location with two icons in the same position, they open perfectly, but when you click on the same place again, the icons disappear and the "spider" remains visible (see picture).
spider remains
The methods in the Vue3 App are:
methods:{
setupMarkers(){
this.markers.clearLayers();
this.cursesData.forEach(cursa =>this.ficaMarkers(cursa));
this.map.addLayer(this.markers);
},
setupLeafletMap(){
this.map=L.map("mapContainer").setView(this.center,6);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{
attribution:'OpenStreetMap',
}).addTo(this.map);
this.markers= L.markerClusterGroup({
//spiderfyOnMaxZoom: true,
});
},
ficaMarkers(cursa){
this.markers.addLayer(L.marker([cursa.coordenades[0],cursa.coordenades[1]],{title:cursa.nom})
.bindPopup(cursa.distancies)
)
},
},
If someone could help me, I would be very grateful.
Thanks.
It is a similar issue as in Uncaught TypeError: this._map is null (Vue.js 3, Leaflet) :
What seems to be the culprit is the proxying of this.map by Vue, which seems to interfere with Leaflet events (un)binding. It looks like Vue 3 now automatically performs deep proxying, whereas Vue 2 was shallow.
In your case, the same thing happens for this.markers (which is the Leaflet MarkerClusterGroup).
A solution consists in "unwrapping" / un-proxying the map and the mcg whenever you use them, e.g. with Vue3's toRaw:
toRaw(this.map).addLayer(toRaw(this.markers));
Then we retrieve the normal MCG behaviour, i.e. if you click on the cluster while it is already spiderfied, nothing happens (whereas initially the Markers were collapsing, but the spider legs were remaining indefinitely)
Fixed CodeSandbox: https://codesandbox.io/s/markers-hide-spiders-stay-forked-l2ruqh?file=/src/App.vue

What I need to put "url" in mapbox addSource

This is my first time using mapbox and I can't figure out how to addSource when map load.
Below is the sample code.
I uploaded 'KML' file for tilesets and I want to use this tileset for source, but I don't know how to write 'url' part.
I also want to know what is 'source-layer'. What should I write in the 'source-layer?
I am sorry I know this is very basic question, but I really need to know.
Please help me.
Thanks.
map.on('load', function() {
// Add the source to query. In this example we're using
// county polygons uploaded as vector tiles
map.addSource('counties', {
"type": "vector",
"url": "mapbox://mapbox.82pkq93d" <<---here
});
map.addLayer({
"id": "counties",
"type": "fill",
"source": "counties",
"source-layer": "original", <<---source layer
"paint": {
"fill-outline-color": "rgba(0,0,0,0.1)",
"fill-color": "rgba(0,0,0,0.1)"
}
}, 'place-city-sm'); // Place polygon under these labels.
});
EDIT:
Your tile url should also be fine like this:
mapbox://{}
It is a bit tricky to find in the documentation: When uploading KML you are creating tileset for which you should get a map ID. With the map ID you can either request separate tiles using a tile url like this:
/v4/{map_id}/{zoom}/{x}/{y}{#2x}.{format}
You can use the tile url when adding a source
map.addSource({
type: 'vector',
tiles: ['https://api.mapbox.com/v4/{map_id}/{zoom}/{x}/{y}.mvt']
});
Or you can request a TileJSON metadata object and use this to add the source:
map.addSource({
type: 'vector',
url: 'https://api.mapbox.com/v4/{map_id}.json' // <-- tileJSON url
});
For your source layer question: Vector tiles include multiple "layers" of data/geometry, when adding a map layer you need to define which source-layer the map layer refers to. E.g. you can have a single vector tile set consisting of line strings and points (two different source-layers), but your map layer should only render on of them. You can either check to tile JSON to see what source-layers are included in your tile set or create a map style in mapbox studio, using your uploaded tile set as a source.

Mapbox - Update data-driven styling in session

There are several tutorials on data-driven styling on Mapbox's site, but none of them address how to update an existing data-driven style (created in Mapbox Studio) in-session. For example, say I want to create a choropleth of US states, colored by area. User then selects 'color by population' and the color of the states update accordingly.
I've found some resources that would allow one to achieve this by adding the geojson of all the states and then doing map.addLayer, however the geojson I'm working with (census tracts) is too massive to add to the front-end, so I needed to change the data-driven styling of an existing layer (or find a similar work-around). The data has to be a persisted tileset from mapbox studio, with user updating the data coloration based on geojson properties.
Any ideas or examples would be much appreciated.
Updating data-driven styling at run-time is straightforward. You simply call map.setPaintProperty.
I usually implement this with one function that generates the property value. Something like this:
function fillColorByPopulation(min, max) {
return {
property: 'pop',
stops: [
[min, 'red'],
[max, 'blue']
],
type: 'exponential'
}
}
function updateStyle(prop) {
if (prop === 'population') {
map.setPaintStyle('regions', 'fill-color', fillColorByPopulation(data.minpopulation, data.maxpopulation));
} else {
map.setPaintStyle('regions', 'fill-color', 'transparent');
}
}
I generally don't create any data-driven styles within Mapbox Studio. It's simpler to create them all in Javascript.

How to use a remote wmts and generate its tiles in mapbox

according to How to implement a tile source to mapbox-gl i have an issue on a raster tile source in mapbox gl JS, which probably seems to fit to your declaration that mapbox only supports x/y/z and not lat/lon tile coordinates. I've trouble on this with the following tile source (WMTS): https://www.wmts.nrw.de/geobasis/wmts_nw_dop20/1.0.0/WMTSCapabilities.xml.
I want to include this wmts as source and add as layer like this:
map.on("load", function() {
map.addSource("wmts-layer", {
"type": "raster",
"tiles":['https://www.wmts.nrw.de/geobasis/wmts_nw_dop20/tiles/nw_dop20/EPSG_3857_16/{z}/{x}/{y}.jpeg'],
"tileSize": 256
});
map.addLayer({
"id": "wmts-layer",
"source": "wmts-layer",
"type": "raster",
"visibility": "visible",
"source-layer": "nw_dop20",
});
});
it does not work at all, Tiles get loaded but are empty images!
Can anyone point out whats the problem here?
cheers phil
You seem to be using Mapbox-GL-JS correctly (although you don't need source-layer). For whatever reason, that service is returinng blank tiles for example.
Thank you for investigation Steve,
this is really weird and for some reason the service seems to be unusable in mapbox gl as it serves different coordinates on each zoomlevel than it is specified in the tilescheme of mapbox (tms or xyz)!
see:
https://github.com/mapbox/mapbox-gl-js/issues/6089