GCPのMaps JavaScript APIを体験してみた

# はじめに
こんにちは。
APIの勉強を始めたばかりで、よく分かっていないため、とりあえず実際に使ってみようと思います。
そこで今回は、以前から気になっていた3大クラウドサービスの1つのGCPを、初心者なりに利用したので、ご参考になればと思います。

# 3大クラウドサービスとは
本題に入る前に、3大クラウドサービスをご存知でしょうか？
3大クラウドサービスとは、AmazonやGoogle、Microsoftが提供しているクラウドサービスで、Amazon Web Services（AWS）、Google Cloud Platform（GCP）、Microsoft Azure（Azure）のことを指します。
これらのサービスは、2024年第2四半期で、世界中のクラウドサービスマーケットシェアの約63%を占めるほど、圧倒的な利用率を誇っています。
特にこの中でも、AWSが約33%の利用率で、1番利用されています。

## 今回GCPを選んだ理由
その中でも今回、GCPを利用しようと思った理由は、ズバリ
**私がGoogleのサービスをよく利用しているから**です。
同じ企業が作っているサービスだとメニュー画面などのインタフェースも似た作りになっていることが多いので、覚えることが余計に増えない分少しでも理解しやすいかな、と思いました。

# Maps JavaScript APIを使ってみた
では、ここからは実際にマップ関連のAPIを利用したので、それを順を追って記載します。
各APIには、公式のドキュメントがあるので、基本的にはそれを基に進めております。
参考：[Maps JavaScript APIのドキュメントページ](https://developers.google.com/maps/documentation/javascript?hl=ja)

※今回使用した範囲では、無料分で済みましたが、**従量課金制**のため、使用量や他のAPIを使用する時は、各自確認してご利用ください。

### 1. Google Cloud Platformにアクセスし、アカウントを作成する
- 下記URLにアクセスし、`無料トライアルを試す`をクリック
Google Cloud Platform：https://console.cloud.google.com/

![スクリーンショット 2024-12-23 19.16.09 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/e3a1a9b5-01b9-93c8-dd0b-0fad17d2a9b4.png)

- Google Cloud Platformのアカウント情報の作成画面が出るので、内容を確認した後、`同意して続行`をクリック
- `お支払いプロファイル`や`お支払い方法`を入力後、`無料で利用開始`をクリック
![スクリーンショット 2024-12-18 18.30.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/35a36a7f-18e1-4e93-6bb6-586f483662cf.png)
- 作成し終わったら、このように表示されました
![アカウント作成後の表示.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/1c39c6fa-a105-ee11-6c4c-24fbd001ee74.png)


### 2. Maps JavaScript APIの有効化
- 左上のナビゲーションメニューをクリック
![スクリーンショット 2024-12-23 20.12.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/cadbc8c6-d72b-bdd3-2b46-ec0033049bcc.png)
- 出てきたメニューの中の`APIとサービス`-`ライブラリ`をクリック
![スクリーンショット 2024-12-23 20.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/744e249a-8057-12e6-a02e-f92efd219d48.png)
- 以下のような画面が出るので、今回使用する`Maps JavaScript API`をクリック
※もし出てきていない場合は、検索欄での検索や`すべて表示`ボタンをクリックするなどで出てくると思います。
![スクリーンショット 2024-12-23 20.13.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/8c5bdb88-1e6f-4196-113f-01545caf201a.png)
- 下記画面になるので、`有効にする`をクリック
![スクリーンショット 2024-12-23 20.44.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/6300bcff-a62a-09e3-5ca1-dbc686cadb74.png)
- `有効にする`をクリック後、以下の画面に遷移
![スクリーンショット 2024-12-23 20.51.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/70d40236-d3f5-1328-908a-412cd08798e5.png)


### 3. APIキーが発行されているか確認
- 左側のメニューから、`鍵と認証情報`をクリックし、さらに、APIキーの`Maps Platform API Key`をクリック
![スクリーンショット 2024-12-23 20.53.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/5e1fcfad-41d6-68cd-e4be-59f89c1247eb.png)

- 下記画面が表示され、右側の詳細情報にAPI Keyが表示される
※今回は、この画面では特に何もしないが、ここで各種制限の設定によるセキュリティ対策ができる様子
![スクリーンショット 2024-12-23 20.57.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/0527cc2b-4d15-08e1-38d2-6ad3a80799c9.png)


### 4. コード作成
- 上記画面の`APIとサービス`をクリック
- ページ中段あたりにある`Maps JavaScript API`の`Guides`をクリック
![スクリーンショット 2024-12-24 15.58.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/52ab0e5e-5036-7958-6adc-48ae6b4cadea.png)
- 以下のようなMaps JavaScript APIのドキュメントページに遷移
![スクリーンショット 2024-12-25 12.54.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/9f162674-ca04-54e1-c8d6-717e82e88988.png)
- 左側のメニューから、`APIキーを使用する`をクリックし、ページ下部にある`リクエストにAPIキーを追加する`のコードを確認
![スクリーンショット 2024-12-24 16.02.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/ebd40b30-dd65-f5e5-678a-a687b907bc94.png)

- 上記コードを基にVSコード等のテキストエディタでHTMLファイルを作成
なお、`YOUR_API_KEY`には、先ほど確認したご自身のAPIキーを入れてください
※サンプルコードは、記事の下のほうに載せます。
![スクリーンショット 2024-12-24 16.13.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/7b43ef2d-9ec6-8dc5-5668-52f6387f1ba8.png)
- ドキュメントに戻り、左側メニューの`JavaScript HTMLを使用するマーカーが配置された Googleマップを追加する`をクリックし、ページ下部の`コードサンプルの全文`の`JavaScript`タブで開いたコードを確認
![スクリーンショット 2024-12-24 16.25.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/81cedbda-32ae-4007-3b39-7a2df64cd172.png)
- 先ほどのコードサンプルを追加し、bodyタグの最初に`id="map"`を入れたdivタグも追加します
さらに、表示を考慮して、CSSファイルの作成とheadタグ内にそのリンクの追加もします
※`YOUR_API_KEY`には、先ほど確認したご自身のAPIキーを入れてください
``` html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div id="map"></div>
    <script>
        // Initialize and add the map
        let map;

        async function initMap() {
            // The location of Uluru
            const position = { lat: -25.344, lng: 131.031 };
            // Request needed libraries.
            //@ts-ignore
            const { Map } = await google.maps.importLibrary("maps");
            const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

            // The map, centered at Uluru
            map = new Map(document.getElementById("map"), {
                zoom: 4,
                center: position,
                mapId: "DEMO_MAP_ID",
            });

            // The marker, positioned at Uluru
            const marker = new AdvancedMarkerElement({
                map: map,
                position: position,
                title: "Uluru",
            });
        }
        initMap();
    </script>

    <script>
        (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
            key: "YOUR_API_KEY",
            v: "weekly",
            // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
            // Add other bootstrap parameters as needed, using camel case.
        });
    </script>
</body>

</html>
```
``` css:style.css
@charset "utf-8";

#map {
    width: 900px;
    height: 600px;
}
```

### 5. 実行
・・・・・・何も出ない・・・・・
![スクリーンショット 2024-12-24 19.00.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/35e24c45-015d-d315-4e26-60e55dae6d90.png)
- エラー内容を確認
![エラー内容.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/7d292641-1575-2073-9e52-5ab821b9b1d7.png)
googleが定義されていない・・・？
ということで、自分のコードを確認しつつ、ドキュメントを読んだり、色々な記事や動画なども調査したのですが・・・よく分からない！
※記事や動画は、おそらく古いドキュメントを参考にしているものが多かったので、最新のドキュメントには対応していなかったように思いました。

- ありがちなエラーへの対応
後日、改めて考えたときに、HTMLやJavaScriptを書いているときによく起こるエラーの原因といえば、**「記述する順番が違う」** という経験があったのを思い出したので、一旦、`APIキーの箇所`と`マップやマーカー生成の箇所`の順番を逆にしたコードにして、実行
![スクリーンショット 2024-12-25 13.42.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964476/d44240d3-13cd-1c50-f545-a1389adcabd9.png)
出た・・・
つまり、今回の[googleが定義されていない]は、おそらく、APIを利用する前に、マップやマーカーの生成コードを書いてしまっていたことが原因で、「まだAPIを利用できていないよ」ということだったのでしょう。
- 修正後のHTMLファイル
※YOUR_API_KEYには、先ほど確認したご自身のAPIキーを入れてください
``` html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

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

    <script>
        (g => { var h, a, k, p = "The Google Maps JavaScript API", c = "google", l = "importLibrary", q = "__ib__", m = document, b = window; b = b[c] || (b[c] = {}); var d = b.maps || (b.maps = {}), r = new Set, e = new URLSearchParams, u = () => h || (h = new Promise(async (f, n) => { await (a = m.createElement("script")); e.set("libraries", [...r] + ""); for (k in g) e.set(k.replace(/[A-Z]/g, t => "_" + t[0].toLowerCase()), g[k]); e.set("callback", c + ".maps." + q); a.src = `https://maps.${c}apis.com/maps/api/js?` + e; d[q] = f; a.onerror = () => h = n(Error(p + " could not load.")); a.nonce = m.querySelector("script[nonce]")?.nonce || ""; m.head.append(a) })); d[l] ? console.warn(p + " only loads once. Ignoring:", g) : d[l] = (f, ...n) => r.add(f) && u().then(() => d[l](f, ...n)) })({
            key: "YOUR_API_KEY",
            v: "weekly",
            // Use the 'v' parameter to indicate the version to use (weekly, beta, alpha, etc.).
            // Add other bootstrap parameters as needed, using camel case.
        });
    </script>

    <script>
        // Initialize and add the map
        let map;

        async function initMap() {
            // The location of Uluru
            const position = { lat: -25.344, lng: 131.031 };
            // Request needed libraries.
            //@ts-ignore
            const { Map } = await google.maps.importLibrary("maps");
            const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");

            // The map, centered at Uluru
            map = new Map(document.getElementById("map"), {
                zoom: 4,
                center: position,
                mapId: "DEMO_MAP_ID",
            });

            // The marker, positioned at Uluru
            const marker = new AdvancedMarkerElement({
                map: map,
                position: position,
                title: "Uluru",
            });
        }
        initMap();
    </script>


</body>

</html>

```

# まとめ
今回、GCPの1つのAPIだけではありますが、経験することができたので、クラウドサービスの利用のハードルが少し下がった気がします。
また、今回でいえば、HTMLやCSS、JavaScriptの知識があったほうが理解しやすいものだったと思いますが、公式ドキュメントのサンプルコードを利用することで、ある程度の形は簡単に作成できるように感じました。
一方で、ドキュメントは随時更新されているようなので、過去の記事や動画などが参考にならないケースもあると思います。その点には注意しましょう。


# 参考
続きの記事：[GCPのMaps JavaScript APIを体験してみた2](https://qiita.com/2012ataka/items/9d59f528c7f2159db8da)