Reputation: 124
We are building a simple React application that uses google maps to display various events on the map. We are using this repo: https://github.com/tomchentw/react-google-maps
This is the scenario that we are tying to create: Have a bunch of markers shown on the map and have a custom OverlayView shown at all times above the markers.
This is the problem: We are also using google MarkerClusterer. While the markers get clustered when we zoom out the custom Overlays are still shown.
What we need: Have the custom Overlays hide when the markers are clustered.
Here is the code showing the rendering of our google maps. See the <OverlayView>
component. It does not display anything in this example.
Is there a way using react to detect when the markers are no longer visible on the map and then set the visibility of the custom Overlay to hidden?
Thank you.
return ( < div >
< GoogleMapLoader containerElement = { < div {...this.props
}
style = {
{
height: "70vh"
}
}
/>}
googleMapElement={
<GoogleMap
containerProps={{...this.props}}
ref="map"
onBoundsChanged={this.handleBoundsChanged}
defaultZoom={12}
center={
center ? center: userPosition
}
>{contents}
<MarkerClusterer
averageCenter={true}
enableRetinaIcons={true}
gridSize={20}>
{this.data.Missions.map((marker, index) => {
const position = marker.startLocationGeo ? {lat:marker.startLocationGeo.latitude, lng: marker.startLocationGeo.longitude} : null;
const ref = `marker_${index}`;
if(position){
let icon = '';
switch (marker.type) {
case "hit":
icon = "https:/ / www.dropbox.com / s / likbnwqx8y5kywv / shooting.png ? dl = 1 ";
break;
case "
transport ":
icon = "
https: //www.dropbox.com/s/r22dfeh8lutpwv1/fourbyfour.png?dl=1";
break;
default: icon = "https://www.dropbox.com/s/dfjpx65j5v3wlih/pirates.png?dl=1";
break;
}
return ( < Marker key = {
ref
}
ref = {
ref
}
icon = {
icon
}
position = {
position
}
title = {
marker.title
}
onClick = {
this.handleMarkerClick.bind(this, marker)
}
onShapeChanged = {
this.testFunction.bind(this, marker)
} >
{ < OverlayView > THIS COMPONENT SHOULD NOT BE VISIBLE WHEN MARKERS ARE CLUSTERED < /OverlayView>}
{<InfoWindow key={`infoWindow_${index}`} position={position} content={marker.value} ref={`infoWindow_${index}`}/ >
} {
this.state.openedMissions.indexOf(marker.id.objectId) > -1 ? this.renderInfoWindow(ref, marker) : null
} < /Marker>
);
}
})}
</MarkerClusterer >
< SearchBox bounds = {
this.state.bounds
}
controlPosition = {
google.maps.ControlPosition.TOP_LEFT
}
onPlacesChanged = {
this.handlePlacesChanged
}
ref = "searchBox"
placeholder = "Search address"
style = {
inputStyle
}
/>
</GoogleMap >
}
/>
</div >
)
Upvotes: 3
Views: 6799
Reputation: 139
I've faced with the same problem and want to post my answer even after almost 1,5 years. I hope that my experience will help someone!
So, what did I do: 1) I created react ccustom marker react component
showMarkerContent() {
this.setState({
isShown: true
});
}
hideMarkerContent() {
this.setState({
isShown: false
});
}
render() {
return (
<Marker
key={this.props.key}
position={this.props.position}
icon={this.props.icon}
>
{
this.state.isShown &&
<OverlayView
/* https://github.com/tomchentw/react-google-maps/issues/482 */
key={ Math.random() }
position={this.props.position}
mapPaneName={"overlayMouseTarget"}
getPixelPositionOffset={this._getPixelPositionOffset}
>
<div style={this.props.styles}>
{this.props.children}
</div>
</OverlayView>
}
</Marker>
);
}
2) In my map component I added all markers and in MarkerClusterer I implemented 2 hooks
<MarkerClusterer
onClusteringBegin={this._handleClusteringBegin}
onClusteringEnd={this._handleClusteringEnd}
>
{markers}
</MarkerClusterer>
3) Hooks looks something like that: clear all Overlay contents before clustering
_handleClusteringBegin() {
this.markers.forEach((marker) => {
if(!marker) {
return;
}
marker.hideMarkerContent();
});
}
4) And draw overlay contents if there is only 1 ,arker in cluster
_handleClusteringEnd(event) {
const clusters = event.clusters_;
clusters.forEach((cluster) => {
if (cluster.markers_.length == 1) {
const notClusteredMarker = cluster.markers_[0];
const notClusteredMarkerPosition = notClusteredMarker.position;
this.markers.forEach((marker) => {
if(!marker) {
return;
}
const markerPosition = new google.maps.LatLng(marker.props.position.lat, marker.props.position.lng);
if (
markerPosition.lat() == notClusteredMarkerPosition.lat()
&& markerPosition.lng() == notClusteredMarkerPosition.lng()
) {
marker.showMarkerContent();
}
});
}
});
}
I hope this will help!
Upvotes: 4