π Dragging & Editing
Once you have customized your map , markers , shapes , and info windows , you can let your users to interact with them.
Any artifact can be made moveable (or draggable) using the draggable: true property. This property can also be toggled on-demand via .setDraggable(true) or .setOptions({ draggable: true }).
Once the user stops dragging the marker, the dragend event is fired:
const marker = new google.maps.Marker({
...,
draggable: true,
});
marker.addListener('dragend', () => {
console.info('New position: ', marker.getPosition().toJSON());
}); If the marker is connected with an InfoWindow , the info window will be dragged along with it:
const infowindow = new google.maps.InfoWindow({ ... });
marker.addListener('click', () => {
infowindow.open({ map, anchor: marker });
}); If you have a Circle drawn βaroundβ a marker:
const circle = new google.maps.Circle({
map,
center: position,
radius: 500,
draggable: true,
}); you can sync their positions using the .bindTo utility :
circle.bindTo("center", marker, "position"); This statement follows the bindTo(key, target, targetKey?) ****syntax so it can be understood as βbind the circle's center to the marker's position.β
The neat thing about this is that it works both ways β when you drag the marker, the circle moves along with it and if you drag the circle, the marker repositions as well.
Circles, polygons, and other shapes all expose their respective dragend events. However, if the positions are synced like in the example above, the circle's dragend event won't fireβ¦
You can listen to its center_changed event though:
circle.addListener('center_changed', () => { ... }); Now, in contrast to the dragend event, this listener will fire many times over until the dragging is truly finished. In situations like these, it's customary to debounce the callback to ensure that only one notification is made for an event that fires multiple times:
debounce.ts// https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_debounce export function debounce(func, wait, immediate = false) { var timeout; return function () { var context = this, args = arguments; clearTimeout(timeout); timeout = setTimeout(function () { timeout = null; if (!immediate) func.apply(context, args); }, wait); if (immediate && !timeout) func.apply(context, args); }; }
Using a lodash/underscore.js debounce alternative :