Having custom icon image per feature. Icons may be different depending their data.
A the moment, we need call addImage in order to add custom icon-image, but it's not appropriate if each feature have differents image (and if these images are generated based on feature data).
data-driven _generation_ of icon-image would be ideal, but we can't have js callback inside styling as far I know.
The source server could calculate the base64 image for each feature into a icon property, and then we just have to set something like:
"layout": {
"icon-image (or another property name)": "{icon}",
"icon-size": 0.25
}
I know that html markers can do this, but they're not as smooth as symbol layers.
I really need this feature, the html markers is not supported with clustering and I have a shit load of icons to load and the "addImage" is limited by the "AtlasSprite" size.
I know this has been brought up again and again, but I couldn't find a proper solution to support the way we want our markers to be shown and ability to form cluster, drag, drop, filter etc. (Marker is a way, but not sure how you do clustering and drag, drop with them).
Design wise, our markers consists of two layers, background: where users select color and foreground where the user selects the icon. Colors and Icons are dynamically selected.
With Mapbox.js, doing this was easy, L.mapbox.featureLayer
().addLayer(L.Marker(…)), this would support clustering as well.
But with GL-JS, Marker doesn't return a layer(?), where supporting clustering is a tricky (looping GeoJSON back and forth).
Markers we want to support:

Is it possible to create markers like above with Symbol?
Does this trick help you? I find this approach a bit more flexible than using external URLs because external requests are not needed. Not as elegant as using base64 from icon-image directly:
this.map.loadImage(' INSERT YOUR BASE64 HERE', (error, image) => {
console.log(error);
if (error) {
throw error;
}
this.map.addImage('cat', image);
this.map.addLayer({
'id': 'points',
'type': 'symbol',
'source': {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [27, 61.7]
}
}]
}
},
'layout': {
'icon-image': 'cat',
'icon-size': 0.25
}
});
});
In your example your base64 image is not generated based on feature properties.
It could be, but it means one layer per symbol (not sure if it's better than html markers at this point), and it's still probably limited by the AtlasSprite size issue.
My use case is using d3.js in order to generate a custom icon based on a feature props.
The new expression system may solve this issue (but definitly not sure if it's good enough).
For now, I switch from/to layer/htmlmarker depending on the number of symbol currently visible.
This is also an issue for a project I am working.
We consume a GeoJSON that is a feature collection of aircraft locations, heading, etc. Each feature includes a base64 encoded icon for that type of aircraft. Ideally we should be able to to reference the properties that contain the icons and heading and have it render.
Using the loadImage method is very clunky and not appropriate for our use-case.
I'm not using mapbox-gl currently, but this seems to solve this issue: https://github.com/mapbox/mapbox-gl-js/pull/7987 🎉
Most helpful comment
Does this trick help you? I find this approach a bit more flexible than using external URLs because external requests are not needed. Not as elegant as using base64 from icon-image directly: