正直よくわかっていなくても短時間でそれっぽい地図アプリケーションが作れる


##開発できた地図を操作するWEBアプリケーション
将来開発したいサービスがあり、その実現性を確かめるべくスピード重視でプロト開発してみました。
完成品をNetlifyで公開していますので触ってみてください↓

https://agitated-mahavira-7d1166.netlify.app/

参考）将来開発したいと思っているもの（note記事に飛びます）
https://note.com/grayhamchan/n/ne9e12909f60d
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365273/4e1c8609-990a-e526-a2fd-5858907ce470.png">

##確認したかった機能
* ブラウザに地図を表示する
* 現在地を地図上にプロットする
* ほかの任意の地点を地図上にプロットする
* 2点間の距離を計算する

これらの機能が初心者でも実装できるのか？確認してみました

##結論：ライブラリを活用することで簡単にそれっぽいものが作れた
* 地図サービス
    * **OpenStreetMap**というサービスを利用しました
    * なじみのあるGoogleMapはクレジット登録やAPIキーの取得が必要なため、お試しには不向きと判断しました
    * http://openstreetmap.org
* 地図を操作するライブラリ
    * OpenStreetMapが提供する地図データを**Leaflet**という地図ライブラリで操作しました
    * こちらのサイト様がとても参考になりました。Leafletのカテゴリを参照ください
    * https://kita-note.com/
* 2点間の距離を計算するライブラリ
    * **Geolib**というライブラリを利用しました
    * こちらのサイト様がとても参考になりました
    * https://www.mmpp.org/archives/1663

##ポイント：地図データと操作ライブラリを組み合わせることで1つの地図アプリを作る
これがポイントと思いました
このようなイメージです
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365273/05b41192-e74c-a3df-d4af-d8133651392c.png">
このほかにも、**ルートを検索するライブラリ**など拡張機能がたくさん公開されていますので、必要に応じてそれらを追加することでより高機能な地図アプリを作ることができるようです

##ソースコード
参考にさせていただいたサンプルコードを切った貼ったしたものなので正解ではないですがとりあえず動作します。

<details><summary>HTML</summary><div>

```html:index.html
<!DOCTYPE html>
<html lang="jp" >
<head>
  <meta charset="UTF-8">
  <title>ハム旅シミュレータ</title>
  <meta name="viewport" content="width=device-width, initial-scale=1"><link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css'><link rel="stylesheet" href="./style.css">

</head>
<body>
<!-- partial:index.partial.html -->
<script src="https://cdn.jsdelivr.net/npm/geolib@3.3.1/lib/index.min.js"></script>

    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="">
    <script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>
<style type="text/css">
     <!--
      #mapid { height: 300px; width: 400px}
    -->
</style>
<div class="container text-center">
  <div class ="row">
    <div class="col-sm-6">
      <H2>ハム旅シミュレーター</H2>
      <H5>ディズニーランドでハム会あるってよ！</H5>
      <IMG SRC="https://hamimg.png" width="100" height="100" >
        <P>ハムちゃんが直径21cmの回し車を1回転させると「約66cm」走った事になります。<B><U>ハム旅シミュレータ</U></B>は、これをもとに現在地からディズニーランドまでの道のりを<B><U>ハムちゃんが走っていくと仮定</U></B>し、次の項目をシミュレーションするWEBアプリケーションです。<BR><BR>
          🐹今いるところからディズニーランドまでの距離<BR>
          🐹回し車を何回くらい回せば到着するか？<BR>
          🐹到着まで何日くらいかかるか？<BR><BR>
        
          その姿を勝手に妄想することで<B>ハム愛がさらに深まる</B>効果が期待できます。<BR>
        
      </P>
    </DIV>
  </div>

  <div class ="row">
    <div class="col-sm-6">
    使い方１．ディズニーランドはどこかな？地図を縮小して確認しよう<BR>
      <Font size="-4">※ディズニーランドまでの距離を計算するために、位置情報にアクセスします。<BR>位置情報サービスを有効・許可してください。位置情報は距離計算以外には利用いたしません</Font>
      
    </div>
  </div>
  <div class ="row">
    <div class="col-sm-6">
      <div id="mapid"></div><BR>
    </div>
  </div>
  <div class ="row">
    <div class="col-sm-6">
      使い方２．ハム足で走っていったらどれくらいかかるのか確認しよう。<BR>ボタンをクリックしてね
      <div class="hidden_box">
        <label for="label1">クリックして計算結果を確認</label>
        <input type="checkbox" id="label1"/>
        <div class="hidden_show">
          <!--非表示ここから--> 
              東京ディズニーランドまでの道のりは....<div id="kyori"><p></p></div>
              回し車を....<B><U><div id="mawasu"><p></p></div></U></B>まわすと到着する距離です！<BR>
              ハムスターは私たちが寝ている間に、10Km程度走るといわれていますので<BR>
          <B><U><div id="days"><p></p></div></U></B>しているようですよ。がんばれハムちゃん！！<BR>
              <IMG SRC="https://user-images.githubusercontent.com/82483123/119250743-2225c800-bbdd-11eb-824b-68d634746f38.png" Width = "200" Height = "180">
              <BR><BR>Powered by HPF
          <!--ここまで-->
        </div>
      </div>
    </div>
</div>
<!-- partial -->
  <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.1/js/bootstrap.min.js'></script><script  src="./script.js"></script>

</body>
</html>
```
</div></details>

