Skip to main content

Create a draggable point

In this example, a user can drag a point to a new location on the map, and a map overlay displays the new point coordinates.

The example stores the point coordinates in a variable with a GeoJSON value, then uses MapTouchEvents to prevent the default map drag behavior and get the updated coordinates. Then it uses setData to enable changes to the variable and addSource to use the variable as the value for the data property.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Create a draggable point</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v3.3.0/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<style>
.coordinates {
background: rgba(0, 0, 0, 0.5);
color: #fff;
position: absolute;
bottom: 40px;
left: 10px;
padding: 5px 10px;
margin: 0;
font-size: 11px;
line-height: 18px;
border-radius: 3px;
display: none;
}
</style>

<div id="map"></div>
<pre id="coordinates" class="coordinates"></pre>

<script>
// TO MAKE THE MAP APPEAR YOU MUST
// ADD YOUR ACCESS TOKEN FROM
// https://account.mapbox.com
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
const coordinates = document.getElementById('coordinates');
const map = new mapboxgl.Map({
container: 'map',
// Choose from Mapbox's core styles, or make your own style with Mapbox Studio
style: 'mapbox://styles/mapbox/streets-v12',
center: [0, 0],
zoom: 2
});

const canvas = map.getCanvasContainer();

const geojson = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [0, 0]
}
}
]
};

function onMove(e) {
const coords = e.lngLat;

// Set a UI indicator for dragging.
canvas.style.cursor = 'grabbing';

// Update the Point feature in `geojson` coordinates
// and call setData to the source layer `point` on it.
geojson.features[0].geometry.coordinates = [coords.lng, coords.lat];
map.getSource('point').setData(geojson);
}

function onUp(e) {
const coords = e.lngLat;

// Print the coordinates of where the point had
// finished being dragged to on the map.
coordinates.style.display = 'block';
coordinates.innerHTML = `Longitude: ${coords.lng}<br />Latitude: ${coords.lat}`;
canvas.style.cursor = '';

// Unbind mouse/touch events
map.off('mousemove', onMove);
map.off('touchmove', onMove);
}

map.on('load', () => {
// Add a single point to the map.
map.addSource('point', {
'type': 'geojson',
'data': geojson
});

map.addLayer({
'id': 'point',
'type': 'circle',
'source': 'point',
'paint': {
'circle-radius': 10,
'circle-color': '#F84C4C' // red color
}
});

// When the cursor enters a feature in
// the point layer, prepare for dragging.
map.on('mouseenter', 'point', () => {
map.setPaintProperty('point', 'circle-color', '#3bb2d0');
canvas.style.cursor = 'move';
});

map.on('mouseleave', 'point', () => {
map.setPaintProperty('point', 'circle-color', '#3887be');
canvas.style.cursor = '';
});

map.on('mousedown', 'point', (e) => {
// Prevent the default map drag behavior.
e.preventDefault();

canvas.style.cursor = 'grab';

map.on('mousemove', onMove);
map.once('mouseup', onUp);
});

map.on('touchstart', 'point', (e) => {
if (e.points.length !== 1) return;

// Prevent the default map drag behavior.
e.preventDefault();

map.on('touchmove', onMove);
map.once('touchend', onUp);
});
});
</script>

</body>
</html>
Was this example helpful?