【问题标题】:Adding Marker to Google Maps in google-map-react在 google-map-react 中向 Google 地图添加标记
【发布时间】:2017-05-15 07:00:57
【问题描述】:

我正在使用google-map-react NPM 包来创建一个谷歌地图和几个标记。

问题:我们如何将默认的 Google 地图标记添加到地图中?

From this Github issue,看来我们需要使用onGoogleApiLoaded 函数访问内部Google Maps API。

引用an example from the Google Maps JS API docs,我们可以使用下面的代码来渲染标记,但是我们如何定义对map的引用呢?

var marker = new google.maps.Marker({
    position: myLatLng,
    map: map,
    title: 'Hello World!'
});

当前代码:

renderMarkers() {
    ...
}

render() {
    return (
        <div style={{'width':800,'height':800}}>
            <GoogleMap
                bootstrapURLKeys={{key: settings.googleMapApiKey}}
                defaultZoom={13}
                defaultCenter={{ 
                    lat: this.props.user.profile.location.coordinates[1], 
                    lng: this.props.user.profile.location.coordinates[0]
                }}
                onGoogleApiLoaded={({map, maps}) => this.renderMarkers()}
                yesIWantToUseGoogleMapApiInternals
            >
            </GoogleMap>
        </div>
    );
}

【问题讨论】:

    标签: javascript google-maps reactjs meteor google-maps-api-3


    【解决方案1】:

    编辑:
    由于发布了此答案,GoogleMapReact 元素的文档(可能还有 API)已更改为支持子级。任何具有latlng 的孩子都将在地图上的相应位置呈现,@Jobsamuel 的回答也表明了这一点。

    onGoogleApiLoaded 回调不应用于此目的,因为它不如声明式风格,并且在对地图进行更改时不会重新运行。


    原始答案(已过时):

    这在自述文件中的描述中可能并不完全清楚,但 maps 参数实际上是地图 API 对象(当然,map 是当前的 Google Map 实例)。因此,您应该将两者都传递给您的方法:

    onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)}
    

    并使用它们:

    renderMarkers(map, maps) {
      let marker = new maps.Marker({
        position: myLatLng,
        map,
        title: 'Hello World!'
      });
    }
    

    【讨论】:

    • 你还知道如何添加infowindow吗?我在执行此操作时遇到了困难
    • 我确实在这个包中使用了原始的 Maps API,而是声明性的 React API。 Google API 文档中的example 不适合您吗?如果没有,您可能应该使用您的代码和解释创建一个新问题。
    • 每次地图更改时如何重新渲染标记?
    • 是他们的演示
    【解决方案2】:

    在地图上添加标记并不像我们想的那么简单,主要是因为confusing docs,但这里有一个超级简单的例子:

    const Map = props => {
      return (
        <GoogleMapReact
         bootstrapURLKeys={{ props.key }}
         defaultCenter={{lat: props.lat, lng: props.lng}}
         defaultZoom={props.zoom}>
    
           {/* This is the missing part in docs:
             *
             * Basically, you only need to add a Child Component that
             * takes 'lat' and 'lng' Props. And that Component should
             * returns a text, image, super-awesome-pin (aka, your marker).
             *
             */}
           <Marker lat={props.lat} lng={props.lng}} />
        </GoogleMapReact>
      )
    }
    
    const Marker = props => {
      return <div className="SuperAwesomePin"></div>
    }
    

    【讨论】:

    • 你能发布你的 SuperAwesomePin 课程吗?
    • 如何导入Marker
    • @ben.coffee 你不需要。 Marker 只是一个自定义组件。类似const Marker = props =&gt; &lt;div className="pin"&gt;&lt;/div&gt;
    • 这里有@newman gist.github.com/jobsamuel/56496033bfb4d0f3e316aeb88341ed16 (抱歉,超超级超级迟到的答案)
    • 我觉得这很令人困惑,因为打字稿迫使我将 lat lng 道具添加到市场组件,但它也不能那样工作..
    【解决方案3】:
    import React from 'react';
    import GoogleMapReact from 'google-map-react';
    
    const GoogleMaps = ({ latitude, longitude }) => {
     const renderMarkers = (map, maps) => {
      let marker = new maps.Marker({
      position: { lat: latitude, lng: longitude },
      map,
      title: 'Hello World!'
      });
      return marker;
     };
    
     return (
       <div style={{ height: '50vh', width: '100%' }}>
        <GoogleMapReact
          bootstrapURLKeys={{ key: 'YOUR KEY' }}
          defaultCenter={{ lat: latitude, lng: longitude }}
          defaultZoom={16}
          yesIWantToUseGoogleMapApiInternals
          onGoogleApiLoaded={({ map, maps }) => renderMarkers(map, maps)}
        >
        </GoogleMapReact>
       </div>
     );
    };
    
    export default GoogleMaps;
    

    【讨论】:

    • 查看文档,它提到“您可以使用 onGoogleApiLoaded 访问 Google Maps 地图和地图对象,在这种情况下,您需要将 yesIWantToUseGoogleMapApiInternals 设置为 true”,这有助于我使用上面的代码这对我有用。
    【解决方案4】:

    基于MasterAM 的回答。

    如果你使用 react 钩子,这个可以解决问题:

    import React, { useMemo, useEffect } from 'react';
    
    const createControlledPromise = () => {
      let resolver;
      let rejector;
      const promise = new Promise((resolve, reject) => {
        resolver = resolve;
        rejector = reject;
      });
      return { promise, resolver, rejector };
    };
    
    const useMarker = ({ lat, lng }) => {
      const { 
        promise: apiPromise, 
        resolver: handleGoogleApiLoaded 
      } = useMemo(
        createControlledPromise,
        []
      ).current;
    
      useEffect(
        () => {
          let marker;
          apiPromise.then(api => {
            const { map, maps } = api;
            marker = new maps.Marker({ position: { lat, lng }, map });
          });
          return () => {
            if (marker) {
              marker.setMap(null);
            }
          };
        },
        [lat, lon],
      );
      return { handleGoogleApiLoaded };
    };
    
    const Location = ({
      location: { locationName, lat, lng }
    }) => {
      const { handleGoogleApiLoaded } = useMarker({ lat, lng });
      return (
        <section>
          <h1>{locationName}</h1>
          <p>
            <GoogleMapReact
              bootstrapURLKeys={{ key: __GOOGLE_MAP_API_KEY__ }}
              center={{ lat, lng }}
              defaultZoom={11}
              onGoogleApiLoaded={handleGoogleApiLoaded}
            />
          </p>
        </section>
      );
    };
    

    【讨论】:

    • 感谢您的提及。请注意,API/文档已更改为支持子级。有关详细信息,请参阅我的编辑。
    猜你喜欢
    • 2020-12-03
    • 2013-06-14
    • 1970-01-01
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 2020-07-30
    相关资源
    最近更新 更多