Mapbox GL JS is a powerful tool for creating interactive maps. In this tutorial, I’ll show you how to create a custom toolbox for map drawing with different styles of draw points - something that isn’t immediately obvious from the official documentation.
The Challenge#
I needed to:
- Select a drawing tool from a toolbox
- Add markers to multiple locations
- Switch to another tool and repeat with different marker styles
After searching through documentation and asking on StackOverflow, I developed my own solution.
Step 1: Loading Custom Images#
First, you need to add your custom marker images to the map. Add this code when the map loads:
map.on('load', function() {
// Load trough icon
map.loadImage('{{asset("/images/icons/[email protected]")}}', function(error, image) {
if (error) throw error;
map.addImage('trought', image); // giving a name to image
});
// Load windmill icon
map.loadImage('{{asset("/images/icons/[email protected]")}}', function(error, image) {
if (error) throw error;
map.addImage('windmill', image);
});
});
Step 2: Handling Tool Selection#
Set up event handlers for your toolbox selections:
$(".dropdown-menu a").on('click', function(event) {
// Prevent event bubbling
event.stopPropagation();
event.stopImmediatePropagation();
// Get selected tool name
var menu = event.target.innerHTML;
menu = menu.replace(/\s/g, '').toLowerCase();
switch(menu) {
case 'trough':
draw.changeMode('draw_point'); // Set draw mode
selected_mode = 'draw_point'; // Store mode globally
selectedTool = "trought"; // Store tool type
break;
case 'windmill':
draw.changeMode('draw_point');
selected_mode = 'draw_point';
selectedTool = "windmill";
break;
default:
}
// Maintain draw mode on map interactions
map.on('draw.modechange', e => {
draw.changeMode(selected_mode);
});
});
Important Variables:#
selected_mode
: Stores the current drawing modeselectedTool
: Stores the currently selected marker type
Step 3: Adding Markers to the Map#
Handle map clicks to add markers:
map.on('click', function (e) {
// Create unique ID for each marker
var imageId = e.lngLat.lng + e.lngLat.lat + "";
// Add new layer with custom marker
map.addLayer({
"id": imageId,
"type": "symbol",
"source": {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [e.lngLat.lng, e.lngLat.lat]
}
}]
}
},
"layout": {
"icon-image": selectedTool,
"icon-size": 1
}
});
});
Key Points to Remember#
- Each marker needs a unique ID to prevent conflicts
- The
icon-image
property must match the name given inmap.addImage()
- Coordinates are specified in [longitude, latitude] format
- The
draw.modechange
event handler is crucial for maintaining the selected draw mode
Troubleshooting#
If you encounter issues:
- Verify that your image paths are correct
- Check that image names match between
addImage()
andicon-image
- Ensure unique IDs for each marker layer
- Confirm that your coordinates are in the correct format
Next Steps#
You can enhance this implementation by:
- Adding marker removal functionality
- Implementing marker drag-and-drop
- Adding custom popup information
- Storing marker data for later use
Feel free to ask questions in the comments below!