Search code examples
javascriptreactjsgoogle-mapsreact-google-maps

Custom Popups with react-google-maps


Custom Popups with react-google-maps

Someone know how to add custom Popups with react-google-maps? I want to achieve something like in a track from google: https://developers.google.com/maps/documentation/javascript/examples/overlay-popup. I tried use Portals but i don't know that's possible with react-google-maps. For now i have base like this:



function Map(restaurants) {
  const restaurantsC = restaurants.restaurants.restaurants;

  const mapRef = useRef(null);
  // Fit bounds function

  const centerPin = (data) => {
    var latLng = new window.google.maps.LatLng(
      data.Position.lat,
      data.Position.lng
    ); //Makes a latlng
    mapRef.current.panTo(latLng);
  };

  useEffect(() => {
    const fitBounds = () => {
      const bounds = new window.google.maps.LatLngBounds();
      restaurantsC.edges.forEach((document) => {
        bounds.extend(document.node.Position);
      });
      mapRef.current.fitBounds(bounds);
    };
    fitBounds();
  }, []);

  return (
    <ContextConsumer>
      {({ data, set }) => (
        <GoogleMap
          ref={mapRef}
          defaultZoom={18}
          defaultCenter={{
            lat: restaurantsC.edges[0].node.Position.lat,
            lng: restaurantsC.edges[0].node.Position.lng,
          }}
        >
          {data.currentMapLoc ? centerPin(data.currentMapLoc) : null}
          {restaurantsC.edges.map((document, index) => (
            <>
              <Marker
                key={index}
                position={{
                  lat: document.node.Position.lat,
                  lng: document.node.Position.lng,
                }}
          
                onClick={() => {
                  set({ currentMapLoc: document.node });
                  centerPin(document.node);
                }}
              />
            </>
          ))}

          {data.currentMapLoc ? (
            <>
              {centerPin(data.currentMapLoc)}
              <InfoWindow
                key={data.currentMapLoc.id}
                position={{
                  lat: data.currentMapLoc.Position.lat,
                  lng: data.currentMapLoc.Position.lng,
                }}
                onCloseClick={() => {
                  set({ currentMapLoc: null });
                }}
              >
                <div>{data.currentMapLoc.Name}</div>
              </InfoWindow>
            </>
          ) : null}
        </GoogleMap>
      )}
    </ContextConsumer>
  );
}

const MapWrapped = withScriptjs(withGoogleMap(Map));

export default function App(restaurants) {
  return (
    <div style={{ width: "700px", height: "700px" }}>
      <MapWrapped
        restaurants={restaurants}
        googleMapURL={`url`}
        loadingElement={<div style={{ height: `100%` }} />}
        containerElement={<div style={{ height: `100%` }} />}
        mapElement={<div style={{ height: `100%` }} />}
      />
    </div>
  );
}


Solution

  • The customized popup from Google Maps sample link uses Custom Overlays that uses the OverlayView object.To achieve this using the react-google-maps library, you can use the OverlayView object of the library.

    You can check this sample code (make sure to put your API key in the index file to make the code work) and code snippet below:

    import React, { Component } from 'react';
    import { withGoogleMap, GoogleMap, OverlayView } from 'react-google-maps';
    
    const getPixelPositionOffset = (width, height) => ({
      x: -(width / 2),
      y: -(height / 2)
    });
    
    class Map extends Component {
      constructor(props) {
        super(props);
    
        this.state = {
          count: 0
        };
      }
    
      onClick = () => {
        this.setState({
          count: this.state.count + 1
        });
        console.log(this.state.count);
      };
    
      handleToggleClose = () => {
        this.setState({
          isOpen: false
        });
      };
    
      render() {
        const GoogleMapExample = withGoogleMap(props => (
          <GoogleMap
            defaultCenter={{ lat: 40.756795, lng: -73.954298 }}
            defaultZoom={13}
          >
            <OverlayView
              position={{ lat: 40.756795, lng: -73.954298 }}
              mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
              getPixelPositionOffset={getPixelPositionOffset}
            >
              <div>
                <div class="popup-bubble">
                  <h1>OverlayView</h1>
                  <button onClick={this.onClick} style={{ height: 60 }}>
                    I have been clicked {this.state.count} time
                    {this.state.count > 1 ? `s` : ``}
                  </button>
                </div>
                <div class="popup-bubble-anchor" />
              </div>
            </OverlayView>
          </GoogleMap>
        ));
    
        return (
          <div>
            <GoogleMapExample
              containerElement={<div style={{ height: `500px`, width: '500px' }} />}
              mapElement={<div style={{ height: `100%` }} />}
            />
          </div>
        );
      }
    }
    
    export default Map;