如何将 Google Maps API 集成到 React 应用程序中

介绍

Google Maps 是 Google 提供的地图服务,支持多种配置设置。将 Google 地图添加到您的应用程序可以为用户提供比街道地址或坐标集更多的上下文信息。

本教程旨在将 Google Maps API 集成到您的 React 组件中,并使您能够在您的网站上显示地图。

先决条件

要完成本教程,您需要:

注意:为避免在使用 Google Maps API 时出现“仅用于开发目的”消息,您需要提供有效的信用卡并与 Google Cloud 项目的结算帐户相关联,但本教程不需要这样做。

本教程已通过 Node v14.2.0、npmv6.14.5、reactv16.13.1 和google-maps-reactv.2.0.6 验证。

步骤 1 — 设置 React 应用程序

在本教程中,您将使用create-react-app脚手架搭建一个新的 React 应用程序。

首先,在终端窗口中运行npx以使用create-react-app

  • npx create-react-app react-googlemaps

然后,导航到您的新项目目录:

cd react-googlemaps

在添加任何代码之前,让我们安装依赖项:

  • npm install google-maps-react@2.0.6

注意:可选地,此时您可以删除src目录中不必要的文件和导入您不需要logo.svg, App.css, index.css如果您删除index.css,您还应该删除importfor index.cssinindex.html以避免构建错误。

此时,您有一个带有google-maps-react的 React 应用程序您现在可以在应用程序中使用地图进行探索。

第 2 步 – 使用MapGoogleApiWrapper

接下来,您需要编辑App.js文件并将代码替换为将加载 Google 地图的组件。

打开App.js:

  • nano src/App.js

将 的内容替换为App.js以下代码行:

源代码/App.js
import React, { Component } from 'react';
import { Map, GoogleApiWrapper } from 'google-maps-react';

const mapStyles = {
  width: '100%',
  height: '100%'
};

export class MapContainer extends Component {
  render() {
    return (
      <Map
        google={this.props.google}
        zoom={14}
        style={mapStyles}
        initialCenter={
          {
            lat: -1.2884,
            lng: 36.8233
          }
        }
      />
    );
  }
}

export default GoogleApiWrapper({
  apiKey: 'YOUR_GOOGLE_MAPS_API_KEY_GOES_HERE'
})(MapContainer);

注意:替换YOUR_GOOGLE_MAPS_API_KEY_GOES_HERE为您的 Google Maps JavaScript API 密钥。

警告:请务必避免将您的 API 密钥保存在您提交到公共存储库(如 GitHub)的任何文件中,因为它可能会被其他人用于您不想要的目的。

对于基本 Google 地图的功能,这就是您需要的全部代码。

Map组件接受一些可选的道具:

  • style – CSS 样式对象
  • zoom – 数值表示更紧密地关注地图的中心
  • initialCenter – 包含纬度和经度坐标的对象

在此示例中,您将定义:

  • 具有100%宽度和100%高度的 CSS 样式对象
  • 缩放值 14
  • 和地点-1.2884, 36.8233(肯尼亚内罗毕的肯雅塔国际会议中心)

打开您的终端并运行您的应用程序:

  • npm start

并确保地图加载到浏览器:

浏览器中显示的地图

GoogleApiWrapper是一个高阶组件 (HOC),它提供了围绕 Google API 的包装器。或者,GoogleApiWrapper可以通过传递一个函数来配置 HOC ,该函数将被包装组件的 props 调用,并且应该像这样返回配置对象:

export default GoogleApiWrapper(
  (props) => ({
    apiKey: props.apiKey
  }
))(MapContainer)

此时,您的 React 应用程序中有一个 Google Map。您现在可以探索实现 Google 地图的其他功能。

第 3 步 – 使用MarkersInfoWindow

您现在将在您的代码中添加一个Marker和一个InfoWindow

首先,您需要库中导入MarkerInfoWindow组件,google-maps-react以帮助您实现对两者的加载。

源代码/App.js
import React, { Component } from 'react';
import { Map, GoogleApiWrapper, InfoWindow, Marker } from 'google-maps-react';

注意到你之前的组件是无状态的吗?您需要为状态管理添加状态。

源代码/App.js
// ...

