MapSnippets logoMapSnippets logo

Drawing Tools with MapTiler SDK

MapTiler SDK

Draw polygons interactively by clicking on a MapTiler SDK map, collecting vertices into a GeoJSON source.

progress_activityLoading map...
maptilersdk.config.apiKey = 'YOUR_MAPTILER_KEY';
const map = new maptilersdk.Map({
  container: 'map',
  style: maptilersdk.MapStyle.STREETS,
  center: [14.42, 50.08],
  zoom: 13
});
const coords = [];
const geojson = { type: 'Feature', geometry: { type: 'Polygon', coordinates: [[]] } };
function clickHandler(e) {
  coords.push([e.lngLat.lng, e.lngLat.lat]);
  var ring = coords.concat([coords[0]]);
  geojson.geometry.coordinates = [ring];
  map.getSource('draw').setData(JSON.parse(JSON.stringify(geojson)));
  map.getSource('vertices').setData({ type: 'FeatureCollection', features: coords.map(function(c) { return { type: 'Feature', geometry: { type: 'Point', coordinates: c } }; }) });
}
map.on('load', function() {
  map.addSource('draw', { type: 'geojson', data: geojson });
  map.addLayer({ id: 'draw-fill', type: 'fill', source: 'draw', paint: { 'fill-color': '#9C27B0', 'fill-opacity': 0.2 } });
  map.addLayer({ id: 'draw-line', type: 'line', source: 'draw', paint: { 'line-color': '#9C27B0', 'line-width': 2 } });
  map.addSource('vertices', { type: 'geojson', data: { type: 'FeatureCollection', features: [] } });
  map.addLayer({ id: 'draw-points', type: 'circle', source: 'vertices', paint: { 'circle-radius': 5, 'circle-color': '#fff', 'circle-stroke-width': 2, 'circle-stroke-color': '#9C27B0' } });
  map.on('click', clickHandler);
});
document.getElementById('finish-btn').addEventListener('click', function() {
  if (coords.length < 3) return;
  map.off('click', clickHandler);
  map.getCanvas().style.cursor = '';
});
document.getElementById('clear-btn').addEventListener('click', function() {
  coords.length = 0;
  geojson.geometry.coordinates = [[]];
  map.getSource('draw').setData(JSON.parse(JSON.stringify(geojson)));
  map.getSource('vertices').setData({ type: 'FeatureCollection', features: [] });
  map.off('click', clickHandler);
  map.on('click', clickHandler);
  map.getCanvas().style.cursor = 'crosshair';
});

How it works

This example implements polygon drawing without external plugins. Each map click adds a vertex to a coordinate array. The polygon is rendered by closing the ring (appending the first coordinate) and updating the GeoJSON source.

Three layers visualize the drawing: a fill layer for the polygon interior, a line layer for the border, and a circle layer for individual vertices. All three update in real time as the user clicks.

The “Finish” button removes the click listener to finalize the polygon. The “Clear” button resets the coordinate array, clears the GeoJSON sources, and re-attaches the click listener so the user can draw again.

Key APIs

API Description Docs
source.setData() Update GeoJSON source data docs.maptiler.com/sdk-js/api/
map.on('click') Listen for map clicks docs.maptiler.com/sdk-js/api/
map.off('click') Remove click listener docs.maptiler.com/sdk-js/api/

FAQ

How do I calculate the polygon area?

Use a library like Turf.js: turf.area(polygon) returns the area in square meters.

Can I edit vertices after drawing?

This basic implementation does not support vertex editing. For full draw/edit functionality, consider implementing drag handlers on vertex points.

How do I export the drawn polygon?

Read the GeoJSON object directly: it is already a valid GeoJSON Feature that can be sent to an API or saved as a file.

Common mistakes

  • Not closing the polygon ring: append the first coordinate to the end of the array
  • Forgetting to deep-copy the GeoJSON before setData(): the SDK may cache references
  • Allowing polygon creation with fewer than 3 points: 2 points or fewer cannot form a valid polygon
auto_awesome

Build maps using MapTiler SDK with AI

Generate code like this drawing tools with maptiler sdk example using the MapTiler SDK skill in your IDE.