【Google MAP】2点間orクリックによる多地点間の距離を取得する(直線距離)

# はじめに
GoogleMAPで距離を知りたい、ということはよくあります。普通に、GoogleMAPで「出発地」「目的地」「移動手段」を入力すれば、簡単にルートと距離を知ることができます（本当に素晴らしい時代です）

基本的にはそれで事足りてしまうのですが、自分でさっとクリックやドラックで地点を指定し、直線距離でだいたいどのくらい、と知りたいことがたまにあったりします。

そこで、GoogleMapsAPIを使用して、直線距離ではどのくらいなのかを求めたいと思います。その次にルートを考慮して距離を求めていきたいと思いますので、その第1段階となります。

基本的に参考にするのは、Google Developersです。

https://developers-jp.googleblog.com/2019/12/how-calculate-distances-map-maps-javascript-api.html

距離の計算について難しいことはわからなくても、参考サイトを見ながら簡単にできます。初学者にはとてもありがたいです。

# 作成するもの
- 【プログラム1】 2地点間の距離を計算し表示します。マーカーは2つ表示。2つのマーカーはドラック可能で、移動した際には、距離を再計算させるようにします。

- 【プログラム2】 クリックにより指定した(最大10カ所まで可能)多地点間の距離を求めます(直線距離)


