最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Google maps Infowindow ReactJS - Stack Overflow

programmeradmin2浏览0评论

very new to react. I'm using google-maps-react-api. I have two files. Index.js and MapMarker.js. It loads a few location points with info windows already loaded. I can close the window but when clicking on the marker they do not reopen. My onCLick events do not work as I expect. I want the case to be the markers load and I click them to show info window and then can close the window as well. I've read the docs and issues on Github but can't find the info. Thanks.

Index.js

import ReactDOM from "react-dom";
import React from "react";

import { GoogleMap, LoadScript, MarkerClusterer } from "@react-google-maps/api";

import MapMarker from "./MapMarker";

const mapOptions = {
  fullscreenControl: false,
  streetViewControl: false,
  mapTypeControl: false,
  styles: [
    {
      featureType: "poi",
      elementType: "labels",
      stylers: [
        {
          visibility: "off"
        }
      ]
    },
    {
      featureType: "transit",
      elementType: "all",
      stylers: [
        {
          visibility: "off"
        }
      ]
    }
  ]
};
const key = ""; // PUT GMAP API KEY HERE
const defaultLocation = {
  lat: 37.9755691,
  lng: 23.7361789
};
let markers = [
  {
    id: 1,
    lat: 37.975,
    lng: 23.7361789
  },
  {
    id: 2,
    lat: 37.9755,
    lng: 23.7361789
  },
  {
    id: 3,
    lat: 37.976,
    lng: 23.7361789
  }
];

class Map extends React.Component {
  state = {
    isInfoOpen: false,
    selectedMarkerId: null,
    noOfClusters: null,
    markers: markers
  };

  onClick = (isInfoOpen, selectedMarkerId) => {
    this.setState({
      isInfoOpen,
      selectedMarkerId
    });
  };

