Kotlinで地図アプリ（ゴミ拾いアプリ）作成。（10日目）


Kotlinで制作している、GoogleMapを使った、自作のゴミ拾いアプリ。制作10日目。

Kotlin + PHP + MySQLで、スマホアプリから、データベースへの位置情報の記録までできるようになったので、今日は、HTML + CSS + JavaScript + GoogleMap APIで、地図を表示してマーカーを複数表示できるまでやってみました。



#VSCodeの環境作成

JavaScriptでGoogleMapを使う前に、VScodeの環境を見直し。

参考サイト：

https://uetani33.net/vscode-web-extensions/


#JavaScriptからGoogleMAPを表示

前回の記事で、JavaScriptからGoogleMAP APIを使って地図の表示に失敗してましたが、本日、表示できるようになりました。

サーバ上にアップせず、ローカル環境でテストしてます。
動かなかった原因は、単純な記述ミスだったのかもしれません。

![イメージ7464.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/73a4cf2e-8aba-f63d-7c52-a223a77f6690.jpeg)

Maps JavaScript APIのリクエスト数も増加
![イメージ7465.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/6b4dafd1-ca97-345c-41b6-e11bb8fa6591.jpeg)



参考サイト：

https://mono96.jp/wordpress/know-how-wordpress/43336/



##注意点

コードをそのまま貼り付けると動かないので「&amp;amp;」のところを、「&」へ変更。
その他、外部CSSを使わず、HTMLのみで完結するように変更して、分かりやすいように、バックにオレンジ色を追加。


```html:GoogleMapAPI-TEST-01.html
<script async="" src="https://maps.googleapis.com/maps/api/js?key=（GoogleMAP API）&callback=initMap"></script>
<script>
  function initMap() {
    var mapPosition = new google.maps.LatLng( 35.69681563029324, 139.7851593285365 );//緯度経度
    var map = new google.maps.Map(document.getElementById('gmap'), {
      zoom: 20,
      center: mapPosition
    });
    var marker = new google.maps.Marker({
    position: mapPosition,
    map: map
    });
  }
</script>
<div id="gmap" style="width:600px; height:400px; background-color:orange"></div>
```

「&callback=initMap」という所が、ポイントみたいです。

参考サイト：

https://www.javadrive.jp/google-maps-javascript/charset/index6.html


実行後、オレンジ色で表示される部分に地図が表示されれば成功。
地図が表示されない場合は、APIキーの記述ミスか、Google Maps Platformの設定ミス？


漸く、スタートラインに立てました。


#Markerのアイコンを変更

動くようになったので、早速、カスタムしてみます。

とりあえず、マーカーアイコンを、別の画像に差し替え。


```html:GoogleMapAPI-TEST-02.html
<script>
  function initMap() {
    ...
    var marker = new google.maps.Marker({
      position: mapPosition,
      map: map,
      icon: {
        url: 'gomi01.png',                      //アイコンのURL
        scaledSize: new google.maps.Size(40, 40) //サイズ
      }
    });
    ...
```

アイコン表示
![イメージ7466.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/3bd8a6d9-f940-408e-18a9-3381d232d01d.jpeg)


参考サイト：

https://developers.google.com/maps/documentation/javascript/markers

https://maps.multisoup.co.jp/blog/1881/


#複数のマーカーを表示

```html:GoogleMapAPI-TEST-03.html
<script async="" src="https://maps.googleapis.com/maps/api/js?key=（GoogleMAP API）&callback=initMap"></script>
<script>
  function initMap() {
    var mapMainPosition = new google.maps.LatLng(35.71, 139.83);

    var data = new Array();
    data.push({position: new google.maps.LatLng(35.697745, 139.826395), content: 'ゴミ（小）',icon: 'gomi01.png'},);
    data.push({position: new google.maps.LatLng(35.700295, 139.833692), content: 'ゴミ（中）',icon: 'gomi02.png'},);
    data.push({position: new google.maps.LatLng(35.707055, 139.831897), content: 'ゴミ（大）',icon: 'gomi03.png'},);
    data.push({position: new google.maps.LatLng(35.710127, 139.828033), content: 'ゴミ（小）',icon: 'gomi01.png'},);
    data.push({position: new google.maps.LatLng(35.717753, 139.816786), content: 'ゴミ（中）',icon: 'gomi02.png'});

    var map = new google.maps.Map(document.getElementById('gmap'), {
      zoom: 14,
      center: mapMainPosition,
    });
    
    for (i = 0; i < data.length; i++) {
      var myMarker = new google.maps.Marker({
        position: data[i].position,
        map: map,
        icon: {
          url: data[i].icon,
          scaledSize: new google.maps.Size(40, 40)
        }
      });
  }
</script>
<div id="gmap" style="width:600px; height:400px; background-color:orange"></div>
```
![イメージ7468.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/28cfa280-bbae-761d-25f5-423e8856e980.jpeg)


#複数のマーカーを表示（吹き出しあり）