# プログラム1
[デモサイト](https://anotherskyjp.site/devapps/googlemapdev/calc_2distance.html)

![Screenshot_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/ff0aa884-03a2-55f8-3838-1e8e36a05880.png)



# プログラム1 - コード

距離の計算については参考サイトのままです。
```googlemap_sample1.html
  <script>
  // 距離計算関数
    function calc_distance(LAT1, LNG1, LAT2, LNG2) {
      var R = 6371.0710;
      var rlat1 = LAT1 * (Math.PI/180);
      var rlat2 = LAT2 * (Math.PI/180);
      var difflat = rlat2 - rlat1;   // Radian difference (latitudes)
      var difflon = (LNG2 - LNG1) * (Math.PI/180); // Radian difference (longitudes)
      var d = 2 * R * Math.asin(Math.sqrt(Math.sin(difflat/2) * Math.sin(difflat/2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.sin(difflon/2) * Math.sin(difflon/2)));
      return d;
    }
  </script>
```

<details><summary>全体のコード</summary>
<div>

```googlemap_sample1.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>Google Maps Distance</title>
    <meta charset="utf-8">
    <style>
        /* 省略 */
    </style>
  </head>
  <body>
      <p>【位置1】緯度:<input type="text" id="lat-1"> 経度:<input type="text" id="lng-1"></p>
      <p>【位置2】緯度:<input type="text" id="lat-2"> 経度:<input type="text" id="lng-2"></p>
      <p>【計算結果表示】<span id="dist"></span>km</p>
      <div id="map"></div>

      <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=YOURAPI&callback=initMap" async defer></script>

      <script>
        var map;
        function initMap() {

          // マップ初期表示
          map = new google.maps.Map(document.getElementById("map"), {
            center: {lat: 35.681167, lng: 139.767052},
            zoom: 6,
            scaleControl: true
          });

          // 初期値位置定数
          var LAT1 = 35.67224257810213;
          var LNG1 = 139.8000109843750;
          var LAT2 = 34.68448757518170;
          var LNG2 = 135.5153430156250;

          // 初期位置表示
          document.getElementById('lat-1').value = LAT1;
          document.getElementById('lng-1').value = LNG1;
          document.getElementById('lat-2').value = LAT2;
          document.getElementById('lng-2').value = LNG2;

          var place1 = new google.maps.LatLng(LAT1, LNG1);
          var place2 = new google.maps.LatLng(LAT2, LNG2);

          // ドラックできるマーカーの表示
          marker1 = new google.maps.Marker({
            position: place1,
            map: map,
            draggable: true,
            title: "位置1",
            label: "1"
          });

          marker2 = new google.maps.Marker({
            position: place2,
            map: map,
            draggable: true,
            title: "位置2",
            label: "2"
          });

          // 2点を結ぶ線を表示
          polyline(place1, place2);

          // 距離計算
          var distance = calc_distance(LAT1, LNG1, LAT2, LNG2);

          // 計算結果表示
          document.getElementById('dist').innerHTML = distance.toFixed(2);

          // マーカーのドロップ（ドラッグ終了）時のイベント
          google.maps.event.addListener(marker1, 'dragend', function(e){

            // 緯度・経度取得
            var LAT1 = e.latLng.lat();
            var LNG1 = e.latLng.lng();
            var LAT2 = document.getElementById('lat-2').value;
            var LNG2 = document.getElementById('lng-2').value;
            document.getElementById('lat-1').value = LAT1.toFixed(8);
            document.getElementById('lng-1').value = LNG1.toFixed(8);

            display_calc(LAT1, LNG1, LAT2, LNG2);

          });

          google.maps.event.addListener(marker2, 'dragend', function(e){

            // 緯度・経度取得
            var LAT1 = document.getElementById('lat-1').value;
            var LNG1 = document.getElementById('lng-1').value;
            var LAT2 = e.latLng.lat();
            var LNG2 = e.latLng.lng();
            document.getElementById('lat-2').value = LAT2.toFixed(8);
            document.getElementById('lng-2').value = LNG2.toFixed(8);

            display_calc(LAT1, LNG1, LAT2, LNG2);

          });
        }

        // 距離計算関数
        function calc_distance(LAT1, LNG1, LAT2, LNG2) {
          var R = 6371.0710;
          var rlat1 = LAT1 * (Math.PI/180);
          var rlat2 = LAT2 * (Math.PI/180);
          var difflat = rlat2 - rlat1;   // Radian difference (latitudes)
          var difflon = (LNG2 - LNG1) * (Math.PI/180); // Radian difference (longitudes)
          var d = 2 * R * Math.asin(Math.sqrt(Math.sin(difflat/2) * Math.sin(difflat/2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.sin(difflon/2) * Math.sin(difflon/2)));
          return d;
        }

        // 2点を結ぶ線を表示関数
        function polyline(latlng1, latlng2) {
          line = new google.maps.Polyline({
            path: [latlng1, latlng2],
            map: map,
            strokeColor: "red",
            strokeOpacity: 0.7,
            strokeWeight: 3
          });
        }

        // ドラック後の再表示と再計算関数
        function display_calc(LAT1, LNG1, LAT2, LNG2) {
          // 線を消去
          line.setMap(null);
          var mk1 = new google.maps.LatLng(LAT1, LNG1);
          var mk2 = new google.maps.LatLng(LAT2, LNG2);
          // 2点を結ぶ線を表示
          polyline(mk1, mk2);
          // 距離計算
          var distance = calc_distance(LAT1, LNG1, LAT2, LNG2);
          // 計算結果表示
          document.getElementById('dist').innerHTML = distance.toFixed(2);
        }

      </script>
    </body>
  </html>
```

</div></details>


# プログラム2
[デモサイト](https://anotherskyjp.site/devapps/googlemapdev/calc_click_distance.html)

![Screenshot_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/b3c59fab-8e44-c909-0a0c-69aa4419bf26.png)

# プログラム2 - コード

<details><summary>全体のコード</summary>
<div>

```googlemap_sample2.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>Google Maps Distance</title>
    <meta charset="utf-8">
    <style>
      #map {
        height: 900px;
        width: 1200px;
      }
    </style>
  </head>

    <body>

      <p>【計算結果表示】<span id="dist"></span>km  <span><button id="clear">クリア</button></span></p>

      <div id="map"></div>

      <script src="https://maps.googleapis.com/maps/api/js?language=ja&region=JP&key=YOURAIPKEY&callback=initMap" async defer></script>

      <script>

        var map;
        var markerPts = [];
        var lines = [];
        var distSum = 0;

        function initMap() {

          // マップ初期表示
          map = new google.maps.Map(document.getElementById("map"), {
            center: {lat: 35.681167, lng: 139.767052},
            zoom: 10,
            scaleControl: true
          });

          // マップクリック時イベント
          google.maps.event.addListener(map, 'click', function(e) {
            addMarker(e.latLng);
          });

          // 結果クリアーボタン押下時イベント
          document.getElementById('clear').addEventListener('click', function() {
            reset();
          });

        }

        function addMarker(latlng) {

          // 地点は10箇所まで
          if (markerPts.length < 10) {

            var markerPt = new google.maps.Marker({
              position: latlng,
              draggable: true,
              label: String(markerPts.length),
              map: map
            })

            markerPts.push(markerPt);

            calcResult();

          } else {
            alert("マーカーセットは10カ所まで可能です");
          }

        };

        // 距離計算と線を引く
        function calcResult() {

          if (markerPts.length > 1) {

            distSum = 0;

            for (i = 1; i < markerPts.length; i++) {

              n = i - 1;

              var LAT1 = markerPts[n].position.lat();
              var LNG1 = markerPts[n].position.lng();
              var LAT2 = markerPts[i].position.lat();
              var LNG2 = markerPts[i].position.lng();

              var distance = calc_distance(LAT1, LNG1, LAT2, LNG2);
              distSum += distance;

            }

            document.getElementById('dist').innerHTML = "距離: " + distSum.toFixed(2);

            var lat_lng_1 = new google.maps.LatLng(LAT1, LNG1);
            var lat_lng_2 = new google.maps.LatLng(LAT2, LNG2);
            polyline(lat_lng_1, lat_lng_2);

          }

        };

        // 距離計算関数
        function calc_distance(LAT1, LNG1, LAT2, LNG2) {

          var R = 6371.0710;

          var rlat1 = LAT1 * (Math.PI/180);
          var rlat2 = LAT2 * (Math.PI/180);

          var difflat = rlat2 - rlat1;   // Radian difference (latitudes)
          var difflon = (LNG2 - LNG1) * (Math.PI/180); // Radian difference (longitudes)

          var d = 2 * R * Math.asin(Math.sqrt(Math.sin(difflat/2) * Math.sin(difflat/2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.sin(difflon/2) * Math.sin(difflon/2)));

          return d;

        }

        // 2点を結ぶ線を表示関数
        function polyline(latlng1, latlng2) {

          var line = new google.maps.Polyline({
            path: [latlng1, latlng2],
            map: map,
            strokeColor: "red",
            strokeOpacity: 0.7,
            strokeWeight: 3
          });

          lines.push(line);

        }

        // 結果リセット
        function reset() {

          for (var i in lines) {
            lines[i].setMap(null);
          }

          for (var i in markerPts) {
            markerPts[i].setMap(null);
          }

          markerPts = [];
          lines = [];
          distSum = 0;
          document.getElementById('dist').innerHTML = "";

        };

      </script>

    </body>
  </html>
```

</div></details>

# まとめ
- GoogleMapsAPIを使用して、2値点間or多地点間の直線距離を計算・表示することができました。
- GoogleMapsAPIを学ぶには、とてもよい題材ではないかと思いました。
- 次に、ルート(徒歩や自動車など)を考慮した多地点間の距離を求めて表示させていきたいと思います。

# 参考にしたサイト
- https://developers-jp.googleblog.com/2019/12/how-calculate-distances-map-maps-javascript-api.html
- https://www.nanchatte.com/map/computeDistance.html
- https://www.mk-mode.com/blog/2013/07/12/google-maps-api-calc-distance/