【问题标题】:Google-map-react - reactjs: How to dynamically show pop-up window after clicking on a markerGoogle-map-react - reactjs:单击标记后如何动态显示弹出窗口
【发布时间】:2020-06-05 04:09:30
【问题描述】:

我正在使用 AISHub 构建船只可视化器。我能够使用纬度/经度定位我想要的船只并将它们显示在地图上。但是容器(标记)太多,我不知道谁是谁。

问题:如何在点击如下标记后动态显示弹出窗口?

下面是我正在使用的代码中最重要的部分:

class BoatMap extends Component {
    constructor(props) {
        super(props);
        this.state = {
            buttonEnabled: true,
            buttonClickedAt: null,
            progress: 0,
            ships: [],
            type: 'All',
            shipTypes: [],
            activeShipTypes: [],
            logoMap: {}
        };
        this.updateRequest = this.updateRequest.bind(this);
        this.countDownInterval = null;
    }

// ... other operations
// ... other operations

    render() {
        return (
            <div className="google-map">
                <GoogleMapReact
                    bootstrapURLKeys={{ key: 'My_KEY' }}
                    center={{
                        lat: this.props.activeShip ? this.props.activeShip.latitude : 42.4,
                        lng: this.props.activeShip ? this.props.activeShip.longitude : -71.1
                    }}
                    zoom={8}
                >
                    {/* Rendering all the markers here */}
                    {this.state.ships.map((ship) => (
                        <Ship
                            ship={ship}
                            key={ship.CALLSIGN}
                            lat={ship.LATITUDE}
                            lng={ship.LONGITUDE}
                            logoMap={this.state.logoMap}
                        />
                    ))}

                    <select className="combo-companies" onClick={this.props.handleDropdownChange}>
                        <option value="All">All</option>

                        {this.state.shipTypes.map((type) => (
                            <option
                                className={this.state.activeShipTypes.includes(type) ? 'active' : ''}
                                key={type}
                                value={type}
                            >
                                {type}
                            </option>
                        ))}
                    </select>
                </GoogleMapReact>
            </div>
        );
    }
}

到目前为止我做了什么:

1) 我找到了this post,这对于理解程序很有用。但不幸的是我无法解决它。

2) 我还发现this one 非常有用,但是有两个问题让我无法使用它:a) 信息框不是动态的,b) 我正在使用 google-map-react 但帖子不是:

3) 最后我尝试编写自己的组件InfoWindowBox.js,下面是我到目前为止所做的,但不知道我是否朝着正确的方向前进,以及是否应该在初始代码中实现:

InfoWindowBox.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { InfoWindow } from 'google-maps-react';

export default class InfoWindowEx extends Component {
    constructor(props) {
        super(props);
        this.infoWindowRef = React.createRef();
        this.contentElement = document.createElement(`div`);
    }

    componentDidUpdate(prevProps) {
        if (this.props.children !== prevProps.children) {
            ReactDOM.render(React.Children.only(this.props.children), this.contentElement);
            this.infoWindowRef.current.infowindow.setContent(this.contentElement);
        }
    }

    render() {
        return <InfoWindow ref={this.infoWindowRef} {...this.props} />;
    }
}

请有没有人经历过这个,指导正确的方向来解决它,因为我已经没有想法了。

