GoogleMapsAPIをReactアプリケーションに統合する方法
序章
Googleマップは、さまざまな構成設定をサポートするGoogleが提供する地図サービスです。 Googleマップをアプリケーションに追加すると、住所や座標のセットよりも多くのコンテキスト情報をユーザーに提供できます。
このチュートリアルは、Google Maps APIをReactコンポーネントに統合し、Webサイトに地図を表示できるようにすることを目的としています。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- Node.jsはローカルにインストールされます。これは、Node.jsのインストール方法とローカル開発環境の作成に従って実行できます。
- ReactJavaScriptフレームワークに精通していること。
- Google MapsJavasScriptAPIキー。 これには、Googleアカウント、Google Cloud Platform Consoleへのログイン、新しいプロジェクトの作成、およびプロジェクトのGoogle MapsJavasScriptAPIの有効化が必要です。
注: Google Maps APIを使用するときに「開発目的のみ」のメッセージを回避するには、有効なクレジットカードを提供し、それをGoogleCloudProjectの請求先アカウントに関連付ける必要があります。このチュートリアルには必要ありません。
このチュートリアルは、ノード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 [email protected]
注:オプションで、この時点で不要なファイルを削除し、src
ディレクトリにインポートできます。 logo.svg
、App.css
、index.css
は必要ありません。 index.css
を削除する場合は、ビルドエラーを回避するために、index.html
のindex.css
のimport
も削除する必要があります。
この時点で、google-maps-react
ライブラリを備えたReactアプリケーションができました。 これで、アプリケーションでマップを使用して探索できます。
ステップ2—Map
およびGoogleApiWrapper
を使用する
次に、App.js
ファイルを編集し、コードをGoogleマップをロードするコンポーネントに置き換える必要があります。
App.js
を開きます:
nano src/App.js
App.js
の内容を次のコード行に置き換えます。
src / 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
をGoogleMapsJavasScriptAPIキーに置き換えてください。
警告: APIキーは、意図しない目的で他のユーザーが使用できるため、パブリックリポジトリ(GitHubなど)にコミットするファイルには保存しないでください。
基本的なGoogleマップの機能については、これが必要なすべてのコードです。
Map
コンポーネントは、いくつかのオプションの小道具を取り入れます。
style
-CSSスタイルオブジェクトzoom
-マップの中心に焦点を合わせていることを表す数値initialCenter
-緯度と経度の座標を含むオブジェクト
この例では、次を定義しています。
100%
幅と100%
高さのCSSスタイルオブジェクト14
のズーム値-1.2884, 36.8233
の場所(ケニア、ナイロビのケニヤッタ国際コンベンションセンター)
ターミナルを開き、アプリを実行します。
npm start
そして、マップがブラウザにロードされることを確認します。
GoogleApiWrapper
は、Google APIのラッパーを提供する高次コンポーネント(HOC)です。 または、GoogleApiWrapper
HOCは、ラップされたコンポーネントの小道具で呼び出され、次のように構成オブジェクトを返す関数を渡すことで構成できます。
export default GoogleApiWrapper( (props) => ({ apiKey: props.apiKey } ))(MapContainer)
この時点で、ReactアプリケーションにGoogleマップがあります。 これで、Googleマップの他の機能の実装を検討できます。
ステップ3—Markers
およびInfoWindow
を使用する
ここで、MarkerとInfoWindowをコードに追加します。
まず、Marker
およびInfoWindow
コンポーネントをgoogle-maps-react
ライブラリからインポートして、2つのコンポーネントをロードできるようにする必要があります。
src / App.js
import React, { Component } from 'react'; import { Map, GoogleApiWrapper, InfoWindow, Marker } from 'google-maps-react';
以前のコンポーネントはステートレスでしたか? 状態管理のために状態を追加する必要があります。
src / 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
がクリックされたときのイベントハンドラーを追加する必要があります。
src / 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
ライブラリのコンポーネントであり、クリックされた[ X176X]。
onClose
メソッドは、ユーザーがInfoWindow
の閉じるボタンをクリックするとInfoWindow
を閉じるためのものです。
<Marker>
および<InfoWindow>
コンポーネントをrender
メソッドに追加して、コンポーネントを完成させましょう。
src / 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
そして、クリックするとInfoWindow
が付いたMarker
が1つあることを確認します。
フォローアップの練習として、<Map>
に<Marker>
をいくつか追加し、<InfoWindow>
に双方向性を追加することができます。
ステップ4—ユーザーの現在地を表示する
次に、ブラウザの現在の場所を取得するようにマップを設定します。 Navigator を使用します。これは、デバイスの場所へのWebコンテンツアクセスを提供するGeolocation
オブジェクトを返す読み取り専用プロパティです。
src
ディレクトリに新しいファイルを作成し、Map.js
という名前を付けます。
nano src/Map.js
CurrentLocation
という名前のコンポーネントを作成します—ここで、ブラウザーの場所を取得するためのすべての機能を構築します。
src / 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;
現在の場所が提供されていない場合は、center
でマップを設定する必要があるため、<CurrentLocation>
コンポーネントにいくつかのデフォルトの小道具を追加することから始めます。 これはブールプロップcenterAroundCurrentLocation
によって処理されます。
src / Map.js
// ... CurrentLocation.defaultProps = { zoom: 14, initialCenter: { lat: -1.2884, lng: 36.8233 }, centerAroundCurrentLocation: false, visible: true };
次に、コンポーネントをステートフルにする必要があります。
src / 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>
コンポーネントを更新して、ネットワークの問題や予期しないメンテナンスのためにGoogleMapsAPIが利用できないシナリオを処理しましょう。 また、ブラウザの現在の場所が提供され、その場所にマップを再配置する状況も処理します。
src / 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(); } } } // ...
コンポーネントの状態のcurrentLocation
が更新されたときに呼び出されるrecenterMap()
関数を定義しましょう。 panTo()
メソッドを使用して、マップの中心を変更します。
src / 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()
ライフサイクルメソッドによって処理されます。
src / 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()
関数に注意してください? 先に進んでそれを定義しましょう。
src / 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>
が現在の場所(つまり、ブラウザの現在の場所)を選択していることを確認する必要があるため、[X210Xを介して親子コンポーネント通信を導入する必要があります。 ]子コンポーネントのメソッドの呼び出しを担当するメソッド。
src / 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()
メソッドを追加しましょう。
src / 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> ); } } // ...
最後に、App.js
のMapContainer
コンポーネントを更新する必要があります。
nano src/App.js
Map
コンポーネントを新しいCurrentLocation
コンポーネントに置き換えます。
src / 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の詳細については、 React.js シリーズのコーディング方法をご覧になるか、Reactトピックページで演習やプログラミングプロジェクトを確認してください。