I would like to know how could I use a custom marker with google maps drawing controls. I want to do that because I need to place a marker when a user clicks in the map and have it open a info window (when clicked) and have a few custom actions in there (buttons and such).
I'm using react and @react-google-maps/api for this, but that might be besides the point since it is just a wrapper around the Maps Javascript API provided by Google.
From the docs it is possible to provide google.maps.MarkerOptions
to the google.maps.drawing.DrawingManagerOptions
. Unfortunately there is no option there to provide a custom Marker
to be rendered.
I tried using the markercomplete()
call back exposed by the google.maps.drawing.DrawingManager
since it has the newly created Marker
as parameter, and then doing something like this:
const handleNewMarker = (marker) => {
marker.addListener('click', function() {
setActiveMarker(marker);
});
}
My map component would then be something like this:
<GoogleMap
zoom={18}
center={latLng}
>
{activeMarker && <CustomInfoWindow anchor={activeMarker} />}
<DrawingManager
options={{
markerOptions: {
clickable: true,
draggable: true,
},
}}
onMarkerComplete={handleNewMarker}
/>
</GoogleMap>
Although this worked, it is not at all viable for production, for some reason the InfoWindow
takes too much time to appear in the screen, that approach might be causing a memory leak and I don`t know why.
I might be missing something here, but on my research I didn't find a single soul trying to create a custom marker with the drawing tool, just custom markers by themselves which is relatively easy to do. My ideal case scenario, since I'm using React, would be to create a CustomMarker
component with a CustomInfoWindow
inside it, and just tell the drawing controls, "hey, take this marker and use it whenever a user tries to draw a new marker with your drawing tool".
Thank you.
Here is a screenshot of what I mean, that marker in the screen shot was placed there using the "new marker" drawing control, and I need the "new marker" drawing control to place a custom marker defined by me.
All you need to do is to set the icon
property in the MarkerOptions
, if I correctly understand your meaning of "custom marker". Below is an example using a SVG path for the icon.
This snippet is in full JS but the same should work with the React library.
var map;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.MARKER]
},
markerOptions: {
draggable: false,
icon: {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 0.6,
anchor: new google.maps.Point(0, 0),
strokeWeight: 0,
scale: 1
}
}
});
drawingManager.setMap(map);
}
#map {
height: 180px;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize&libraries=drawing" async defer></script>
Now if you need the marker to be clickable, have an Infowindow, etc. do you really need to use the drawing manager? Could you not simply listen for a map click event, and create a standard marker?
Or possibly, use both? (Create the marker with the drawing manager and convert it to a standard marker by the use of the markercomplete
event, which seems to be more or less what you are doing.)
If you need to create a "real" marker with an InfoWindow, you can do it in the markercomplete
event.
var map;
var infowindow;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
infowindow = new google.maps.InfoWindow();
var drawingManager = new google.maps.drawing.DrawingManager({
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [google.maps.drawing.OverlayType.MARKER]
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'markercomplete', function(marker) {
// Remove overlay from map
marker.setMap(null); // Optional, but this will remove the drawn marker
drawingManager.setDrawingMode(null); // Optional, but this will "disable" the drawing tools
// Create the "real" marker
createMarker(marker.getPosition());
});
}
function createMarker(position) {
var marker = new google.maps.Marker({
position: position,
map: map,
title: 'Custom marker',
icon: {
path: "M-20,0a20,20 0 1,0 40,0a20,20 0 1,0 -40,0",
fillColor: '#FF0000',
fillOpacity: 0.6,
anchor: new google.maps.Point(0, 0),
strokeWeight: 0,
scale: 1
}
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent('This is the content');
infowindow.open(map, this);
});
}
#map {
height: 180px;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize&libraries=drawing" async defer></script>