<details><summary>CSS</summary><div>

```css:style.css
.mapid {
  position: absolute;
  width: 400px;
  height: 300px;
}

/*全体*/
.hidden_box {
    margin: 2em 0;/*前後の余白*/
    padding: 0;
}

/*ボタン装飾*/
.hidden_box label {
  position: relative;
  display: inline-block;
  padding: 0.25em 0.5em;
  text-decoration: none;
  color: #FFF;
  background: #fd9535;/*背景色*/
  border-bottom: solid 2px #d27d00;/*少し濃い目の色に*/
  border-radius: 4px;/*角の丸み*/
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.2), 0 2px 2px rgba(0, 0, 0, 0.19);
  font-weight: bold;
}

/*ボタンホバー時*/
.hidden_box label:hover {
  position: relative;
  display: inline-block;
  padding: 0.25em 0.5em;
  text-decoration: none;
  color: #FFF;
  background: #fd9535;/*色*/
  border-radius: 4px;/*角の丸み*/
  box-shadow: inset 0 2px 0 rgba(255,255,255,0.2), inset 0 -2px 0 rgba(0, 0, 0, 0.05);
  font-weight: bold;
  border: solid 2px #d27d00;/*線色*/
}

/*チェックは見えなくする*/
.hidden_box input {
    display: none;
}

/*中身を非表示にしておく*/
.hidden_box .hidden_show {
    height: 0;
    padding: 0;
    overflow: hidden;
    opacity: 0;
    transition: 0.8s;
}

/*クリックで中身表示*/
.hidden_box input:checked ~ .hidden_show {
    padding: 10px 0;
    height: auto;
    opacity: 1;
}
```
</div></details>

<details><summary>JavaScript</summary><div>

```javascript:script.js
//GPSで位置情報を取得
navigator.geolocation.getCurrentPosition(successCallback, errorCallback);

function successCallback(position) {
//geolibで距離を計測
  let distance =  geolib.getDistance(
    {latitude: position.coords.latitude, longitude: position.coords.longitude},	//自分
    {latitude: 35.6261554, longitude: 139.884501}	//ディズニーランド               
  );
      
  console.log(distance);
  document.getElementById( 'kyori' ).innerHTML = '約' + distance / 1000 + 'キロメートル';
  document.getElementById( 'mawasu' ).innerHTML =  Math.floor(distance * 100 / 66) + '回くらい'; //1回転で66cm計算 
  document.getElementById( 'days' ).innerHTML =  Math.ceil(distance / 1000 / 10) + '日後の朝には到着';
  
  var mymap = L.map('mapid');
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 18 ,
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, '
  }).addTo(mymap);
 
  function onLocationFound(e) {
    L.marker(e.latlng).addTo(mymap).bindPopup("🐹いっくよー！<BR>ディズニーランドが見えるまで左の「-」ボタンをクリックしてね").openPopup();
   }
 
  function onLocationError(e) {
    alert("現在地を取得できませんでした。" + e.message);
  }
 
  mymap.on('locationfound', onLocationFound);
  mymap.on('locationerror', onLocationError);
  mymap.locate({setView: true, maxZoom: 16, timeout: 20000});
  var disneymarker = L.marker([35.6261554, 139.884501]).addTo(mymap);
  disneymarker.bindPopup("<p>東京でぃずにぃらんど🐭</p>").openPopup();
  
}
      
function errorCallback(error) {
//エラー時
  
}
```
</div></details>

##正直よくわかってなくても短時間でそれっぽい地図アプリケーションが作れる
プロトタイプレベルであればあっという間に作れてしまいますね。すごい世の中になったものです。