首页 > 解决方案 > 谷歌地图信息窗口 ReactJS

问题描述

很新的反应。我正在使用 google-maps-react-api。我有两个文件。Index.js 和 MapMarker.js。它加载了一些已加载信息窗口的位置点。我可以关闭窗口,但是单击标记时它们不会重新打开。我的 onCLick 事件没有按我的预期工作。我希望案例成为标记加载,然后单击它们以显示信息窗口,然后也可以关闭窗口。我已经阅读了 Github 上的文档和问题,但找不到信息。谢谢。

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>
    );
  }
}

标签: javascriptreactjsgoogle-maps

解决方案


我从您提供的代码和框链接中对您的 MapMaker.js 进行了一些更改。

首先,我添加了一个名为的状态showingInfoWindow并为其赋值false。这将是指示是否显示信息窗口的状态。

然后,我添加了一个名为的函数onMarkerClick,每次单击标记时都会调用该函数。这会将状态设置showingInfoWindowtrue

接下来,我在 MapMaker 类的返回中放置了一个条件,它只会在showingInfoWindow设置为时显示信息窗口true

然后,我添加了onInfoWindowClose将状态设置showingInfoWindow回的函数false

最后,我在onCloseClick函数中添加了参数并调用了onInfoWindowClose函数。

您可以按照下面的代码片段了解 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>
    );
  }
}

推荐阅读