【问题讨论】:

    标签: javascript reactjs google-map-react


    【解决方案1】:

    据我所知,有两种方法可以添加到 Popups,这两种方法都不是 google-map-react 包的原生方法(它建议在地图上使用 react 组件)。您可以定位 &lt;Popup /&gt;position: absolute,或将 lnglat 传递给 &lt;Popup /&gt;

    第一步:创建一个标准的react组件,我们称之为&lt;Popup /&gt;

    第 2 步,选项 A:使用 CSS 定位

    position: absolute 分配给&lt;Popup /&gt;。这将允许您避免数学来确定弹出窗口何时呈现屏幕外/视口外)。将&lt;Popup /&gt;&lt;GoogleMapReact&gt;(的兄弟)相邻放置,并将父容器分配为position: relative

    <div style={{ height: '100vh', width: '100%', position: 'relative' }}>
      <GoogleMapReact
        bootstrapURLKeys={{ key: 'SECRETS' }}
        defaultCenter={defaults.center}
        defaultZoom={defaults.zoom}
      >
        {markers.map((marker) => (
          <Marker
            key={marker.id}
            lat={marker.latitude}
            lng={marker.longitude}
            onClick={() => setPopupInfo(marker)}
          />
        ))}
      </GoogleMapReact>
      {popupInfo && (<Popup store={popupInfo} style={{ position: 'absolute', top: 0, left: 0, width: '200px' }} />)}
    </div>
    

    第 2 步,选项 B:使用地图 lat/lng 定位

    或者,您可以将latlng 作为道具传递给&lt;Popup /&gt;。为此,Popup 应该是 &lt;GoogleMapReact&gt; 的子级。

    <div>
      <GoogleMapReact
        bootstrapURLKeys={{ key: 'SECRETS' }}
        defaultCenter={defaults.center}
        defaultZoom={defaults.zoom}
      >
        {markers.map((marker) => (
          <Marker
            key={marker.id}
            lat={marker.latitude}
            lng={marker.longitude}
            onClick={() => setPopupInfo(marker)}
          />
        ))}
        {popupInfo && (<Popup
          store={popupInfo}
          lat={popupInfo.latitude}
          lng={popupInfo.longitude}
         />)}
      </GoogleMapReact>
    </div>
    

    【讨论】:

    • 感谢您的回答和您阅读问题的时间,非常感谢您的宝贵时间。这也是一个很好的答案。
    【解决方案2】:

    我在 reactjs 中成功创建了这个,但是我没有使用 google-map-react。我只是简单地使用了这个answer 中的一些sn-ps,并在我的sample react code 中使用它。您可以在提供的链接中看到它,然后才能看到它工作,您必须在此行中更改 API 密钥

    const API_KEY = "CHANGE_YOUR_API_KEY";
    

    供您参考,以下是我在代码中的实现方式:

    import React from "react";
    import ReactDOM from 'react-dom';
    
    var map;
    var markers=[];
    var infowindow;
    const API_KEY = "CHANGE_YOUR_API_KEY" ;
    
    class Map extends React.Component {
      constructor(props) { 
        super(props);
        this.onScriptLoad = this.onScriptLoad.bind(this);
      }
    
    
      onScriptLoad() {
          var locations = [
                ['Bondi Beach', -33.890542, 151.274856, 4],
                ['Coogee Beach', -33.923036, 151.259052, 5],
                ['Cronulla Beach', -34.028249, 151.157507, 3],
                ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
                ['Maroubra BeachManly Beach Manly Beach Manly Beach', -33.950198, 151.259302, 1]
            ];
          var mapOptions = {
                zoom: 10,
                center: new google.maps.LatLng(locations[0][1], locations[0][2]),
                scrollwheel: true,
            };   
        map = new window.google.maps.Map(document.getElementById(this.props.id), mapOptions);
        this.props.onMapLoad(map)
    
           for (var count = 0; count < locations.length; count++) {
             var name = locations[count][0];
             var loc =  new google.maps.LatLng(locations[count][1], locations[count][2]);
                this.createMarker(name,loc);
            }
      }
    
      componentDidMount() {
        if (!window.google) {
          const script = document.createElement('script');
          script.type = 'text/javascript';
          script.src = `https://maps.googleapis.com/maps/api/js?key=`+API_KEY+`&libraries=places,geometry`;
          script.id = 'googleMaps';
          script.async = true;
          script.defer = true;
          document.body.appendChild(script);
          script.addEventListener('load', e => {
            this.onScriptLoad()
          })
        }
        else {
          this.onScriptLoad()
        }
        var marker = new google.maps.Marker({
          position: { lat: -25.344, lng: 131.036 },
          map: map
        });
      }
    
      createMarker(name,loc) {
        var marker = new google.maps.Marker({
          map: map,
          position: loc,
          title: name
    
        });
        markers.push(marker);
    
        infowindow = new google.maps.InfoWindow();
        var content =
          'Location: ' + name +
          '<br/>Lat: ' + loc.lat() +
          '<br/>Long: ' + loc.lng() ;
    
        marker.addListener('click', ()=>{     
          infowindow.setContent(content);  
          infowindow.open(map, marker); 
        });
      }
    
      render() {
        return (
          <div id="root">
          <div className="map" id={this.props.id} />
          </div>
        )
      }
    }
    
    export default Map;
    
    

    注意:有时我的代码在 Stackblitz 中显示“google is not defined”错误,但如果您在任何地方放置空格,您仍然可以继续。

    【讨论】:

    • Pagemag,答案开头链接的示例反应代码不起作用。 this 是链接。
    猜你喜欢
    • 2012-05-03
    • 2020-02-16
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    相关资源
    最近更新 更多