  render() {
    const { isInfoOpen, selectedMarkerId } = this.state;

    return (
      <LoadScript googleMapsApiKey={key} >
        <div>
          <div
            style={{
              width: "100%",
              height: 500,
              display: "flex"
            }}
          >
            <GoogleMap
              options={mapOptions}
              center={defaultLocation}
              zoom={18}
              onLoad={this.onMapMounted}
              onIdle={this.onMapIdle}
              onBoundsChanged={this.onBoundsChanged}
              onZoomChanged={this.onZoomChanged}
              mapContainerStyle={{ flex: 1 }}
            >
              <MarkerClusterer averageCenter enableRetinaIcons gridSize={60}>
                {clusterer =>
                  this.state.markers.map(markerData => (
                    <MapMarker
                      key={markerData.id}
                      clusterer={clusterer}
                      markerData={markerData}
                      isSelected={markerData.id === selectedMarkerId}
                      isInfoOpen={
                        markerData.id === selectedMarkerId && isInfoOpen
                      }
                      onClick={() => this.onClick()}
                    />
                  ))
                }
              </MarkerClusterer>
            </GoogleMap>  
          </div>
        </div>
      </LoadScript>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Map />, rootElement);

MapMarker.js

import React from "react";

import { InfoWindow, Marker} from "@react-google-maps/api";

export default class MapMarker extends React.Component {
  state = {
    mapMarker: null,
    activeMarker: {},
    selectedPlace: {},
    showingInfoWindow: false
};

onMarkerClick = (props, marker) =>
    this.setState({
        activeMarker: marker,
        selectedPlace: props,
        showingInfoWindow: true
    });

onInfoWindowClose = () =>
    this.setState({
        activeMarker: null,
        showingInfoWindow: false
    });

  onLoad = mapMarker => {
    this.setState({
      mapMarker
    });
  };

  render() {
    const { clusterer, markerData } = this.props;
    const { mapMarker } = this.state;

    return (
      <Marker
        clusterer={clusterer}
        onLoad={this.onLoad}
        position={{ 
          lat: markerData.lat,
          lng: markerData.lng
        }}
        onClick={() => this.onMarkerClick()}

      >
        {mapMarker && (
        <InfoWindow
            anchor={mapMarker}
            position={{
              lat: markerData.lat,
              lng: markerData.lng
            }}  
            marker={this.state.activeMarker}
            onClose={this.onInfoWindowClose}
            visible={this.state.showingInfoWindow}
          >
            <div style={{ background: "white" }}>
              {"custom Infobox: " + markerData.id}
            </div>
          </InfoWindow>
        )}
      </Marker>
    );
  }
}

very new to react. I'm using google-maps-react-api. I have two files. Index.js and MapMarker.js. It loads a few location points with info windows already loaded. I can close the window but when clicking on the marker they do not reopen. My onCLick events do not work as I expect. I want the case to be the markers load and I click them to show info window and then can close the window as well. I've read the docs and issues on Github but can't find the info. Thanks.

Index.js

import ReactDOM from "react-dom";
import React from "react";

import { GoogleMap, LoadScript, MarkerClusterer } from "@react-google-maps/api";

import MapMarker from "./MapMarker";

const mapOptions = {
  fullscreenControl: false,
  streetViewControl: false,
  mapTypeControl: false,
  styles: [
    {
      featureType: "poi",
      elementType: "labels",
      stylers: [
        {
          visibility: "off"
        }
      ]
    },
    {
      featureType: "transit",
      elementType: "all",
      stylers: [
        {
          visibility: "off"
        }
      ]
    }
  ]
};
const key = ""; // PUT GMAP API KEY HERE
const defaultLocation = {
  lat: 37.9755691,
  lng: 23.7361789
};
let markers = [
  {
    id: 1,
    lat: 37.975,
    lng: 23.7361789
  },
  {
    id: 2,
    lat: 37.9755,
    lng: 23.7361789
  },
  {
    id: 3,
    lat: 37.976,
    lng: 23.7361789
  }
];

class Map extends React.Component {
  state = {
    isInfoOpen: false,
    selectedMarkerId: null,
    noOfClusters: null,
    markers: markers
  };

  onClick = (isInfoOpen, selectedMarkerId) => {
    this.setState({
      isInfoOpen,
      selectedMarkerId
    });
  };

  render() {
    const { isInfoOpen, selectedMarkerId } = this.state;

    return (
      <LoadScript googleMapsApiKey={key} >
        <div>
          <div
            style={{
              width: "100%",
              height: 500,
              display: "flex"
            }}
          >
            <GoogleMap
              options={mapOptions}
              center={defaultLocation}
              zoom={18}
              onLoad={this.onMapMounted}
              onIdle={this.onMapIdle}
              onBoundsChanged={this.onBoundsChanged}
              onZoomChanged={this.onZoomChanged}
              mapContainerStyle={{ flex: 1 }}
            >
              <MarkerClusterer averageCenter enableRetinaIcons gridSize={60}>
                {clusterer =>
                  this.state.markers.map(markerData => (
                    <MapMarker
                      key={markerData.id}
                      clusterer={clusterer}
                      markerData={markerData}
                      isSelected={markerData.id === selectedMarkerId}
                      isInfoOpen={
                        markerData.id === selectedMarkerId && isInfoOpen
                      }
                      onClick={() => this.onClick()}
                    />
                  ))
                }
              </MarkerClusterer>
            </GoogleMap>  
          </div>
        </div>
      </LoadScript>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Map />, rootElement);

MapMarker.js

import React from "react";

import { InfoWindow, Marker} from "@react-google-maps/api";

export default class MapMarker extends React.Component {
  state = {
    mapMarker: null,
    activeMarker: {},
    selectedPlace: {},
    showingInfoWindow: false
};

onMarkerClick = (props, marker) =>
    this.setState({
        activeMarker: marker,
        selectedPlace: props,
        showingInfoWindow: true
    });

onInfoWindowClose = () =>
    this.setState({
        activeMarker: null,
        showingInfoWindow: false
    });

  onLoad = mapMarker => {
    this.setState({
      mapMarker
    });
  };

  render() {
    const { clusterer, markerData } = this.props;
    const { mapMarker } = this.state;

    return (
      <Marker
        clusterer={clusterer}
        onLoad={this.onLoad}
        position={{ 
          lat: markerData.lat,
          lng: markerData.lng
        }}
        onClick={() => this.onMarkerClick()}

      >
        {mapMarker && (
        <InfoWindow
            anchor={mapMarker}
            position={{
              lat: markerData.lat,
              lng: markerData.lng
            }}  
            marker={this.state.activeMarker}
            onClose={this.onInfoWindowClose}
            visible={this.state.showingInfoWindow}
          >
            <div style={{ background: "white" }}>
              {"custom Infobox: " + markerData.id}
            </div>
          </InfoWindow>
        )}
      </Marker>
    );
  }
}

Share Improve this question asked Jun 14, 2020 at 7:57 RobbenRobben 592 silver badges6 bronze badges 10
  • Do you get any errors? What have you tried to debug? Can you provide a working CodeSandbox? – MrUpsidown Commented Jun 14, 2020 at 10:24
  • Hey, no errors. I've been reading the documentation and it makes no reference to being able to open and close info windows by clicking markers. react-google-maps-api-docslify.app/#infowindow . I've changed the code a little and here is the sandbox link codesandbox.io/s/cocky-faraday-10kbs?file=/src/index.js . I have a cluster, markers and info boxes displaying permanantly and an alert when the marker is clicked but when I close the info box clicking the marker does not re open. Thanks – Robben Commented Jun 14, 2020 at 11:02
  • Do you need multiple info windows to be open at the same time? Otherwise, you should probably use only 1. – MrUpsidown Commented Jun 14, 2020 at 12:04
  • No, ideally just one. Click on a marker and one window displays which I can then close and open another one. Thanks so much for your help. – Robben Commented Jun 14, 2020 at 12:08
  • 1 That library is google-map-react which doesn’t support marker clustering and the one I’m using google-map-react-api which supports clustering but doesn’t seem to support opening into windows. Thanks again for your help. I might have to Compromise something for now until I can make my own. – Robben Commented Jun 14, 2020 at 12:18
 |  Show 5 more ments

1 Answer 1

Reset to default 3

I made a couple of changes in your MapMaker.js from the codesandbox link you provided.

First, I added a state named showingInfoWindow and assign a value of false. This will be the state that will indicate if the infowindow will be shown or not.

Then, I added a function named onMarkerClick which is called everytime the Marker is clicked. This will set the state of showingInfoWindow to true.

Next, I put a condition in the return of MapMaker class, which will only show the infowindow when the showingInfoWindow is set to true.

Then, I add the onInfoWindowClose function that sets the state of showingInfoWindow back to false.

Lastly, I added the onCloseClick parameter in the and call the onInfoWindowClose function.

You can follow the code snippet below for the changes in MapMaker.js

import React from "react";

import { Marker, InfoWindow } from "@react-google-maps/api";


export default class MapMarker extends React.Component {
  state = {
    mapMarker: null,
    showingInfoWindow: false
  };

  onMarkerClick = (props) => {
    this.setState({
      showingInfoWindow: true
    });
  };

  onInfoWindowClose = () =>
    this.setState({
      showingInfoWindow: false
    });

  onLoad = (mapMarker) => {
    this.setState({
      mapMarker
    });
  };

  render() {
    const { clusterer, markerData } = this.props;

    return (
      <Marker
        clusterer={clusterer}
        onLoad={this.onLoad}
        position={{
          lat: markerData.lat,
          lng: markerData.lng
        }}
        clickable
        onClick={this.onMarkerClick}
      >
        {this.state.showingInfoWindow === true && (
          <InfoWindow
            position={{
              lat: markerData.lat,
              lng: markerData.lng
            }}
            onCloseClick={this.onInfoWindowClose}
          >
            <div>
              <p>hello</p>
            </div>
          </InfoWindow>
        )}
      </Marker>
    );
  }
}
发布评论

评论列表(0)

  1. 暂无评论