Add custom vector icons
When you upload custom vector icons into your map style, you can dynamically define their color using the Mapbox Style Specification. For that you need to upload the SVG icon image in Mapbox Studio with defined dynamic color parameters. The SVG used in this example is below:
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:m="https://www.mapbox.com">
<m:metadata>
<m:parameters>
<m:parameter m:type="color" m:name="flag_color" m:value="#000000"/>
</m:parameters>
</m:metadata>
<path d="M10.1418 27.3334L10.1417 4.12779C10.401 4.00292 10.5826 3.73252 10.5826 3.41689V1.78416C10.5826 1.35152 10.2441 1 9.82689 1H8.56725C8.14958 1 7.81108 1.35152 7.81108 1.78416V3.41689C7.81108 3.73301 7.99218 4.00292 8.25198 4.12779L8.25206 27.3334C6.01343 27.5064 4 28.2935 4 29.6485C4 31.1927 6.61409 32 9.19692 32C11.7793 32 14.3938 31.1922 14.3938 29.6485C14.3938 28.2935 12.3799 27.505 10.1418 27.3334ZM9.19692 30.8235C6.55768 30.8235 5.13401 29.9897 5.13401 29.6475C5.13401 29.3496 6.22013 28.6751 8.25206 28.5094V29.6475H10.1418V28.5094C12.1742 28.676 13.2598 29.3496 13.2598 29.6475C13.2598 29.9897 11.8362 30.8235 9.19692 30.8235ZM28 13.9994C28 14.0205 27.9962 14.0407 27.9938 14.0603C28.0038 14.1473 27.9981 14.2363 27.9678 14.3238C27.9483 14.3824 27.4638 15.7737 25.9633 16.2801C25.6073 16.4005 25.2275 16.461 24.8269 16.461C23.5403 16.461 22.0261 15.843 20.3075 14.6134C15.3263 11.0515 12.2945 14.3814 12.1674 14.5244C12.0096 14.7034 11.7612 14.7639 11.5431 14.6763C11.3255 14.5888 11.1809 14.3725 11.1809 14.1296V3.74333C11.1809 3.73448 11.1828 3.72613 11.1832 3.71678C11.1823 3.69663 11.188 3.67795 11.1889 3.65779C11.1908 3.64402 11.1918 3.63026 11.1946 3.61747C11.207 3.49948 11.2439 3.38296 11.3264 3.28808C11.3639 3.24481 15.1281 -0.968021 20.9513 3.19762C22.8718 4.57076 24.4828 5.09484 25.612 4.71382C26.5692 4.39033 26.8949 3.49604 26.8973 3.4867C26.9888 3.21679 27.2538 3.05258 27.5278 3.10175C27.8004 3.14944 27.9995 3.39476 27.9995 3.68188L28 13.9994Z" fill="#000000"/>
</svg>
To make your SVG available for Mapbox GL JS to interact with it, place all required metadata attributes inside the m:metadata element. All dynamic parameters for vector icons should be stored in the m:parameters element. For colors, use m:parameter elements with m:type="color", and place them inside the m:parameters element. You cannot use multiple m:name attributes for the same color value, as this may cause conflicts.
Finally, you must add the m: XML namespace to the SVG element: xmlns:m="https://www.mapbox.com" as seen on line #1 in the above code snippet.
The SVG file above was uploaded to Mapbox Studio with the name flag.
Now that the SVG icon is uploaded to the map style, the color can be customized using the symbol layer's icon-image property. The second parameter of the icon-image property is an object that can contain a params dictionary, where you can specify colors. The color values can be specified as a static value or as an expression. In the example snippet below, a get expression is used to change the icon's color based on the feature property flagColor.
For this example to work, your SVG's must live inside the map style. When SVG's are uploaded to the Mapbox Studio style editor, they become part of the map style and can be referenced via the style's sprite file. This example will not work locally hosted SVG files.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Add custom vector icons</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
// TO MAKE THE MAP APPEAR YOU MUST
// ADD YOUR ACCESS TOKEN FROM
// https://account.mapbox.com
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
const geojson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
flagColor: 'red'
},
geometry: {
type: 'Point',
coordinates: [24.68727, 60.185755]
}
},
{
type: 'Feature',
properties: {
flagColor: 'yellow'
},
geometry: {
type: 'Point',
coordinates: [24.68827, 60.186255]
}
},
{
type: 'Feature',
properties: {
flagColor: '#800080'
},
geometry: {
type: 'Point',
coordinates: [24.68927, 60.186055]
}
}
]
};
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox-map-design/cm4r19bcm00ao01qvhp3jc2gi',
center: [24.68727, 60.185755],
zoom: 16
});
map.once('load', () => {
map.addSource('points', {
type: 'geojson',
data: geojson
});
map.addLayer({
id: 'points',
type: 'symbol',
source: 'points',
layout: {
'icon-image': [
'image',
'flag',
{ params: { flag_color: ['get', 'flagColor'] } }
]
}
});
});
</script>
</body>
</html>
YOUR_MAPBOX_ACCESS_TOKEN with an access token from your Mapbox account.import React, { useEffect, useRef } from 'react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
const MapboxExample = () => {
const mapContainerRef = useRef();
const mapRef = useRef();
useEffect(() => {
// TO MAKE THE MAP APPEAR YOU MUST
// ADD YOUR ACCESS TOKEN FROM
// https://account.mapbox.com
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
mapRef.current = new mapboxgl.Map({
preserveDrawingBuffer: true,
container: mapContainerRef.current,
style: 'mapbox://styles/mapbox-map-design/cm4r19bcm00ao01qvhp3jc2gi',
center: [24.68727, 60.185755],
zoom: 16
});
const geojson = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
flagColor: 'red'
},
geometry: {
type: 'Point',
coordinates: [24.68727, 60.185755]
}
},
{
type: 'Feature',
properties: {
flagColor: 'yellow'
},
geometry: {
type: 'Point',
coordinates: [24.68827, 60.186255]
}
},
{
type: 'Feature',
properties: {
flagColor: '#800080'
},
geometry: {
type: 'Point',
coordinates: [24.68927, 60.186055]
}
}
]
};
mapRef.current.once('load', () => {
mapRef.current.addSource('points', {
type: 'geojson',
data: geojson
});
mapRef.current.addLayer({
id: 'points',
type: 'symbol',
source: 'points',
layout: {
'icon-image': [
'image',
'flag',
{ params: { flag_color: ['get', 'flagColor'] } }
]
}
});
});
}, []);
return <div ref={mapContainerRef} id="map" style={{ height: '100%' }} />;
};
export default MapboxExample;
YOUR_MAPBOX_ACCESS_TOKEN with an access token from your Mapbox account.