skip to Main Content

I want to create a tool-tip on a marker on the map, that when clicked opens a window with some information. I use @react-google-maps/api

I want something like this:
enter image description here

this is my code:

import { GoogleMap, LoadScript, Marker } from '@react-google-maps/api';
import { AppConfig } from '../../../constants/AppConfig';

const containerStyle = {
  width: '100%',
  height: '100%',
};

export interface MapProps {
  isMarkerShown?: boolean;
  otherMarkers?: {
    lat: number;
    lng: number;
  }[];
  lat: number;
  lng: number;
}

export const Map = ({ lat, lng, isMarkerShown = true, otherMarkers }: MapProps) => {
  return (
    <LoadScript googleMapsApiKey={AppConfig.googleMapsApiKey}>
      <GoogleMap
        options={{
          disableDefaultUI: true,
          styles: [
            { featureType: 'poi', elementType: 'labels', stylers: [{ visibility: 'off' }] },
            { featureType: 'transit', elementType: 'labels', stylers: [{ visibility: 'off' }] },
          ],
        }}
        mapContainerStyle={containerStyle}
        center={{ lat, lng }}
        zoom={15}
      >
        <Marker
          position={{ lat, lng }}
          visible={isMarkerShown}
          options={{}}
          icon="/assets/svg/MapMakerIcon.svg"
        />
        {/* other markers */}
        {otherMarkers &&
          otherMarkers.map((marker) => (
            <Marker
              title="marker"
              key={`${marker.lat}-${marker.lng}`}
              position={{ lat: marker.lat, lng: marker.lng }}
              icon="/assets/svg/MapMarkerRoundedIcon.svg"
            />
          ))}
      </GoogleMap>
    </LoadScript>
  );
};

I want render the tooltip in other markers.

2

Answers


  1. Chosen as BEST ANSWER

    To create a tooltip-like pop-up on a marker in your Google Map using @react-google-maps/api.

    @react-google-maps/api has a component called InfoBox that can be used to display information

    A state must be created to save information about some data and to verify that it is open.

    A function must be defined to manage the clinics in the markers and update the status with the information of the selected marker.

    And customize the content of the InfoBox to display the desired information.

    import { useState } from 'react';
    import { GoogleMap, LoadScript, Marker, InfoBox } from '@react-google-maps/api';
    import { Box, Typography } from '@mui/material';
    
    import { AppConfig } from '../../../constants/AppConfig';
    import { Color } from '../../../theme/MUITheme/colors';
    import CloseIcon from '../../icons/CloseIcon';
    import { IconButton } from '../IconButton/IconButton';
    import { VSpacer } from '../Spacer';
    import { TextLink } from '../TextLink/TextLink';
    import DirectionsIcon from '../../icons/DirectionsIcon';
    
    import './Map.scss';
    import { IClinicInformation } from '@libs/shared';
    
    const containerStyle = {
      width: '100%',
      height: '100%',
    };
    
    export interface MapProps {
      isMarkerShown?: boolean;
      clinicsInformation?: IClinicInformation[];
      lat: number;
      lng: number;
    }
    
    export const Map = ({ lat, lng, isMarkerShown = true, clinicsInformation }: MapProps) => {
      const [selectedClinic, setSelectedClinic] = useState<IClinicInformation | null>(null);
    
      const handleMarkerClick = (marker: IClinicInformation) => {
        setSelectedClinic(marker);
      };
    
      return (
        <LoadScript googleMapsApiKey={AppConfig.googleMapsApiKey}>
          <GoogleMap
            options={{
              disableDefaultUI: true,
              styles: [
                { featureType: 'poi', elementType: 'labels', stylers: [{ visibility: 'off' }] },
                { featureType: 'transit', elementType: 'labels', stylers: [{ visibility: 'off' }] },
              ],
            }}
            mapContainerStyle={containerStyle}
            center={{ lat, lng }}
            zoom={15}
          >
            <Marker
              position={{ lat, lng }}
              visible={isMarkerShown}
              icon="/assets/svg/MapMakerIcon.svg"
            />
            {/* other markers */}
            {clinicsInformation &&
              clinicsInformation.map((clinic) => (
                <Marker
                  title="marker"
                  key={`${clinic.location?.coordinates[0]}-${clinic.location?.coordinates[1]}`}
                  position={{
                    lat: clinic.location?.coordinates[0] ?? 0,
                    lng: clinic.location?.coordinates[1] ?? 0,
                  }}
                  icon="/assets/svg/MapMarkerRoundedIcon.svg"
                  onClick={() => handleMarkerClick(clinic)}
                />
              ))}
            {selectedClinic && (
              <InfoBox
                position={
                  new google.maps.LatLng(
                    selectedClinic.location?.coordinates[0] ?? 0,
                    selectedClinic.location?.coordinates[1] ?? 0,
                  )
                }
                options={{
                  closeBoxURL: '',
                  enableEventPropagation: true,
                }}
              >
                <Box
                  borderRadius="10px"
                  boxShadow="0px 4px 4px 0px rgba(0, 0, 0, 0.05)"
                  padding="9px 13px"
                  width="100%"
                  sx={{ backgroundColor: '#fff' }}
                >
                  <Box display="flex" alignItems="center" justifyContent="space-between">
                    <Typography color={Color.primary.main} variant="body2" fontWeight="bold">
                      {selectedClinic.name}
                    </Typography>
                    <IconButton
                      testID="close-tooltip"
                      size="small"
                      onClick={() => setSelectedClinic(null)}
                      sx={{ padding: '4px' }}
                    >
                      <CloseIcon />
                    </IconButton>
                  </Box>
    
                  <VSpacer size="1" />
    
                  <Box display="flex" alignItems="start" justifyContent="space-between">
                    <Box>
                      <Typography fontSize="12px" variant="body2">
                        {selectedClinic.address?.main}
                      </Typography>
                      <Typography fontSize="12px" variant="body2">
                        Abierto {selectedClinic.is24Hours ? '24 horas' : 'hasta las 18:00'}
                      </Typography>
                      <Typography noWrap fontSize="12px" variant="body2">
                        Teléfono: {selectedClinic.directPhone}
                      </Typography>
                      <TextLink fontSize="12px" testID="view-more">
                        Ver más
                      </TextLink>
                    </Box>
                    <IconButton testID="directions" size="small" sx={{ padding: '4px' }}>
                      <DirectionsIcon />
                    </IconButton>
                  </Box>
                </Box>
              </InfoBox>
            )}
          </GoogleMap>
        </LoadScript>
      );
    };


  2. I had to go read the documentation and found out that there were some missing parts. You can consider

    That, you only need to add a Child Component that takes ‘lat’ and ‘lng’ Props. And that Component should returns a text, image and your marker.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search