君は心理学者なのか?

大学時代に心理学を専攻しなぜかプログラマになった、サイコ(心理学)プログラマかろてんの雑記。

Angular2/4とgoogle maps apiを使って、緯度経度から住所を取得してみた(逆ジオコーディング)

やりたいこと

google mapのある地点をクリックした際に、

その地点の緯度経度・住所を取得する必要がありましたので、

google maps apiを使って逆ジオコーディングを実現してみました。

ジオコーディング / 逆ジオコーディングとは

  • ジオコーディング

住所の情報から、緯度経度などの地理的情報を取得すること。

  • 逆ジオコーディング

緯度経度から、住所等の情報を取得すること。

google mapをクリックした時点で緯度経度情報が取得できるので、

今回は逆ジオコーディングを行いました。

準備

karoten512.hatenablog.com

まずはこちらでAGMを導入してmapを表示するところまでやっておきます。

手順

  1. mapをクリックしたときのイベント取得ができるようにする

  2. 逆ジオコーディングを行うためのサービスを定義する

  3. mapをクリックしたときに逆ジオコーディングが行われるようする

1 mapをクリックしたときのイベント取得ができるようにする

1-1. app.component.htmlにて、mapのクリックイベントを設置する

<agm-map
  [latitude]="lat"
  [longitude]="lng"
  [zoom]="zoom"
  (mapClick)="mapClicked($event)"
  >
</agm-map>

1-2. app.component.tsにて、クリックイベントが起こった時の処理を記述する

export class AppComponent {
  /** ここから */
  mapClicked($event)
  {
    let lat = $event.coords.lat;
    let lng = $event.coords.lng;
    console.log('緯度: ' + lat);
    console.log('経度: ' + lng);
  }
  /** ここまで追加 */
}

1の結果

f:id:karoten512:20171030181914g:plain

2 逆ジオコーディングを行うためのサービスを定義する

2-1. サービスクラスを生成

ng g service geocoder

2-2. サービスクラスに必要モジュールを読み込む

/** geocoder.service.ts */
import {
  Injectable, 
  NgZone
} from '@angular/core';
import {
  AgmCoreModule,
  GoogleMapsAPIWrapper,
  MapsAPILoader
} from '@agm/core';

2-2. コンストラクタの記述

// GoogleMapsAPIWrapperを継承する
export class GeocoderService extends GoogleMapsAPIWrapper {

  constructor(
    private __loader :MapsAPILoader,
    private __zone :NgZone
  )
  {
    super(__loader, __zone);
  }
}

2-3. google maps apiの読み込み処理の記述

export class GeocoderService extends GoogleMapsAPIWrapper {
  getAddress(lat, lng)
  {
    this.__loader.load().then(() => {
      /**
       * google maps scriptsがloadしおわると、
       * この中でgoogle maps apiが使える
       * (new google.maps等)
       */
      let geocoder = new google.maps.Geocoder();

      /** 以下に逆geocode処理を記述 */
    }

  }
}

2-4. 逆ジオコーデングの処理を記述

export class GeocoderService extends GoogleMapsAPIWrapper {
  getAddress(lat, lng)
  {
    this.__loader.load().then(() => {
      /**
       * google maps scriptsがloadしおわると、
       * この中でgoogle maps apiが使える
       * (new google.maps等)
       */
      let geocoder = new google.maps.Geocoder();

      /** 以下に逆geocode処理を記述 */
      let latlng = new google.maps.LatLng(lat, lng);
      geocoder.geocode( { 'latLng': latlng }, function(results, status) {
        if (status == 'OK') {
          console.log(results);
          console.log(results[0]);
        } else {
         alert('Geocode was not successful for the following reason: ' + status);
          return false;
        }
     }
  }
}

3. mapをクリックしたときに逆ジオコーディングが行われるようする

3-1. app.module.tsにgeocoderサービスをDI

import { GeocoderService } from './geocoder.service';

@NgModule({
  providers: [
    GeocoderService
  ]
})

3-2. app.component.tsにgeocoderサービスをコンストラクタに追加

import { GeocoderService } from './geocoder.service';

export class AppComponent {
  constructor(
    private geocoderService :GeocoderService
  ) {}

3-3. app.component.tsにてgeocoderサービスの住所取得関数を呼び出す

export class AppComponent {
  mapClicked($event)
  {
    let lat = $event.coords.lat;
    let lng = $event.coords.lng;
    console.log('緯度: ' + lat);
    console.log('経度: ' + lng);
    this.geocoderService.getAddress(lat, lng); // 追加
  }
}

結果

f:id:karoten512:20171030185222g:plain

apiからは複数の逆ジオコーディング候補が返ってきます。

そのなかからいろいろな条件を指定したり、整形するなどして目的の情報を手に入れる必要があります。

今回の例では1件目(results[0])を取得してみました。