I have a Google Maps application that displays some markers with custom labels. I want to trigger the marker click listener when the user clicks on the label, not only on the marker icon. However, I can't find a way to do that with the Google Maps API. Is there a way to achieve this functionality?
Here is the code I use to create the markers and the labels:
// Map initialization
function initMap(mapId, centerLatitude, centerLongitude, mapZoomLevel) {
// Generate and set google maps
mapCenter = { lat: centerLatitude, lng: centerLongitude };
mapZoom = mapZoomLevel;
map = new google.maps.Map(document.getElementById(mapId), {
center: mapCenter,
...MAP_OPTIONS, // Spread '...' constant map options
zoom: mapZoom,
});
}
// The method i use to generate all the markers starting from a json
async function loadData(serializedData) {
// Convert serialized data to a JavaScript object
data = JSON.parse(serializedData);
// Iterate on each object in the dataset using map
markers = await Promise.all(
data.map(async (object) => {
// Wait for the promise returned by createMarker and return it
return await createMarker(object);
})
);
initClusterer();
}
// How i create the marker
async function createMarker(object) {
// Create marker
const marker = new google.maps.Marker({
position: object.Position,
map,
icon: getIcon(object.Direction),
label: generateMarkerLabel(object.Name)
});
// Add listener
marker.addListener("click", function () {
focusOn(marker);
ShowMarkerRouteViewBtn.click();
});
// Returns the marker created
return marker;
}
// How i create the label
function generateMarkerLabel(markerName) {
return {
text: markerName,
fontSize: "10px",
className: "marker-label"
};
}
// How i create the icon
function generateMarkerIcon(direction) {
// Generate the icon svg
let iconSvg = `
<svg xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 36 36" xml:space="preserve" >
...[the svg paths]...
</svg>
`;
// Generate and return the marker icon literal object
return {
url: "data:image/svg+xml;charset=UTF-8," + encodeURIComponent(iconSvg),
scaledSize: new google.maps.Size(36,36),
anchor: new google.maps.Point(18, 18)
};
}
// How i init the clusterer
function initClusterer() {
clusterer = new markerClusterer.MarkerClusterer({
markers: markers,
map: map,
});
}
The problem is that the label is not part of the marker, but a separate overlay on the map. So, clicking on the label does not trigger the marker click listener. How can I make the label clickable and trigger the marker click listener? Any help would be appreciated. Thanks.
Edit:
The MarkerLabel
interface you're using places the labels onto a pane that cannot accept pointer events (e.g. clicks).
Quick hack: increase the marker icon SVG height so it covers the label. That way, the click on the transparent top part of the SVG will act as an "artificial click" on the label itself.
Another option: check out the js-markerwithlabel
package.
Otherwise, have a look at Advanced Markers. That's the recommended way to implement markers (+ labels) in 2023 and beyond. Here's a disambiguation.
Original answer:
Your generateMarkerLabel
function returns a JavaScript object and it's not immediately clear how you attach it to the DOM.
But once you've got the .marker-label
element, you can bind a click
event to it and delegate the marker's click
event from where:
// ideally attached shortly after the label element has been attached to the DOM
const mLabel = document.querySelector('.marker-label');
mLabel.addEventListener('click', (evt => {
google.maps.event.trigger(marker, 'click');
}));