介绍
Google Maps 是 Google 提供的地图服务,支持多种配置设置。将 Google 地图添加到您的应用程序可以为用户提供比街道地址或坐标集更多的上下文信息。
本教程旨在将 Google Maps API 集成到您的 React 组件中,并使您能够在您的网站上显示地图。
先决条件
要完成本教程,您需要:
- Node.js 安装在本地,您可以按照如何安装 Node.js 和创建本地开发环境来完成。
- 熟悉React JavaScript 框架。
- 一个Google Maps JavasScript API 密钥。
- 这将需要一个 Google 帐户,登录到 Google Cloud Platform Console,创建一个新项目,并为该项目启用 Google Maps JavasScript API。
注意:为避免在使用 Google Maps API 时出现“仅用于开发目的”消息,您需要提供有效的信用卡并与 Google Cloud 项目的结算帐户相关联,但本教程不需要这样做。
本教程已通过 Node v14.2.0、npm
v6.14.5、react
v16.13.1 和google-maps-react
v.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
,您还应该删除import
for index.css
inindex.html
以避免构建错误。
此时,您有一个带有google-maps-react
库的 React 应用程序。您现在可以在应用程序中使用地图进行探索。
第 2 步 – 使用Map
和GoogleApiWrapper
接下来,您需要编辑App.js
文件并将代码替换为将加载 Google 地图的组件。
打开App.js
:
- nano src/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 步 – 使用Markers
和InfoWindow
您现在将在您的代码中添加一个Marker
和一个InfoWindow
。
首先,您需要从库中导入Marker
和InfoWindow
组件,google-maps-react
以帮助您实现对两者的加载。
import React, { Component } from 'react';
import { Map, GoogleApiWrapper, InfoWindow, Marker } from 'google-maps-react';
注意到你之前的组件是无状态的吗?您需要为状态管理添加状态。
// ...
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
。
// ...
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
:
// ...
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
– 您将在此处构建所有功能以检索浏览器的位置:
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
:
// ...
CurrentLocation.defaultProps = {
zoom: 14,
initialCenter: {
lat: -1.2884,
lng: 36.8233
},
centerAroundCurrentLocation: false,
visible: true
};
接下来,您需要使您的组件有状态:
// ...
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 不可用的情况。并且还可以处理提供浏览器当前位置并将地图重新定位到该位置的情况。
// ...
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()
方法来更改地图的中心。
// ...
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()
生命周期方法处理,该方法将设置回调以获取当前位置。
// ...
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()
功能了吗?让我们继续并定义它。
// ...
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()
方法将负责调用子组件上的方法。
// ...
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()
方法:
// ...
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
组件替换该组件:
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 主题页面以获取练习和编程项目。