Create a Draggable Point ​
Allow users to drag a GeoJSON point on the map using mouse events.
Click and drag the point to move it
How It Works ​
- Add a GeoJSON
Pointsource and display it as acirclelayer - Listen for
mousedownon the layer to start dragging - On
mousemove, update the point position withsetData() - On
mouseup, end the drag and re-enable map panning
Key Pattern ​
javascript
let isDragging = false;
// Start drag when user clicks the point
map.on('mousedown', 'my-point', (e) => {
e.preventDefault();
isDragging = true;
map.dragPan.disable(); // prevent map from panning
map.getCanvas().style.cursor = 'grabbing';
});
// Move point while dragging
map.on('mousemove', (e) => {
if (!isDragging) return;
map.getSource('my-point').setData({
type: 'Feature',
geometry: { type: 'Point', coordinates: [e.lngLat.lng, e.lngLat.lat] },
properties: {}
});
});
// End drag
map.on('mouseup', () => {
isDragging = false;
map.dragPan.enable();
map.getCanvas().style.cursor = '';
});Complete Example ​
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
<script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
<style>#map { height: 500px; width: 100%; }</style>
</head>
<body>
<div id="map"></div>
<p id="info">Drag the point</p>
<script>
const map = new mapmetricsgl.Map({
container: 'map',
style: '<StyleFile_URL_with_Token>',
center: [0, 20],
zoom: 2
});
map.on('load', () => {
map.addSource('point', {
type: 'geojson',
data: { type: 'Feature', geometry: { type: 'Point', coordinates: [0, 20] }, properties: {} }
});
map.addLayer({
id: 'point',
type: 'circle',
source: 'point',
paint: { 'circle-radius': 10, 'circle-color': '#3b82f6', 'circle-stroke-width': 3, 'circle-stroke-color': '#fff' }
});
let dragging = false;
map.on('mousedown', 'point', (e) => {
e.preventDefault();
dragging = true;
map.dragPan.disable();
map.getCanvas().style.cursor = 'grabbing';
});
map.on('mousemove', (e) => {
if (!dragging) return;
map.getSource('point').setData({
type: 'Feature',
geometry: { type: 'Point', coordinates: [e.lngLat.lng, e.lngLat.lat] },
properties: {}
});
document.getElementById('info').textContent =
`Lng: ${e.lngLat.lng.toFixed(4)}, Lat: ${e.lngLat.lat.toFixed(4)}`;
});
map.on('mouseup', () => {
dragging = false;
map.dragPan.enable();
map.getCanvas().style.cursor = '';
});
});
</script>
</body>
</html>jsx
import React, { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
const DraggablePoint = () => {
const mapContainer = useRef(null);
const map = useRef(null);
const isDragging = useRef(false);
const [coords, setCoords] = React.useState([0, 20]);
useEffect(() => {
if (map.current) return;
map.current = new mapmetricsgl.Map({
container: mapContainer.current,
style: '<StyleFile_URL_with_Token>',
center: [0, 20],
zoom: 2
});
map.current.on('load', () => {
map.current.addSource('point', {
type: 'geojson',
data: { type: 'Feature', geometry: { type: 'Point', coordinates: [0, 20] }, properties: {} }
});
map.current.addLayer({
id: 'point',
type: 'circle',
source: 'point',
paint: { 'circle-radius': 10, 'circle-color': '#3b82f6', 'circle-stroke-width': 3, 'circle-stroke-color': '#fff' }
});
map.current.on('mousedown', 'point', (e) => {
e.preventDefault();
isDragging.current = true;
map.current.dragPan.disable();
map.current.getCanvas().style.cursor = 'grabbing';
});
map.current.on('mousemove', (e) => {
if (!isDragging.current) return;
const newCoords = [e.lngLat.lng, e.lngLat.lat];
map.current.getSource('point').setData({
type: 'Feature',
geometry: { type: 'Point', coordinates: newCoords },
properties: {}
});
setCoords(newCoords);
});
map.current.on('mouseup', () => {
isDragging.current = false;
map.current.dragPan.enable();
map.current.getCanvas().style.cursor = '';
});
});
return () => { map.current?.remove(); map.current = null; };
}, []);
return (
<div>
<div ref={mapContainer} style={{ height: '500px', width: '100%' }} />
<p>Position: [{coords[0].toFixed(4)}, {coords[1].toFixed(4)}]</p>
</div>
);
};
export default DraggablePoint;For more information, visit the MapMetrics GitHub repository.