YOLP(地図) を利用して、Yahoo! Japan の地図情報を利用するサンプルコード

# 前置き

映画「天気の子」を鑑賞して、感動した自分。
感動を形にしたくて、「天気の子」のモデル場所（いわゆる聖地）のナビゲーションウェブアプリを開発しました。

* [天気の子 聖地ナビ] (https://www.tenkinokoseichi.link/)

![tenkinoseichi_main.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83767/6334b54e-eae1-4acc-d39c-4b93250af2e6.jpeg)

# 本題

今回の開発にあたっては、Yahoo! Japan 様が提供する地図サービス [「YOLP」(Yahoo! Open Local Platform)](https://developer.yahoo.co.jp/webapi/map/) を利用しました。

が、Google Map APIに比べて、YOLPの情報が少ないように感じました。

これからYahoo! Japan の地図サービスを使う方向けに、YOLPの利用方法を、簡単なメモとしてまとめて公開しておきます。

※主に、ウェブアプリ向けの[「Yahoo! JavaScriptマップAPI」](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/) についての記述となります。

# YOLPとは
Yahoo! Open Local Platform　の略称。

https://developer.yahoo.co.jp/webapi/map/

Yahoo! JAPANがデベロッパー向けに提供する地図・地域情報のAPI・SDK
JavaScript のAPIの他に、iOS・Andoroid 向けのSDKが存在する。

# YOLPの利用制限

1つのAPIキーに付き5万回/1日。

https://developer.yahoo.co.jp/appendix/rate.html

毎日午前０時にリセット。
5万回を超えると、403エラーが返される。

# APIキーの取得

手順はこちら
https://developer.yahoo.co.jp/start/

最初に Yahoo! Japan のアカウントを取得する必要がある。
アカウント取得後、アプリケーション作成。
https://e.developer.yahoo.co.jp/register

# 取得したキーの管理

取得したAPIキーは下記URLから管理する
https://e.developer.yahoo.co.jp/dashboard/


# 基本的な使い方

ドキュメントをもとに基本的な使い方をおさらい。
https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/#index1-2

* Yahoo! JavaScriptマップAPIへリンクを生成

```javascript

<script type="text/javascript" charset="utf-8" src="https://map.yahooapis.jp/js/V1/jsapi?appid=【アプリケーションID】"></script>
```

コンストラクタ「Y.map」を呼び出してインスタンスを生成

```javascript
  var ymap = new Y.Map("map");
```

緯度経度をインスタンスに渡して地図を生成する

```javascript
 ymap.drawMap(new Y.LatLng(35.66572, 139.73100), 17, Y.LayerSetId.NORMAL);
```

[「drawMap」](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/reference/YCore.html#drawMapMap
)メソッドを使って地図を生成する。Y.LatLngで緯度経度を受け渡す。
[ZoomLevel](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/#index2-5
)で、地図の縮尺を指定。
[LayerSetId](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/#index2-6) で、表示する地図の種類を指定する。


以下の種類が指定可能。

* Y.LayerSetId.NORMAL
    * 標準地図
* Y.LayerSetId.PHOTO
    * 航空写真
* Y.LayerSetId.B1
    * 地下街
* Y.LayerSetId.OSM
    * オープンストリートマップ(オプション指定が必要)
* Y.LayerSetId.EARTHQUAKEPHOTO
    * 震災後の航空写真

# 地図上にマーカーを表示する

コンストラクタ Y.marker に緯度経度情報を渡すことでマーカー表示が可能。

```javascript

window.onload = function(){
   var ymap = new Y.Map("map");
   ymap.drawMap(new Y.LatLng(35.66572, 139.73100), 17, Y.LayerSetId.NORMAL);
   var marker = new Y.Marker(new Y.LatLng(35.66572,139.73100));
   ymap.addFeature(marker);
}
```


## 動作サンプル

[地図上にマーカーを表示](https://codepen.io/TakeshiNickOsanai/pen/zYOrJdR
)

![yolp_sample_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83767/dfbee73b-3c87-14fd-2f51-7e381d62500f.jpeg)


# 複数のマーカーを表示する

緯度経度の情報を配列にしてわたす。

* 複数マーカーの緯度情報を配列として変数に格納
* ymapインスタンスにaddFeaturesで渡す

複数マーカーを表示する場合「addFeature」ではなく[「addFeatures」](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/reference/YCore.html#addFeaturesMap)というメソッドを使う必要があるようだ。

```javascript
window.onload = function(){
   var ymap = new Y.Map("map");
   ymap.drawMap(new Y.LatLng(35.66572, 139.73100), 17, Y.LayerSetId.NORMAL);
   var marker = [];
   marker.push(new Y.Marker(new Y.LatLng(35.66572,139.73100)));
   marker.push(new Y.Marker(new Y.LatLng(35.6662186,139.7303961)));
   ymap.addFeatures(marker);
}

```


## 動作サンプル

[地図上に複数のマーカーを表示](https://codepen.io/TakeshiNickOsanai/pen/mdbVGGb)

![yolp_sample_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83767/6f4ef1eb-0737-d61d-6a55-6756e5cdcee3.jpeg)



# マーカーの画像を変える

Y.Iconで、マーカーに使いたい画像を指定。
Y.Marker　でマーカーの位置情報を指定するときに、アイコン情報をオブジェクトの引数として渡す。

```javascript
   var ymap = new Y.Map("map");
   ymap.drawMap(new Y.LatLng(35.66572, 139.73100), 17, Y.LayerSetId.NORMAL);
  var markerimg = new Y.Icon('https://s.yimg.jp/images/map/yy/images/icon/yy_aicon_06_32pix.gif');
   var marker = new Y.Marker(new Y.LatLng(35.66572,139.73100), {icon: markerimg});
   ymap.addFeature(marker);
```

## 動作サンプル

[マーカーの画像を変える](https://codepen.io/TakeshiNickOsanai/pen/gOYPdBp)

![yolp_sample_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83767/4fb2a6a9-ec7d-f38e-7ef5-86d0b1eca1f3.jpeg)


# マーカーをクリックすると、任意のリンク先に移動する

[bindメソッド](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/#index7
) を使って、マーカーをクリックしたときの振る舞いを関数として指定する。

```javascript
   var marker = new Y.Marker(new Y.LatLng(35.66572,139.73100));
   marker.bind('click', function(){
       location.href = "https://about.yahoo.co.jp/";
      }
   );
   ymap.addFeature(marker);
```

## 動作サンプル

[マーカーにリンクをバインド](https://codepen.io/TakeshiNickOsanai/pen/BaBjOEz)
 

# 縮尺コントロールボタンや中心マーカーを表示する

[Y.Map.addControl](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/#index3-2) で、追加したいコントローラーを指定する。

例：
・地図の中心地にマーカー
・距離の目安となるスケールバー
・縮尺をコントロールするスライダー

を表示する場合

```javascript

  ymap.addControl(new Y.CenterMarkControl());
  ymap.addControl(new Y.ScaleControl());
  ymap.addControl(new Y.SliderZoomControlVertical());
```

と指定する。


## 動作サンプル

[地図上にコントローラーを表示](https://codepen.io/TakeshiNickOsanai/pen/VwZeEZZ)

![yolp_sample_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83767/f681accf-8303-2d5f-348d-9bcf140b6a92.jpeg)


# 現在地の情報を取得して地図を表示する

HTML5 の [GeoLocation API](https://developer.mozilla.org/ja/docs/Web/API/Geolocation/Using_geolocation) を利用して、現在地の緯度経度を取得後、YOLPのインスタンスに渡す。

```javascript
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        function(position) {
          var lat = position.coords.latitude;
          var long = position.coords.longitude;
          ymap.drawMap(new Y.LatLng(lat, long), 17, Y.LayerSetId.NORMAL);
        },
        function(position) {
          alert("現在地の取得ができませんでした。");
        })
    }
```

## 動作サンプル

[現在地情報を取得して地図を再描画する](https://codepen.io/TakeshiNickOsanai/pen/jONqGrL)

# 複数のマーカーを表示して、クリックしたら関数を呼び出す

複数マーカーに何か特定の値を設定し、クリックしたら関数を呼び出して、その値をごにょごにょしたい。

例として
- クリックしたらマーカー地点の詳しい説明を表示する
- クリックしたら関連URLに移動する

など。

```javascript
window.onload = function(){
   var ymap = new Y.Map("map");
   alertLABEL = function(){
     alert(this.__label__);
   };

   ymap.bind('load', function(){
       var contents = [
               {lat:35.66497038132953, lng:139.7285538253784, label:'アトラスタワー六本木'},
               {lat:35.66648704437695, lng:139.73132186508175, label:'ザ・リッツ・カールトン東京'}
           ];
       var marker = '';
       for(i = 0; i < contents.length; i++){
           marker = new Y.Marker(new Y.LatLng(contents[i].lat, contents[i].lng));
           marker.__label__ = contents[i].label;
           marker.bind('click', alertLABEL);
           ymap.addFeature(marker);
       }
   });

   ymap.drawMap(new Y.LatLng(35.66572, 139.73100), 17, Y.LayerSetId.NORMAL);

```


サンプルでは alert を呼び出して、各マーカーにバインドした label を表示している。

- 配列 「contents」 を定義
- 配列数だけ for を回す
- marker に緯度軽度、マーカーのラベル名、マーカークリック時に実行する関数を定義

を行なった。

クリック時の振る舞いは「alertLABEL」に関数として定義。

関数の中身を変更すれば、任意の挙動を設定できる。


## 動作サンプル

[複数マーカーに対してクリック時の動作をバインドする](https://codepen.io/TakeshiNickOsanai/pen/poogXEN)

# コントローラーの表示位置を調整する

YOLPが用意している検索窓や縮尺コントローラーをそのまま使うと、コントローラー同士が重なり合って使いづらい場合がある。

その様な場合は[「ControlPosition」](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/reference/YControl.html#ControlPosition)で表示位置を調整する。

例として、検索窓を表示したい時。初期状態では地図の左上に表示されるが、位置を右上に調整したい場合

```javascript
   ymap.addControl(new Y.SearchControl(),new Y.ControlPosition(Y.ControlPosition.TOP_RIGHT));
```

と指定する。

## 動作サンプル

[コントロールの表示位置を調整する](https://codepen.io/TakeshiNickOsanai/pen/YzzwoOo)

<img width="658" alt="YOLP_SAMPLE_8.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83767/49c73807-cc50-ab38-f1d8-efa118c06731.jpeg">


サンプルでは、検索窓を右上、縮尺スケールを左下に表示して、コントローラー同士が重ならない様に調整している

# 地図をドラッグ移動後、中心点の緯度経度を表示する

イベントクラス[「dragend」](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/sl/reference/symbols/Event.html#11MapEvents)を使う。

YOLPのインスタンスに「dragend」をバインドして、イベントが発生したら＝地図のドラッグ移動が終了したら、中心地の緯度経度を取得する。

```javascript
ymap.bind('dragend',function(){
    //地図のドラッグが終わったら中心点の緯度経度を表示する

       var center = ymap.getCenter();
       console.log(center);
});
```

## 動作サンプル

[地図をドラッグ移動後、中心点の緯度経度を表示](https://codepen.io/TakeshiNickOsanai/pen/wvvJJjb)