export class MapContainer extends Component {
  state = {
    showingInfoWindow: false,  // Hides or shows the InfoWindow
    activeMarker: {},          // Shows the active marker upon click
    selectedPlace: {}          // Shows the InfoWindow to the selected place upon a marker
  };

  // ...
}

接下来,您需要为单击Map时添加事件处理程序Marker

源代码/App.js
// ...

export class MapContainer extends Component {
  // ...

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

  onClose = props => {
    if (this.state.showingInfoWindow) {
      this.setState({
        showingInfoWindow: false,
        activeMarker: null
      });
    }
  };

  // ...
}

onMarkerClick方法用于显示InfoWindow,它是google-maps-react库中的一个组件, 它使您能够显示一个弹出窗口,显示单击的 的详细信息Marker

onClose方法用于在InfoWindow用户单击InfoWindow.

让我们通过向方法添加<Marker><InfoWindow>组件来完成您的组件render

源代码/App.js
// ...

export class MapContainer extends Component {
  // ...

  render() {
    return (
      <Map
        google={this.props.google}
        zoom={14}
        style={mapStyles}
        initialCenter={
          {
            lat: -1.2884,
            lng: 36.8233
          }
        }
      >
        <Marker
          onClick={this.onMarkerClick}
          name={'Kenyatta International Convention Centre'}
        />
        <InfoWindow
          marker={this.state.activeMarker}
          visible={this.state.showingInfoWindow}
          onClose={this.onClose}
        >
          <div>
            <h4>{this.state.selectedPlace.name}</h4>
          </div>
        </InfoWindow>
      </Map>
    );
  }
}

运行您的应用程序:

  • npm start

并确保您拥有点击后的Marker那个InfoWindow

在浏览器中显示带有标记和信息窗口的地图

作为后续练习,您可以<Marker>在您<Map><InfoWindow>.

步骤 4 — 显示用户的当前位置

您现在将设置地图以检索浏览器的当前位置。您将使用Navigator,它是一个只读属性,它返回一个Geolocation对象,对象允许 Web 内容访问设备的位置。

在您的src目录中创建一个新文件并将其命名为Map.js

  • nano src/Map.js

您将创建一个名为的组件CurrentLocation– 您将在此处构建所有功能以检索浏览器的位置:

源代码/Map.js
import React from 'react';
import ReactDOM from 'react-dom';

const mapStyles = {
  map: {
    position: 'absolute',
    width: '100%',
    height: '100%'
  }
};

export class CurrentLocation extends React.Component {
  // ...
}

export default CurrentLocation;

您将首先向<CurrentLocation>组件添加一些默认道具,因为如果center未提供当前位置,您将需要使用 a 设置地图这是由 boolean prop 处理的centerAroundCurrentLocation

源代码/Map.js
// ...

CurrentLocation.defaultProps = {
  zoom: 14,
  initialCenter: {
    lat: -1.2884,
    lng: 36.8233
  },
  centerAroundCurrentLocation: false,
  visible: true
};

接下来,您需要使您的组件有状态:

源代码/Map.js
// ...

export class CurrentLocation extends React.Component {
  constructor(props) {
    super(props);

    const { lat, lng } = this.props.initialCenter;

    this.state = {
      currentLocation: {
        lat: lat,
        lng: lng
      }
    };
  }
}

// ...

我们还更新您的<CurrentLocation>组件以处理由于网络问题或意外维护而导致 Google Maps API 不可用的情况。并且还可以处理提供浏览器当前位置并将地图重新​​定位到该位置的情况。

源代码/Map.js
// ...

export class CurrentLocation extends React.Component {
  // ...

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.google !== this.props.google) {
      this.loadMap();
    }
    if (prevState.currentLocation !== this.state.currentLocation) {
      this.recenterMap();
    }
  }
}

// ...

让我们定义在组件状态更新recenterMap()时调用函数currentLocation它将使用该panTo()方法来更改地图的中心。

源代码/Map.js
// ...

export class CurrentLocation extends React.Component {
  // ...

  recenterMap() {
    const map = this.map;
    const current = this.state.currentLocation;
    const google = this.props.google;
    const maps = google.maps;

    if (map) {
      let center = new maps.LatLng(current.lat, current.lng);
      map.panTo(center);
    }
  }
}

// ...

接下来,您将需要在地图已加载时处理该场景。这将由componentDidMount()生命周期方法处理,该方法将设置回调以获取当前位置。