```html:GoogleMapAPI-TEST-04.html
<script async="" src="https://maps.googleapis.com/maps/api/js?key=（GoogleMAP API）&callback=initMap"></script>
<script>
  function initMap() {
    var mapMainPosition = new google.maps.LatLng(35.71, 139.83);

    var data = new Array();
    data.push({position: new google.maps.LatLng(35.697745, 139.826395), content: 'ゴミ（小）',icon: 'gomi01.png'},);
    data.push({position: new google.maps.LatLng(35.700295, 139.833692), content: 'ゴミ（中）',icon: 'gomi02.png'},);
    data.push({position: new google.maps.LatLng(35.707055, 139.831897), content: 'ゴミ（大）',icon: 'gomi03.png'},);
    data.push({position: new google.maps.LatLng(35.710127, 139.828033), content: 'ゴミ（小）',icon: 'gomi01.png'},);
    data.push({position: new google.maps.LatLng(35.717753, 139.816786), content: 'ゴミ（中）',icon: 'gomi02.png'});

    var map = new google.maps.Map(document.getElementById('gmap'), {
      zoom: 14,
      center: mapMainPosition,
      scrollwheel: false,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    
    for (i = 0; i < data.length; i++) {
      var myMarker = new google.maps.Marker({
        position: data[i].position,
        map: map,
        icon: {
          url: data[i].icon,
          scaledSize: new google.maps.Size(40, 40)
        }
      });
      attachMessage(myMarker, data[i].content);
    }
  }

  function attachMessage(marker, msg) {
    google.maps.event.addListener(marker, 'click', function(event) {
      new google.maps.InfoWindow({
        content: msg
      }).open(marker.getMap(), marker);
    });
  }
</script>
<div id="gmap" style="width:600px; height:400px; background-color:orange"></div>
```

![イメージ7469.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/7a2f0ac9-e1ff-ef20-53de-0d7d0decfe6f.jpeg)




こうすると動かないようです。（要クロージャー？）


```html:GoogleMapAPI-TEST-05.html
<script async="" src="https://maps.googleapis.com/maps/api/js?key=（GoogleMAP API）&callback=initMap"></script>
<script>
  function initMap() {
    var mapMainPosition = new google.maps.LatLng(35.71, 139.83);
    var data = new Array();
    data.push({position: new google.maps.LatLng(35.697745, 139.826395), content: 'ゴミ（小）',icon: 'gomi01.png'},);
    data.push({position: new google.maps.LatLng(35.700295, 139.833692), content: 'ゴミ（中）',icon: 'gomi02.png'},);
    data.push({position: new google.maps.LatLng(35.707055, 139.831897), content: 'ゴミ（大）',icon: 'gomi03.png'},);
    data.push({position: new google.maps.LatLng(35.710127, 139.828033), content: 'ゴミ（小）',icon: 'gomi01.png'},);
    data.push({position: new google.maps.LatLng(35.717753, 139.816786), content: 'ゴミ（中）',icon: 'gomi02.png'});

    var map = new google.maps.Map(document.getElementById('gmap'), {
      zoom: 14,
      center: mapMainPosition,
      scrollwheel: false,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    for (i = 0; i < data.length; i++) {
      var myMarker = new google.maps.Marker({
        position: data[i].position,
        map: map,
        icon: {
          url: data[i].icon,
          scaledSize: new google.maps.Size(40, 40)
        }
      });

      google.maps.event.addListener(myMarker, 'click', function(event) {
        var m = data[i].content;
        new google.maps.InfoWindow({
          content: data[i].content,
        }).open(myMarker.getMap(), myMarker);
      });
    }
  }
</script>
<div id="gmap" style="width:600px; height:400px; background-color:orange"></div>
```



参考サイト：

https://qiita.com/takeharu/items/4975031faf6f7baf077a

https://www.nanchatte.com/map/showDifferentInfoWindowOnEachMarker.html


#まとめ

なんとかJavaScriptでGoogleMAPを表示できるようになり、マーカーの表示や、複数配置等、できるようになりました。

次の課題としては、MySQLサーバーから位置情報を取得して表示するなど。
それに伴い、Node.jsなど使う事になりそうです。


#今後、問題になりそうな事

参考サイト：

https://teratail.com/questions/69050

大量のマーカーを表示する場合、クライアント側のパフォーマンスが求められるようです。

その他、上記のサイトから引用：

>Marker Clustererのような、複数のピンを1つに集めてしまうライブラリがあるので、そういうのを使うのが適当ではないかと思います（もっとも、これにしても、万単位の表示に対応しようと思ったらチューニングが必要となりました）。

更に

>大量マーカーの配置については「マーカークラスタリング」という機能が用意されています。
「密集しているところはまとめて表示しよう」というものです。
私自身はまだ試したことはないですが、良い案だと思います。
>
>【Marker Clustering】
>https://developers.google.com/maps/documentation/javascript/marker-clustering
>
>【google maps javascript API v3 で大量のマーカーを制御する・まとめる（クラスタリング）】
>http://blog.aquaring.co.jp/1328

その他


>GoogleAPI (v3.x) で大量のマーカーを扱う方法が紹介されたブログがあります。
>
>http://blog.aquaring.co.jp/1328

個人用なので、そんなに大量のマーカーを表示することは無さそうですが、情報として知っておいて損は無さそうです。