GoogleMapsAPIをReactアプリケーションに統合する方法

提供:Dev Guides
移動先:案内検索

序章

Googleマップは、さまざまな構成設定をサポートするGoogleが提供する地図サービスです。 Googleマップをアプリケーションに追加すると、住所や座標のセットよりも多くのコンテキスト情報をユーザーに提供できます。

このチュートリアルは、Google Maps APIをReactコンポーネントに統合し、Webサイトに地図を表示できるようにすることを目的としています。

前提条件

このチュートリアルを完了するには、次のものが必要です。

注: Google Maps APIを使用するときに「開発目的のみ」のメッセージを回避するには、有効なクレジットカードを提供し、それをGoogleCloudProjectの請求先アカウントに関連付ける必要があります。このチュートリアルには必要ありません。


このチュートリアルは、ノードv14.2.0、npm v6.14.5、react v16.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 [email protected]

注:オプションで、この時点で不要なファイルを削除し、srcディレクトリにインポートできます。 logo.svgApp.cssindex.cssは必要ありません。 index.cssを削除する場合は、ビルドエラーを回避するために、index.htmlindex.cssimportも削除する必要があります。


この時点で、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を使用する

ここで、MarkerInfoWindowをコードに追加します。

まず、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
  };

  // ...
}

次に、MapMarkerがクリックされたときのイベントハンドラーを追加する必要があります。

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.jsMapContainerコンポーネントを更新する必要があります。

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トピックページで演習やプログラミングプロジェクトを確認してください。