Google Maps APIを使ってみた

# GoogleMapsAPIとは

ご存知の方も多いと思いますが、あなたのオリジナルのWebサイトや、モバイルアプリにて、GoogleMapを埋め込むテクノロジーです。

今回は、オリジナルのマーカーをhtmlの地図上に表示したいので、javascriptで利用します。

まずはGoogleMapsPlatformに登録しましょう。

# 管理コンソール画面

まだkeyを作っていなければ、下記の赤枠から作成しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680908/231cdbca-b5f2-5968-a2ec-eb3a2d3dbb0b.png)

そうするとkey（長い英数字）が発行されるので、htmlファイルに埋め込んで利用します。

以下の公式ページに例がありますが、非常にシンプルです。

https://developers.google.com/maps/documentation/javascript/adding-a-google-map?_gl=1*2yeb4e*_up*MQ..*_ga*MjExMzUxMjk2Ny4xNzA5OTkwNjY1*_ga_NRWSTWS78N*MTcwOTk5MDY2NC4xLjAuMTcwOTk5MDgwMC4wLjAuMA..

地図を表示したい場所に、idがmapのdivタグを仕込みます。
```html
<div id="map"></div>
```

あとは、公式サイトで指定されている以下のコードをコピペで持ってきて、keyの値を、正しく書き換えます。
```javascript
<!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API... あとは長いので記載を省略します・・！")
        ({key: "ここに先ほどのkeyをセットする！", v: "weekly"});</script>
```


ここで指定するkeyは、htmlファイルやjsファイル上に記載する事になるので、一般の目に触れる事になります。keyが盗まれたりしないのでしょうか・・？

## keyの保護
以下のページにある通り、keyの不正利用を防ぐ仕組みがあります。

https://cloud.google.com/docs/authentication/api-keys?_gl=1*fcrsp6*_ga*MjU1OTMzMzM0LjE3MDQyOTE5NDc.*_ga_WH2QY8WWF5*MTcwOTk4OTk4Mi4yMy4xLjE3MDk5OTAzMjMuMC4wLjA.&_ga=2.114970820.-255933334.1704291947&hl=ja#securing

webからの利用であれば、googlemapを利用するWebサイトのドメインで規制したり（aaaa.bbb.comからのアクセスの時だけOKにしたいなど）、Webサイトが固定IPアドレスを持っていれば、それで規制することができます。

なかなか、面白い仕組みだなと感じました。

# GoogleMapsにあらかじめ用意されたデフォルトのマーカーの表示

（デフォルトのマーカーとは、よく見る以下のこと）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680908/cf88afd0-4d82-72c1-f75f-9b7f5bfc350b.png)


以下の公式ページを見れば、簡単に出来てしまいますが、

https://developers.google.com/maps/documentation/javascript/adding-a-google-map?_gl=1*2yeb4e*_up*MQ..*_ga*MjExMzUxMjk2Ny4xNzA5OTkwNjY1*_ga_NRWSTWS78N*MTcwOTk5MDY2NC4xLjAuMTcwOTk5MDgwMC4wLjAuMA..#map

コメントで解説します。（公式サイトからのコード丸写しで申し訳ない🙇‍♂️です）
```typescript
// GoogleMapオブジェクトを持っておく変数をここに定義しておく。
let map;
async function initMap(): Promise<void> {
  // マーカーを表示したい座標
  const position = { lat: -25.344, lng: 131.031 };

  // 事前にライブラリをインポートしておく。
  //@ts-ignore
  const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
  const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;

  // htmlに表示したmapを、javascript側の世界に呼び出す。
  map = new Map(
    document.getElementById('map') as HTMLElement,
    {
      zoom: 4,
      center: position,
      mapId: 'DEMO_MAP_ID',
    }
  );

  // マーカーオブジェクトをnewする際に、地図を指定する。
  const marker = new AdvancedMarkerElement({
    map: map, // 先ほど用意したmapオブジェクトをmapプロパティにセットする。
    position: position, // 先ほど用意した、マーカーを表示したい座標オブジェクトをセット。
    title: 'Uluru' // マーカーのタイトル
  });
}

initMap();
```

# オリジナルのマーカーを表示する

さて、いよいよオリジナルのマーカーを表示します。

公式サイトに例が載っています。

https://developers.google.com/maps/documentation/javascript/advanced-markers/graphic-markers?_gl=1*1t1npp1*_up*MQ..*_ga*NjQzNTY1NDQxLjE3MDk5OTE1MjU.*_ga_NRWSTWS78N*MTcwOTk5MTUyNS4xLjAuMTcwOTk5MTUyNS4wLjAuMA..

今回は、以下のようなマーカーを表示します。
<img width="50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680908/455744ba-5d7c-5e95-4a18-baa5e1383388.png" />

まずは、マーカーの描画のために必要な色などの情報を、別のjs(ts)ファイルで、一覧で定義しておきます。DBやconfigファイルなどに入れていても良いですね。
```typescript
/**
 * マーカーの種類
 */
const CategoryIdAndMarkerTypeDefMap: Map<number, IMarkerTypeDef> = new Map<number, IMarkerTypeDef>();
CategoryIdAndMarkerTypeDefMap.set(1, {iconKeyWord: "landscape", glyphColor: "#33cc00", bgColor: "#ccffcc"});
CategoryIdAndMarkerTypeDefMap.set(2, {iconKeyWord: "filter_vintage", glyphColor: "#ff0000", bgColor: "#ff99cc"});
CategoryIdAndMarkerTypeDefMap.set(3, {iconKeyWord: "local_cafe", glyphColor: "#663300", bgColor: "#ffcc99"});
CategoryIdAndMarkerTypeDefMap.set(4, {iconKeyWord: "temple_buddhist", glyphColor: "#6600ff", bgColor: "#cc99ff"});
```

先ほどのAdvanceMarkerElementには、contentというプロパティが存在します。

https://developers.google.com/maps/documentation/javascript/reference/advanced-markers#AdvancedMarkerElement.content

このプロパティに、オリジナルマーカーの情報を持たせたPinElementのオブジェクトをセットします。

```typescript
async createOriginalMarker(省略): Promise<google.maps.marker.AdvancedMarkerElement> {
    const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;
    // PinElementを作成し、
    let pinElement = await createPinElement(省略);
    
    return new AdvancedMarkerElement({
      position: position,
      content: pinElement.element, // それをcontentにセットする
    });
  },
  
async createPinElement(markerTypeId: number): Promise<google.maps.marker.PinElement> {

    // オリジナルのマーカーの描画情報を、あらかじめ用意した定数のMapから取得する。
    const markerDef = CategoryIdAndMarkerTypeDefMap.get(markerTypeId);
    const icon = document.createElement('div');

    // マーカーの中の画像は、Google FontsのMaterial Iconを使用するので、spanタグにclassをセットしておく。
    // 描画するhtmlファイルの方で、linkタグで必要なstylesheetを読み込んでおくこと
    icon.innerHTML = '<span class="material-symbols-outlined text-xl">' + markerDef!.iconKeyWord + '</span>';


    const { PinElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;
    return new PinElement({
      glyph: icon,
      glyphColor: markerDef!.glyphColor, // マーカーの中心部分の色
      background: markerDef!.bgColor, // マーカーの背景の色
      borderColor: markerDef!.glyphColor, // マーカーのボーダーの色
      scale: 1.5,
    });
  }
```

公式サイトから拝借しました。それぞれの色の場所が分かります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680908/aa0814f3-dd69-89b3-e204-d713492302c3.png"width="50%" />


ちなみに、Google FontsのMaterial Iconsはこちらです。
https://fonts.google.com/icons