源代码/Map.js
// ...

export class CurrentLocation extends React.Component {
  // ...

  componentDidMount() {
    if (this.props.centerAroundCurrentLocation) {
      if (navigator && navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(pos => {
          const coords = pos.coords;
          this.setState({
            currentLocation: {
              lat: coords.latitude,
              lng: coords.longitude
            }
          });
        });
      }
    }
    this.loadMap();<^>
  }
}

// ...

注意到loadMap()功能了吗?让我们继续并定义它。

源代码/Map.js
// ...

export class CurrentLocation extends React.Component {
  // ...

  loadMap() {
    if (this.props && this.props.google) {
      // checks if google is available
      const { google } = this.props;
      const maps = google.maps;

      const mapRef = this.refs.map;

      // reference to the actual DOM element
      const node = ReactDOM.findDOMNode(mapRef);

      let { zoom } = this.props;
      const { lat, lng } = this.state.currentLocation;
      const center = new maps.LatLng(lat, lng);

      const mapConfig = Object.assign(
        {},
        {
          center: center,
          zoom: zoom
        }
      );

      // maps.Map() is constructor that instantiates the map
      this.map = new maps.Map(node, mapConfig);
    }
  }
}

// ...

loadMap()函数在组件渲染后调用,并获取对 DOM 组件的引用,指向您希望放置地图的位置。

您的<CurrentLocation>组件几乎已完成。但是您需要确保您之前<Marker>选择了您当前的位置(即浏览器的当前位置),因此您需要通过该方法引入父子组件通信,该renderChildren()方法将负责调用子组件上的方法。

源代码/Map.js
// ...

export class CurrentLocation extends React.Component {
  // ...

  renderChildren() {
    const { children } = this.props;

    if (!children) return;

    return React.Children.map(children, c => {
      if (!c) return;

      return React.cloneElement(c, {
        map: this.map,
        google: this.props.google,
        mapCenter: this.state.currentLocation
      });
    });
  }
}

// ...

最后,让我们添加您的render()方法:

源代码/Map.js
// ...

export class CurrentLocation extends React.Component {
  // ...

  render() {
    const style = Object.assign({}, mapStyles.map);

    return (
      <div>
        <div style={style} ref="map">
          Loading map...
        </div>
        {this.renderChildren()}
      </div>
    );
  }
}

// ...

最后,您需要更新您的MapContainer组件App.js

  • nano src/App.js

Map用您的新CurrentLocation组件替换该组件:

源代码/App.js
import React, { Component } from 'react';
import { GoogleApiWrapper, InfoWindow, Marker } from 'google-maps-react';

import CurrentLocation from './Map';

export class MapContainer extends Component {
  state = {
    showingInfoWindow: false,
    activeMarker: {},
    selectedPlace: {}
  };

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

  onClose = props => {
    if (this.state.showingInfoWindow) {
      this.setState({
        showingInfoWindow: false,
        activeMarker: null
      });
    }
  };

  render() {
    return (
      <CurrentLocation
        centerAroundCurrentLocation
        google={this.props.google}
      >
        <Marker onClick={this.onMarkerClick} name={'Current Location'} />
        <InfoWindow
          marker={this.state.activeMarker}
          visible={this.state.showingInfoWindow}
          onClose={this.onClose}
        >
          <div>
            <h4>{this.state.selectedPlace.name}</h4>
          </div>
        </InfoWindow>
      </CurrentLocation>
    );
  }
}

export default GoogleApiWrapper({
  apiKey: 'YOUR_GOOGLE_MAPS_API_KEY_GOES_HERE'
})(MapContainer);

运行您的应用程序:

npm start

转到您的浏览器,您的地图应首先加载,initialCenter然后重新加载以选择浏览器的当前位置,并Marker定位到该位置,瞧,您完成了:

在浏览器中显示当前位置的地图

结论

在本文中,您能够加载您的<Map>React 组件,添加一个Marker并将其关联InfoWindow到它。您还使地图显示了您的当前位置。

基于这些知识,您可以实现更高级的功能,例如具有折线和多边形或将事件侦听器添加到您的地图中。

如果您想了解有关 React 的更多信息,请查看我们的How To Code in React.js系列,或查看我们的 React 主题页面以获取练习和编程项目。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