【问题标题】:How can I use React with Google Places API, to display place markers on a Google map?如何使用 React 和 Google Places API 在 Google 地图上显示地点标记?
【发布时间】:2018-04-17 06:31:10
【问题描述】:

我正在尝试构建与on Airbnb 类似的地图,您可以在其中拖动地图时查看地点标记。 我想在地图上显示来自 Google Places API 的“酒店”标记。

使用 Google Maps 中的以下 JavaScript 代码,我可以在 Google 地图上显示酒店,但我想使用 React 来做到这一点,使用 react-google-maps。

<!DOCTYPE html>
<html>
  <head>
    <title>Place searches</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <style>
      /* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
    </style>
    <script>
      // This example requires the Places library. Include the libraries=places
      // parameter when you first load the API. For example:
      // <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">

      var map;
      var infowindow;

      function initMap() {
        var pyrmont = {lat: -33.867, lng: 151.195};

        map = new google.maps.Map(document.getElementById('map'), {
          center: pyrmont,
          zoom: 15
        });

        infowindow = new google.maps.InfoWindow();
        var service = new google.maps.places.PlacesService(map);
        service.nearbySearch({
          location: pyrmont,
          radius: 500,
          type: ['hotel']
        }, callback);
      }

      function callback(results, status) {
        if (status === google.maps.places.PlacesServiceStatus.OK) {
          for (var i = 0; i < results.length; i++) {
            createMarker(results[i]);
          }
        }
      }

      function createMarker(place) {
        var placeLoc = place.geometry.location;
        var marker = new google.maps.Marker({
          map: map,
          position: place.geometry.location
        });

        google.maps.event.addListener(marker, 'click', function() {
          infowindow.setContent(place.name);
          infowindow.open(map, this);
        });
      }
    </script>
  </head>
  <body>
    <div id="map"></div>
    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap" async defer></script>
  </body>
</html>

react-google-maps 有一个显示搜索输入字段的示例。因此,我可以通过搜索来搜索和显示标记,例如“伦敦的酒店”。但是,我不想搜索地点,而是想立即显示酒店的标记。 (以下示例中的 API 密钥来自 react-google-maps 示例。)

const _ = require("lodash");
const { compose, withProps, lifecycle } = require("recompose");
const {
  withScriptjs,
  withGoogleMap,
  GoogleMap,
  Marker,
} = require("react-google-maps");
const { SearchBox } = require("react-google-maps/lib/components/places/SearchBox");

const MapWithASearchBox = compose(
  withProps({
    googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyC4R6AN7SmujjPUIGKdyao2Kqitzr1kiRg&v=3.exp&libraries=geometry,drawing,places",
    loadingElement: <div style={{ height: `100%` }} />,
    containerElement: <div style={{ height: `400px` }} />,
    mapElement: <div style={{ height: `100%` }} />,
  }),
  lifecycle({
    componentWillMount() {
      const refs = {}

      this.setState({
        bounds: null,
        center: {
          lat: 41.9, lng: -87.624
        },
        markers: [],
        onMapMounted: ref => {
          refs.map = ref;
        },
        onBoundsChanged: () => {
          this.setState({
            bounds: refs.map.getBounds(),
            center: refs.map.getCenter(),
          })
        },
        onSearchBoxMounted: ref => {
          refs.searchBox = ref;
        },
        onPlacesChanged: () => {
          const places = refs.searchBox.getPlaces();
          const bounds = new google.maps.LatLngBounds();

          places.forEach(place => {
            if (place.geometry.viewport) {
              bounds.union(place.geometry.viewport)
            } else {
              bounds.extend(place.geometry.location)
            }
          });
          const nextMarkers = places.map(place => ({
            position: place.geometry.location,
          }));
          const nextCenter = _.get(nextMarkers, '0.position', this.state.center);

          this.setState({
            center: nextCenter,
            markers: nextMarkers,
          });
          // refs.map.fitBounds(bounds);
        },
      })
    },
  }),
  withScriptjs,
  withGoogleMap
)(props =>
  <GoogleMap
    ref={props.onMapMounted}
    defaultZoom={15}
    center={props.center}
    onBoundsChanged={props.onBoundsChanged}
  >
    <SearchBox
      ref={props.onSearchBoxMounted}
      bounds={props.bounds}
      controlPosition={google.maps.ControlPosition.TOP_LEFT}
      onPlacesChanged={props.onPlacesChanged}
    >
      <input
        type="text"
        placeholder="Customized your placeholder"
        style={{
          boxSizing: `border-box`,
          border: `1px solid transparent`,
          width: `240px`,
          height: `32px`,
          marginTop: `27px`,
          padding: `0 12px`,
          borderRadius: `3px`,
          boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
          fontSize: `14px`,
          outline: `none`,
          textOverflow: `ellipses`,
        }}
      />
    </SearchBox>
    {props.markers.map((marker, index) =>
      <Marker key={index} position={marker.position} />
    )}
  </GoogleMap>
);

<MapWithASearchBox />

我已经尝试解决这个问题很多天了,并且一直在寻找教程,但我找不到解决方案。我明白我应该使用:

new google.maps.places.PlacesService()

并添加选项:

 const center = new google.maps.LatLng(37.422, -122.084068);
 const options = {
   location: center
   radius: '500',
   types: ['hotel']
 };

当使用 react-google-maps 时,我需要使用 withScriptjs。但是我该如何把所有这些放在一起呢?

如何使用 react-google-maps 和 Google Places API,在地图上显示来自 Google 的“酒店”标记?

【问题讨论】:

    标签: javascript reactjs google-maps-api-3 google-places-api react-google-maps


    【解决方案1】:

    您可以通过将GoogleMap 的引用传递给new google.maps.places.PlacesService() 来创建服务,然后使用该服务,您可以使用nearbySearch() 搜索酒店、餐馆等。正如Google Places Nearby Search API docs 所说:

    “附近搜索”可让您按关键字或类型搜索指定区域内的地点。

    要触发fetchPlaces() 方法,您可以使用GoogleMap 组件或componentDidMount() 中的onTilesLoaded 属性。在下面的示例中,我还将fetchPlaces 传递给onBoundChanged,因为我的搜索基于bounds,因此每次移动地图时它都可以为我提供新的地点,请注意:

    const bounds = refs.map.getBounds();
    const service = new google.maps.places.PlacesService(refs.map.context.__SECRET_MAP_DO_NOT_USE_OR_YOU_WILL_BE_FIRED);
    const request = {
      bounds: bounds,
      type: ['hotel']
    };
    

    这是我使用 recompose 的示例:

    /*global google*/
    import React from "react"
    import { compose, withProps, withHandlers, withState } from "recompose"
    import { withScriptjs, withGoogleMap, GoogleMap, Marker } from "react-google-maps"
    
    const MyMapComponent = compose(
        withProps({
            googleMapURL: "https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places",
            loadingElement: <div style={{ height: `100%` }} />,
            containerElement: <div style={{ height: `400px` }} />,
            mapElement: <div style={{ height: `100%` }} />,
        }),
        withScriptjs,
        withGoogleMap,
        withState('places', 'updatePlaces', ''),
        withHandlers(() => {
            const refs = {
                map: undefined,
            }
    
            return {
                onMapMounted: () => ref => {
                    refs.map = ref
                },
                fetchPlaces: ({ updatePlaces }) => {
                    let places;
                    const bounds = refs.map.getBounds();
                    const service = new google.maps.places.PlacesService(refs.map.context.__SECRET_MAP_DO_NOT_USE_OR_YOU_WILL_BE_FIRED);
                    const request = {
                        bounds: bounds,
                        type: ['hotel']
                    };
                    service.nearbySearch(request, (results, status) => {
                        if (status == google.maps.places.PlacesServiceStatus.OK) {
                            console.log(results);
                            updatePlaces(results);
                        }
                    })
                }
            }
        }),
    )((props) => {
        return (
            <GoogleMap
                onTilesLoaded={props.fetchPlaces}
                ref={props.onMapMounted}
                onBoundsChanged={props.fetchPlaces}
                defaultZoom={8}
                defaultCenter={{ lat: 51.508530, lng: -0.076132 }}
            >
                {props.places && props.places.map((place, i) =>
                    <Marker key={i} position={{ lat: place.geometry.location.lat(), lng: place.geometry.location.lng() }} />
                )}
            </GoogleMap>
        )
    })
    
    export default class MyFancyComponent extends React.PureComponent {
        render() {
            return (
                <MyMapComponent />
            )
        }
    }
    

    【讨论】:

    猜你喜欢
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多