フォトリアルな 3D 地図にマーカーとアニメーションを追加する

1. 始める前に

このチュートリアルでは、アプリに 3D マーカーを追加してスタイルを設定する方法について説明します。また、特定の場所を飛行してアプリをアニメーション化する方法についても学びます。

このチュートリアルは、最初の codelab で説明したコンセプトを基にしています。まだ Codelab を修了していない場合は、この Codelab を修了して、このアプリに必要な基礎知識を習得してください。

演習内容

「マーカーが配置された完全な地図。

このアプリでは、ヨーロッパの主要な Google オフィスの概要を確認できます。ユーザーはオフィスを選択して、その周辺を飛行して探索し、ズームアウトして全体像に戻ることができます。これらの機能は、旅行や探索のアプリでよく見られ、ユーザーの没入感を高めることができます。

この Codelab では、次のような 3D ウェブアプリを作成します。

  • Maps JavaScript API を動的に読み込みます。
  • 地図に 3D マーカーを追加します。
  • SVG を使用してマーカーのスタイルを設定します。
  • マーカーに移動したり、マーカーの周囲を飛行したりできるようになりました。
  • コードからロケーションを抽象化して配列にします。

学習内容

  • マーカーの仕組み。
  • マーカーのスタイルを設定する方法。
  • 組み込み関数でのアニメーションの仕組み。
  • ポーズを取るカメラの位置とポイントの位置を調整して、フレーミングを改善する。
  • カメラ パラメータをキャプチャして商品をより適切にフレーム設定するための便利なハック。

前提条件

この Codelab を完了するには、以下の内容を理解しておく必要があります。Google Maps Platform の操作に慣れている場合は、すぐに Codelab に進んでください。

必要な Google Maps Platform サービス

この Codelab では次の Google Maps Platform サービスを使用します。

  • Maps JavaScript API

この Codelab のその他の要件

この Codelab を実行するには、次のアカウント、サービス、ツールが必要です。

  • 課金が有効になっている Google Cloud アカウント。
  • Maps JavaScript API を有効にした Google Maps Platform API キー
  • JavaScript、HTML、CSS に関する基本的な知識。
  • 任意のテキスト エディタまたは IDE: 編集したファイルを保存して表示します。
  • 作業中にファイルを表示するウェブブラウザ。

2. セットアップする

Google Maps Platform を設定する

課金を有効にした Google Cloud Platform アカウントとプロジェクトをまだ作成していない場合は、Google Maps Platform スタートガイドに沿って請求先アカウントとプロジェクトを作成してください。

  1. Cloud Console で、プロジェクトのプルダウン メニューをクリックし、この Codelab に使用するプロジェクトを選択します。

  1. Google Cloud Marketplace で、この Codelab に必要な Google Maps Platform API と SDK を有効にします。詳しい手順については、こちらの動画またはドキュメントをご覧ください。
  2. Cloud Console の [認証情報] ページで API キーを生成します。詳しい手順については、こちらの動画またはドキュメントをご覧ください。Google Maps Platform へのすべてのリクエストで API キーが必要になります。

3. シンプルな地球儀

アプリの作成を開始するには、基本的な設定を確立することが不可欠です。これにより、画像のように地球の最も基本的な形状の「青い球体」ビューが生成されます。

「初期設定の地球儀を示す画像。

スターター ページのコードを作成する

サイトに地球を追加するには、次のコードをページに追加する必要があります。これにより、Maps JavaScript API のローダのセクションと、ページ内に地図 3D 要素を作成する init 関数が追加され、マーカーのコードが追加されます。

独自のキー(設定セクションで作成したもの)をページに追加してください。追加しないと、3D 要素を初期化できません。

<!DOCTYPE html>
<html>
   <head>
       <title>Step 1 - Simple Globe</title>
       <style>
           body {
               height: 100vh;
               margin: 0;
           }
       </style>
   </head>

   <body>
       <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: "<INSERT API KEY>",
               v: "alpha",
               // 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>
           let map3D = null;

           async function init() {
               const { Map3DElement, MapMode } = await google.maps.importLibrary("maps3d");

               map3D = new Map3DElement({
                   mode: MapMode.HYBRID,
               });

               document.body.append(map3D);
           }
           init();
       </script>
   </body>
</html>

これで、撮影対象のフレーミングを開始する準備が整いました。フレーミングは次のステップで行います。

4. フレームの最初のビュー

地球儀ビューの地図を作成したので、次は、正しい出発地をフレームに収める実装ステップに進みます。これにより、ユーザーは自分がどこで作業しているかをすぐに把握できます。

この例ではヨーロッパの Google オフィスに焦点を当てていますが、このアプローチは、国全体から 1 つの街区まで、世界中のあらゆる場所に適用できます。このプロダクトの速度と柔軟性により、コードの変更を最小限に抑えて、アプリケーションをグローバルからローカルにスケーリングできます。

最初は、3D 地図を次のようにフレーム設定します。

「ヨーロッパを中心とした地球儀。

カメラをヨーロッパに向けてフレーミングする

表示を写真のようにするには、カメラを空中に配置してその場所を見下ろすように、ディスプレイを正しくフレーム設定する必要があります。

これを行うには、地図コントロールの複数のパラメータを使用してカメラの詳細を設定します。パラメータが「現実」世界でどのように相互作用するかは、次の図に示されています。具体的には、カメラが向いている中心ポイントと、その中心から視線が向いている場所までの距離(範囲)があります。また、カメラの視点の傾斜も設定する必要があります(設定しないと、地球を真上から見下ろすことになります)。

「カメラのパラメータが表示されている画像。

最後の設定である向きは、カメラの向きを決定します。真北からのオフセットとして測定されます。これらの値は、初期表示を設定するためのオブジェクトとして 3D 地図要素に適用されます。これは、更新された 3D 要素コンストラクタのコードで確認できます。

map3D = new Map3DElement({
    center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
    range: 5814650,
    tilt: 33,
    heading: 4.36,
    mode: MapMode.HYBRID
});

カメラ パラメータをキャプチャする

3D マップでビューをフレーム設定するには、カメラを正確に配置する必要があります。これは、コードだけで実現するのは難しい場合があります。このプロセスを簡素化するには、必要なビューをクリックしたときにカメラ パラメータをキャプチャする関数をページに追加します。パラメータがコンソールに出力され、オブジェクトのカメラ設定にコピーできるようになります。

後で使用できるコードは、このページのサンプルに追加されています。Codelab では必要ないため、以降のページのサンプルには表示されませんが、カメラの位置を調整して没入感のあるデモを作成する場合は、覚えておくと便利です。

map3D.addEventListener('gmp-click', (event) => {
   console.log("camera: { center: { lat: " + map3D.center.lat + ", lng : " + map3D.center.lng + ", altitude: " + map3D.center.altitude + " }, range: " + map3D.range + ", tilt: " + map3D.tilt + " ,heading: " + map3D.heading + ", }");
   console.log("{ lat: " + event.position.lat + ", lng : " + event.position.lng + ", altitude: " + event.position.altitude + " }");
   // Stop the camera animation when the map is clicked.
   map3D.stopCameraAnimation();
});

stopCameraAnimation 関数を使用していることに注意してください。ページがズームインまたはオービットしている場合は、アニメーションを停止して、その時点でディスプレイ内の位置をキャプチャできます。次のコードで、この処理を行うことができます。詳細については、stopCameraAnimation のドキュメントをご覧ください。

クリックからの出力例(コンソールに表示されます)。

camera: { center: { lat: 51.39870122020001, lng : -0.08573187165829443, altitude: 51.66845062662254 }, range: 716.4743880553578, tilt: 50.5766672986501 ,heading: -1.048260134782318, }
step2.html:40 { lat: 51.398158351120536, lng : -0.08561139388593597, altitude: 51.860469133677626 }

カメラテキストは、3D 地図のさまざまなオブジェクトの JSON 入力として使用できます。2 番目の出力は、クリックが発生した実際のポイントの位置です。ポイントの作成や、マーカーの配置に役立ちます。

ページが正しくフレーム設定されたら、マーカーを追加できます。方法については、次のステップに進んでください。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 2 - Europe View</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode } = await google.maps.importLibrary("maps3d");

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.HYBRID,
            });

           map3D.addEventListener('gmp-click', (event) => {
               console.log("camera: { center: { lat: " + map3D.center.lat + ", lng : " + map3D.center.lng + ", altitude: " + map3D.center.altitude + " }, range: " + map3D.range + ", tilt: " + map3D.tilt + " ,heading: " + map3D.heading + ", }");
               console.log("{ lat: " + event.position.lat + ", lng : " + event.position.lng + ", altitude: " + event.position.altitude + " }");

               map3D.stopCameraAnimation();
           });

           document.body.append(map3D);
       }
       init();
   </script>

</body>

</html>

5. シンプルなマーカー

このセクションでは、最初のマーカーを追加する方法について説明します。まず、マーカーの一般的な詳細について説明します。

3D 地図では、Marker3DElement クラスと Marker3DInteractiveElement クラスの 2 種類のマーカークラスを作成できます。どちらを選択するかは、マーカーのクリックを有効にするかどうかによって決まります。この点以外は基本的に同じであるため、まず Marker3DElement を作成し、後続の手順で Marker3DInteractiveElement に「アップグレード」します。

このステップの完全な解決策は、こちらをご覧ください。

「完了したステップを示すマーカーが付いた地球。

マーカーの高さを追加する

まず、3D マップ内の他の要素と同様に、マーカーも 3D であることを理解してください。つまり、位置情報には高さ(標高)を設定できます。この高さは、海面、地面、メッシュに対する位置として表すことができます。また、地面に固定して標高の位置を無視するように設定することもできます。詳細については、AltitudeMode のドキュメントの高度定数セクションをご覧ください。

また、extruded 値を使用して、マーカーを押し出すかどうかを設定することもできます。これにより、マーカーから地面まで小さな線が引かれ、高さに関連する実際の位置を示すかどうかを指定できます。これは、地面上の点を特定する場合に便利です。たとえば、Google UK の拠点はどちらも押し出しが適用され、位置が絶対高さに設定されています。1 つ目は 75 m、2 つ目は 125 m です。

75 メートル地点のマーカー

125 メートル地点のマーカー

高度 75 メートル。

高度 125 メートル。

オクルージョンとコリジョンのあるマーカーの表示と非表示を切り替える

このデモでは位置がかなり離れているため重要ではありませんが、重なり合う可能性のあるマーカーや建物の後ろに隠れてしまうマーカーについては、collisionBehavior 値または drawsWhenOccluded 値でマーカーの動作を制御できます。

衝突動作には次のオプションがあります。

  • REQUIRED(デフォルト): 他のマーカーと重なっていても常に表示されます。
  • OPTIONAL_AND_HIDES_LOWER_PRIORITY: 他のマーカーと表示位置が重ならない場合にのみ表示されます。このタイプのマーカー同士が重なった場合、zIndex の高いほうが表示されます。zIndex も同一の場合、画面内の縦位置が低いほうが表示されます。
  • REQUIRED_AND_HIDES_OPTIONAL: 他のマーカーと重なっても常に表示されますが、このマーカーと表示位置が重なる OPTIONAL_AND_HIDES_LOWER_PRIORITY のマーカーとラベルはすべて非表示になります。

定義された衝突動作に基づいてマーカーが表示される仕組みの違いは、次の画像をご覧ください。REQUIRED を設定するとすべてのマーカーが表示されますが、REQUIRED_AND_HIDES_OPTIONAL を使用すると、画面の下部にあるマーカーが表示されます(必要に応じて、zIndex を調整して他のマーカーを上に表示することもできます)。

すべてのマーカーが必須として表示されている

他のマーカーの後ろに隠れているマーカー

必須

REQUIRED_AND_HIDES_OPTIONAL

オクルージョンでは、建物の後ろにマーカーを描画するかどうかを選択できます。次の画像に示します。drawsWhenOccluded が true に設定されている場合、建物に隠れて描画されたマーカーは少し暗くなります。false に設定されている場合、建物に隠れているマーカーは非表示になります。詳細は次の表をご覧ください。

遮蔽されたマーカーが非表示になっている地図の画像

遮蔽されたマーカーが表示された地図を示す画像

drawsWhenOccluded : false

drawsWhenOccluded : true

前述のように、遮蔽されたマーカーの描画が許可されている場合、衝突によって隠されたマーカーは薄く表示されます。この画像では、建物に隠れているマーカーや、他のマーカーに隠れているマーカーがいくつかあります。

「複数のマーカーと遮蔽の影響を示す画像。

詳しくは、2D マップの衝突動作の例をご覧ください。

キャンバスをクリアする

では、最初のマーカーを作成しましょう。ユーザーがマーカーに集中できるように、3D マップでデフォルトのラベルを無効にできます。

3D 地図要素の mode 値を SATELLITE に設定します。

詳細については、mode をご覧ください。

map3D = new Map3DElement({
    center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
    range: 5814650,
    tilt: 33,
    heading: 4.36,
    mode: MapMode.SATELLITE
});

作成された 3D 地図は次のようになります。

「国境とテキストのないヨーロッパの画像。

最初のマーカーを追加する

キャンバスが空になったので、最初のマーカーを追加できます。主なパラメータには、位置とラベルがあります。

マーカーを追加するには、マーカーの位置を設定します。マーカーの上に表示されるラベルや、Marker3DElement のドキュメントで説明されている他の要素を含めることもできます。

マーカーを追加するには、デフォルトのラベルを非表示にする行の後に次のコードを追加します。

const marker = new Marker3DElement({
   position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
   label: 'Google UK',
   altitudeMode: 'ABSOLUTE',
   extruded: true,
});

map3D.append(marker);

マーカーを作成したら、append メソッドを使用して 3D 地図に追加します。マーカーは、3D 地図内の子要素の配列として保存されます。マーカーを変更するには、この配列を介してマーカーにアクセスする必要があります。

API の読み込み時にライブラリのリストに追加して、Marker3DElement が Maps JavaScript API から読み込まれるようにします。

const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");

ページが読み込まれると、ヨーロッパ全体が表示され、ロンドンのオフィスの上にマーカーが表示されます。アニメーションに示すように、手動でズームインすると、作成した場所にマーカーが表示されます。

「Google UK を手動でズームインするアニメーション。

最初のマーカーを読み込んだので、次はマーカーをより見やすくします。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 3 - Simple Marker</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       async function init() {
            const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");

            map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
            });

           const marker = new Marker3DElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });
           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

6. SVG マーカー

このステップでは、マーカーを変更して国を表す旗を追加し、マーカーをより見やすくします。では、その方法を見てみましょう。そのためには、PinElement について理解する必要があります。

最終的に、次のような新しい外観になります。

「英国の国旗が付いたマーカーが写っている画像」

PinElement を使用した基本的なカスタマイズ

Javascript API のマーカー間で共有される要素の 1 つが PinElement です。これは、2D 地図でも 3D 地図でも使用できます。Map3DElementMarker3DElement を追加するときに、その要素の子として PinElementMarker3DElement に追加します。

PinElement には、基本的なレベルで通常のマーカーを変更して、その枠線の色、内部ポイント(またはグリフ)の色、背景色を設定できる機能が含まれています。2D マーカーを示す画像で確認できます。

「マーカーピンのカスタマイズ オプションを含む画像」

要素のスケール値を設定して、マーカーのサイズを設定することもできます(>1 は通常より大きく、<1 は通常より小さくなります)。

標準の PinElement マップピンの外観を維持しながら、よりカスタマイズされた外観にしたい場合は、グリフを画像ファイルまたは svg ファイルに置き換えることもできます。

PinElements 以外

このステップでは、標準の PinElement を svg フラグとさまざまな色で更新します。また、マーカーの外観を完全に変更して、地図のピンのように見えないようにすることもできます。マーカー内に、HTMLImageElement や SVGElement などのテンプレートを使用して新しいグラフィックを挿入することもできます。詳しくは、ドキュメントの Marker3DElement-Slots をご覧ください。

さまざまな手法を使用してマーカーをスタイル設定する例については、次のサンプルをご覧ください。

マーカーの基本的なカスタマイズを示した画像。

複雑なマーカーのカスタマイズを示す画像。

PinElement による基本的なカスタマイズを加えたマーカー。サンプルをご覧ください。

SVG と画像を使用してテンプレートで複雑にカスタマイズされたマーカー(サンプルを参照)。

PinElement を追加する

マーカーの外観を変更するには、まず、PinElement ライブラリがページに追加されていることを確認する必要があります。これを行うには、maps3d ライブラリのインポート後に次のコード行を追加します。

const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");
const { PinElement } = await google.maps.importLibrary('marker');

要素が読み込まれたら、PinElement を参照して作成できます。コードを確認し、マーカーが作成される場所と、マーカーを 3D 地図に追加する場所の間に追加します。

const marker = new Marker3DElement({
   position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
   label: 'Google UK',
   altitudeMode: 'ABSOLUTE',
   extruded: true,
});

const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

const markerPin = new PinElement({
   "background": 'white',
   "glyph": new URL(base + '/images/gb.svg'),
   "scale": 1.0,
});
marker.append(markerPin);

map3D.append(marker);

基本的なピンを読み込むだけでなく、PinElement の設定や、関連する背景色とスケールの設定以外にも、いくつかの作業を行う必要があります。

まず、旗アイコンの svg 画像(この場合はユニオンジャック)を参照する必要があります。https://flagicons.lipis.dev/ などのコレクションから入手できます。

アイコンを作成したら、サイトが見つけられる場所に配置します。この場合は、画像の場所をハードコードするか、ベース変数で示されているように、現在のサイトの場所をディレクトリのスタブとして使用します。次に、これをサーバー上の正しいフラグの場所にリンクします。ここでは '/images/gb.svg' の下にあります。

これにより、次のような PinElement が作成されます。

「ユニオンジャック旗のシンボルを示すマーカー。

フラグを適切な場所に配置し、コードを適切な場所に配置すると、次のような 3D 地図が作成されます。

「新しいマーカーにズームインしています。

マーカーの装飾が完了しました。クリック可能に変更してインタラクションを追加することもできます。これは次のステップで行います。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

また、国旗の svg ファイル(または任意の png ファイル)を取得して、ページから見つけられるディレクトリに保存する必要があります(ここでは images フォルダに保存しています)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 4 - SVG Marker</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode, Marker3DElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

7. インタラクティブ マーカー

前のステップでページにマーカーを追加しましたが、見た目は良くなりましたが、それ以外の機能はなく、3D 地図を操作する方法は変わりません。次のステップでは、マーカーをクリックしたときにマーカーで何かを行う機能を追加し、マーカーがユーザー操作に反応できるようにします。

この機能を追加するには、Marker3DElementMarker3DInteractiveElement に変換する必要があります。最終的には、見た目は同じページになりますが、マーカーをクリックするとアラートが表示されます。次のような表示になります。

「クリックされたときのレスポンスを示している画像。

まず、マーカークラスを変更します。

マーカーにインタラクティビティを追加するには、正しいクラスを使用していることを確認する必要があります。必要なのは Marker3DInteractiveElement ですが、これは Marker3DElement の拡張機能であるため、新しいクラスを読み込み、コンストラクタでクラス名を変更する以外に何もする必要はありません。

const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
const { PinElement } = await google.maps.importLibrary('marker');

map3D = new Map3DElement({
    center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
    range: 5814650,
    tilt: 33,
    heading: 4.36,
    mode: MapMode.SATELLITE,
});

const marker = new Marker3DInteractiveElement({
   position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
   label: 'Google UK',
   altitudeMode: 'ABSOLUTE',
   extruded: true,
});

次に、マーカーにクリック イベントを追加します。

次に、マーカーにクリック イベントを追加して、ユーザー操作を処理し、応答するようにします。このスニペットでは、クリック イベントがマーカーに追加されています。この場合、アラートがトリガーされ、マーカーのラベルを表示するテキストがポップアップ表示されます。このラベルは、ラベル プロパティにアクセスできるトリガーされたイベントのターゲットから取得されます。マーカーの作成直後に、次のコードをアプリケーションに追加します。

marker.addEventListener('gmp-click', (event) => {
   alert('You clicked on : ' + event.target.label);
   event.stopPropagation();
});

stopPropagation イベントは、スタック内の他のクリック リスナーが、3D 地図のメイン キャンバスなどの基盤となるオブジェクトで確実に発生するようにするために使用されます。

これで、アプリケーションを実行すると、次の結果が得られます。

「クリックされたときの応答を示す画像。

マーカーがクリックされたときに何かを行うことができるようになりました。次のステップでは、ページにアニメーションを追加します。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 5 - Interactive Marker</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DInteractiveElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           marker.addEventListener('gmp-click', (event) => {
               alert('You clicked on : ' + event.target.label);
               event.stopPropagation();
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

8. ジャンプ先

このステップでは、マーカーをクリックして追加したアニメーションを使用して、その場所に移動する機能を使用します。操作方法については、こちらをご覧ください。

「クリックされたマーカーとその場所への移動を示すアニメーション。

flyCameraTo によるアニメーション化

これをページに追加するには、3D マップの flyCameraTo メソッドを使用します。このメソッドでは、現在地のカメラ位置から表示するカメラ位置までカメラがアニメーション化され、2 つの位置が補間され、3D マップ内で飛行がアニメーション化されます。

flyCameraTo を使用する場合は、FlyToAnimationOptions を指定する必要があります。このオプションには、endCamera は、アニメーションの終了時にカメラが向く位置で、durationMillis は遷移にかかる時間(ミリ秒単位)です。

この例では、カメラをマーカー位置である建物に向け、傾斜角を 65 度、範囲を 500 メートル、向きを北(0 度)に設定します。アニメーションのタイミングを 12,500 ミリ秒(12.5 秒)に設定します。

ページの現在のアラート イベントを flyCameraTo スニペットに置き換えます。

marker.addEventListener('gmp-click', (event) => {
   map3D.flyCameraTo({
       endCamera: {
           center: marker.position,
           tilt: 65,
           range: 500,
           heading: 0,
       },
       durationMillis: 12500,
   });

   event.stopPropagation();
});

これで、ページを更新してマーカーをクリックし、Google UK に移動できるようになります。アニメーションをご覧ください。

「クリックされたマーカーとその場所への移動を示すアニメーション。

このステップでは、カメラをマーカーの位置に移動するクリック可能なマーカーを追加しました。次のステップでは、ポイントの周囲を飛行してその場所を周回する機能を追加します。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 6 - Zoom To</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
                center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
                range: 5814650,
                tilt: 33,
                heading: 4.36,
                mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DInteractiveElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           marker.addEventListener('gmp-click', (event) => {
               map3D.flyCameraTo({
                   endCamera: {
                       center: marker.position,
                       tilt: 65,
                       range: 500,
                       heading: 0,
                   },
                   durationMillis: 12500,
               });

               event.stopPropagation();
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

9. 飛び回る

アニメーションの最後の要素は、flyCameraAround メソッドを使用して建物の周りを回転するアニメーションを作成します。最終的には、アニメーションのように建物に飛んで行き、建物の周りを飛ぶアニメーションが完成します。実際の例としては少し短いですが、アクションの仕組みを示すには便利です。長すぎないように、適切な値が得られるまでタイミングを調整してください。

「マーカーをクリックして、その場所に移動し、その周囲を飛行するアニメーション。

飛行を開始する

flyCameraAround メソッドは、flyCameraTo 関数と似ており、カメラのパラメータとして、周回する場所と周回にかかる時間(ミリ秒単位)を制御するオプションを入力として受け取ります。また、指定した時間内に発生するローテーションの数も指定できます。すべてのオプションは、FlyAroundAnimationOptions で確認できます。

でも、ちょっと待ってください。

このアニメーションでは、アニメーションが目的地に飛んでから、その周囲を飛び回り、アニメーションを連結しています。そのためには、3D マップの gmp-animationend イベントを使用して、次のアニメーションを開始する前に現在のアニメーションが終了していることを確認します。このアニメーションは 1 回だけ実行し、その後は停止する必要があります。

コードを確認し、前のセクションで追加したコードの後に挿入します。

marker.addEventListener('gmp-click', (event) => {
   map3D.flyCameraTo({
       endCamera: {
           center: marker.position,
           tilt: 65,
           range: 500,
           heading: 0,
       },
       durationMillis: 5000,
   });

   map3D.addEventListener('gmp-animationend', () => {
       map3D.flyCameraAround({
           camera: {
               center: marker.position,
               tilt: 65,
               range: 500,
               heading: 0,
           },
           durationMillis: 5000,
           rounds: 1
       });
   }, { once: true });

   event.stopPropagation();
});

gmp-animationend イベントをリッスンする機能を追加すると、flyCameraAround イベントを呼び出すことができます。開始ポイントを「飛行」メソッドの終了カメラと同じに設定すると、スムーズな遷移が実現します(新しい場所に急激に移動しないようにするためです)。ここでも、durationMillis はアニメーションの実行にかかる時間を制御するために設定します。この場合、メソッドは別のオプション rounds も受け取り、これは 1 に設定されます。

つまり、カメラは 5 秒に 1 回、そのポイントの周りを回転します。これらの値を試して、適切な数値を見つけることができます。

この時点でアニメーションは終了しますが、このコードで gmp-animationend イベントが再度発生しないようにする必要があります。このイベントが発生すると、軌道が無限に続くことになります。これを回避するには、リスナーに oncetrue に設定するオプションを用意します。つまり、イベントは完了すると削除されるため、無限ループを回避できます。

これを追加すると、ソリューションを実行して、アニメーションが最後にマーカーの周りを飛ぶようになります(アニメーションを参照)。

「マーカーの周りを飛ぶ様子を示すアニメーション。

このステップでは、クリック可能なマーカーを追加しました。カメラはマーカーの位置に移動し、その周囲を飛行します。次のステップでは、ポイントを追加して、ポイント間を移動できるようにします。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 7 - Zoom Around</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       const europeCamera = {
           center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
           range: 5814650,
           tilt: 33,
           heading: 4.36,
       };

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
               ...europeCamera,
               mode: MapMode.SATELLITE,
           });

           const marker = new Marker3DInteractiveElement({
               position: { lat: 51.5332, lng: -0.1260, altitude: 75 },
               label: 'Google UK',
               altitudeMode: 'ABSOLUTE',
               extruded: true,
           });

           marker.addEventListener('gmp-click', (event) => {
               map3D.flyCameraTo({
                   endCamera: {
                       center: marker.position,
                       tilt: 65,
                       range: 500,
                       heading: 0,
                   },
                   durationMillis: 5000,
               });

               map3D.addEventListener('gmp-animationend', () => {
                   map3D.flyCameraAround({
                       camera: {
                           center: marker.position,
                           tilt: 65,
                           range: 500,
                           heading: 0,
                       },
                       durationMillis: 5000,
                       rounds: 1
                   });
               }, { once: true });

               event.stopPropagation();
           });

           const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

           const markerPin = new PinElement({
               "background": 'white',
               "glyph": new URL(base + '/images/gb.svg'),
               "scale": 1.0,
           });
           marker.append(markerPin);

           map3D.append(marker);

           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

10. パリ!

ロンドンは素晴らしい都市ですが、ページに 1 つだけだと寂しいので、パリから新しい場所を追加していきましょう。そのためには、配列を使用してロケーション固有の詳細をすべて保持し、それを関数と変数の入力として使用して、マーカーの表示パラメータとカメラのロケーションへの移動とその周辺を設定します。たとえば、建物のより良いカメラショットを撮影するために、マーカーポイントの位置とは異なる場所に設定する必要がある場合があります。

「Google フランスに移動して周囲を飛行するアニメーション。

位置情報の配列

特定の場所に関する詳細(表示カメラ、マーカーポイント、表示オプションなど)をすべてハードコードしなくても済むように、JSON オブジェクトの小さな配列を使用して、このデータを保持できます。作成したマーカーをアプリで使用する場合、このスタイルを適用できます。この例は、配列を保持する officeLocations という変数を作成するコード スニペットに示されています。

init 関数の直前に次のコードを追加します。また、ベース変数を init 関数の外に移動して、すべてのオフィスの場所に適用できるようにしました。

const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

const europeCamera = {
   center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
   range: 5814650,
   tilt: 33,
   heading: 4.36,
};

const officeLocations = [
   {
       "name": "Google France",
       "camera": {
           "center": { lat: 48.877276, lng: 2.329978, altitude: 48 },
           "range": 178,
           "tilt": 57.48,
           "heading": -17,
       },
       "point": { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
       "pin": {
           "background": 'white',
           "glyph": new URL(base + '/images/fr.svg'),
           "scale": 1.0,
       },
   },
   {
       "name": "Google UK",
       "camera": {
           "center": { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
           "range": 500,
           "tilt": 56.21672368296945,
           "heading": -31.15763027564165,
       },
       "point": { lat: 51.5332, lng: -0.1260, altitude: 75 },
       "pin": {
           "background": 'white',
           "glyph": new URL(base + '/images/gb.svg'),
           "scale": 1.0,
       },
   }]
       const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

各オフィス ロケーションには次のプロパティがあります。

  • name : 場所の名前。
  • camera : 飛行先の場所を表示する初期ビュー。
  • point : マーカーを配置する場所。
  • pin : マーカーピンの色とグリフのプロパティの詳細

別の角度

英国ではカメラの中心とマーカーの位置が(高度を除き)同じですが、フランスではカメラと位置が異なります。これは、フランスの場所では、マーカーを最初のカメラビューとは異なる場所に配置する必要があるためです。これにより、マーカー ポイントを使用する場合よりも、飛行中に建物全体をよりよく確認できます。

ヨーロッパに戻る

ポイントを増やす機能の一つは、ポイント間を移動できる要件が追加されることです。プルダウンを使用して選択できるようにすることもできますが、この例では、ユーザーが別の場所を選択できるように、カメラが毎回ヨーロッパのビューに移動します。

これを行うには、カメラをヨーロッパ全体のビューにリセットするために使用できる変数に初期ビューを保存する必要があります。この例では、europeCamera という新しい変数を追加して、後で使用できるように保存します。

init 関数を更新する

最初に行う編集は、Map3DElement の作成時に europeCamera オブジェクトを入力として使用することである。

2 つ目の編集は、マーカー作成セクションをループでラップして、変数に保存されているパラメータで更新することです。コードに示されているように、次のようにします。

  • office.point : マーカーの位置。
  • office.name : マーカーのラベルに使用されるオフィス名。
  • office.camera : カメラの初期位置。
  • office.pin : 表示の違いに関する PinElement オプション

また、フランスの国旗の SVG ファイルまたは画像も忘れずに入手してください。

async function init() {
   const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
   const { PinElement } = await google.maps.importLibrary('marker');

   map3D = new Map3DElement({
       ...europeCamera,
       mode: MapMode.SATELLITE,
   });

   officeLocations.forEach(office => {
       const marker = new Marker3DInteractiveElement({
           position: office.point,
           label: office.name,
           altitudeMode: 'ABSOLUTE',
           extruded: true,
       });

       marker.addEventListener('gmp-click', (event) => {
           map3D.flyCameraTo({
               endCamera: office.camera,
               durationMillis: 5000,
           });

           map3D.addEventListener('gmp-animationend', () => {
               map3D.flyCameraAround({
                   camera: office.camera,
                   durationMillis: 5000,
                   rounds: 1
               });

               map3D.addEventListener('gmp-animationend', () => {
                   map3D.flyCameraTo({
                       endCamera: europeCamera,
                       durationMillis: 5000,
                   });
               }, { once: true });

           }, { once: true });

           event.stopPropagation();
       });

       const markerPin = new PinElement(office.pin);
       marker.append(markerPin);

       map3D.append(marker);
   });
   document.body.append(map3D);
}

保存された europeCamera 変数を使用して、欧州のビューへの飛行を処理するために、flyCameraAround アニメーションの後に 2 つ目の gmp-animationend 関数が追加されています。アニメーションに示すように、

「フランスと英国のオフィス間を飛ぶアニメーション。

このステージでは、2 つのロケーションを追加し、アニメーションとロケーション アレイを使用してそれらの間を移動できるようにアプリを拡張しました。次のステージでは、残りのオフィスの場所を配列に追加します。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

また、フラグの svg ファイル(または任意の png ファイル)を取得して、ページから見つけられるディレクトリに保存する必要があります(ここでは images フォルダに保存しています)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 8 - Paris!</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

       const europeCamera = {
           center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
           range: 5814650,
           tilt: 33,
           heading: 4.36,
       };

       const officeLocations = [
           {
               "name": "Google France",
               "camera": {
                   "center": { lat: 48.877276, lng: 2.329978, altitude: 48 },
                   "range": 178,
                   "tilt": 57.48,
                   "heading": -17,
               },
               "point": { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
               "pin": {
                   "background": 'white',
                   "glyph": new URL(base + '/images/fr.svg'),
                   "scale": 1.0,
               },
           },
           {
               "name": "Google UK",
               "camera": {
                   "center": { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
                   "range": 500,
                   "tilt": 56.21672368296945,
                   "heading": -31.15763027564165,
               },
               "point": { lat: 51.5332, lng: -0.1260, altitude: 75 },
               "pin": {
                   "background": 'white',
                   "glyph": new URL(base + '/images/gb.svg'),
                   "scale": 1.0,
               },
           }]

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
               ...europeCamera,
               mode: MapMode.SATELLITE,
           });

           officeLocations.forEach(office => {
               const marker = new Marker3DInteractiveElement({
                   position: office.point,
                   label: office.name,
                   altitudeMode: 'ABSOLUTE',
                   extruded: true,
               });

               marker.addEventListener('gmp-click', (event) => {
                   map3D.flyCameraTo({
                       endCamera: office.camera,
                       durationMillis: 5000,
                   });

                   map3D.addEventListener('gmp-animationend', () => {
                       map3D.flyCameraAround({
                           camera: office.camera,
                           durationMillis: 5000,
                           rounds: 1
                       });

                       map3D.addEventListener('gmp-animationend', () => {
                           map3D.flyCameraTo({
                               endCamera: europeCamera,
                               durationMillis: 5000,
                           });
                       }, { once: true });

                   }, { once: true });

                   event.stopPropagation();
               });

               const markerPin = new PinElement(office.pin);
               marker.append(markerPin);

               map3D.append(marker);
           });
           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

11. その他の場所

アプリに必要な機能はすべて揃いましたが、3D 地図はまだ少し寂しい感じがします。そこで、もう少し場所を追加して、少し賑やかにしましょう。配列を使用すると、独自の一意のマーカーを使用して、新しい場所を簡単に追加できます。最後に、次のビューが表示されるまでマーカーを追加します。

「すべてのオフィスを示す画像。

マーカーを追加する。

Google はヨーロッパの多くの国にオフィスを構えています。そのうちのいくつかを地図に追加しましょう。配列を更新するだけです。これはウェブサービスから取得することも、どこかの静的ファイルから提供することもできます。この例では、単純に同じページに保持します。

マーカーはいくつでも追加できます。マーカーはページによって検出され、ビューに自動的に追加されます。正しいフラグを取得して、images ディレクトリ(または便利な場所)に保存してください。

const officeLocations = [
   {
       name: "Google France",
       camera: {
           center: { lat: 48.877276, lng: 2.329978, altitude: 48 },
           range: 178,
           tilt: 57.48,
           heading: -17,
       },
       point: { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/fr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google UK",
       camera: {
           center: { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 51.5332, lng: -0.1260, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gb.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Belgium",
       camera: {
           center: { lat: 50.83930408436509, lng: 4.38052394507952, altitude: 64.38932203802196},
           range: 466.62899893119175,
           tilt: 43.61569474716178,
           heading: 51.805907046332074,
       },
       point: { lat: 50.8392653, lng: 4.3808751, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/be.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Czechia",
       camera: {
           center: {
               lat: 50.07004093853976,
               lng: 14.402871475443956,
               altitude: 223.39574818495532
           },
           range: 522.0365799222782,
           tilt: 62.39511972890614,
           heading: -39.150149539328304,
       },
       point: { lat: 50.0703122, lng: 14.402668199999999, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/cz.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Denmark",
       details: "2, Sankt Petri Passage 5, 1165 København",
       camera: {
           center: {
               lat: 55.680359539635866,
               lng: 12.570460204526002,
               altitude: 30.447654757346044
           },
           range: 334.8786935049066,
           tilt: 55.38819319004654,
           heading: 149.63867461295067,
       },
       point: { lat: 55.6804504, lng: 12.570279099999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/dk.svg'),
           scale: 1.0,
       },
   },
   ,
   {
       name: "Google Greece",
       camera: {
           center: {
               lat: 38.038634694028055,
               lng: 23.802924946201266,
               altitude: 196.45884670344995
           },
           range: 343.57226336076565,
           tilt: 54.97375927639567,
           heading: -33.26775344055724,
       },
       point: { lat: 38.038619, lng: 23.8031622, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Germany",
       camera: {
           center: {
               lat: 53.55397683312404,
               lng: 9.986350507286808,
               altitude: 44.83610870143956
           },
           range: 375.3474077822466,
           tilt: 71.35078443829818,
           heading: -160.76930098951416,
       },
       point: { lat: 53.5540227, lng: 9.9863, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/de.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Ireland",
       camera: {
           center: { lat: 53.339816899999995, lng: -6.2362644, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 53.339816899999995, lng: -6.2362644, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ie.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Italy",
       camera: {
           center: {
               lat: 45.486361346538224,
               lng: 9.18995496294455,
               altitude: 138.55834058400072
           },
           range: 694.9398023590038,
           tilt: 57.822470255679114,
           heading: 84.10194883488619,
       },
       point: { lat: 45.4863064, lng: 9.1894762, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/it.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Lithuania",
       camera: {
           center: {
               lat: 54.698040606567965,
               lng: 25.30965338542576,
               altitude: 111.80276944294413
           },
           range: 412.5808304977545,
           tilt: 43.50793332082195,
           heading: -29.181098269421028,
       },
       point: { lat: 54.6981204, lng: 25.3098617, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/at.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Netherlands",
       camera: {
           center: {
               lat: 52.33773837150874,
               lng: 4.871754560171063,
               altitude: 53.68063996154723
           },
           range: 473.1982259177312,
           tilt: 56.216523350388634,
           heading: 71.78252318033718,
       },
       point: { lat: 52.337801, lng: 4.872065999999999, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/nl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Norway",
       camera: {
           center: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/no.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Poland",
       camera: {
           center: { lat: 52.22844380000001, lng: 20.9851819, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 52.22844380000001, lng: 20.9851819, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Portugal",
       camera: {
           center: {
               lat: 38.7240122810727,
               lng: -9.150628263172639,
               altitude: 55.299662291551044
           },
           range: 337.7474313328639,
           tilt: 56.79772652682846,
           heading: 176.0722118222208,
       },
       point: { lat: 38.723915999999996, lng: -9.150629, altitude: 35 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pt.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Romania",
       camera: {
           center: {
               lat: 44.43076650172983,
               lng: 26.109700164718586,
               altitude: 125.57895810814505
           },
           range: 364.25249956711923,
           tilt: 38.517539223834326,
           heading: -38.81294924429363,
       },
       point: { lat: 44.4309897, lng: 26.1095719, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ro.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Spain",
       camera: {
           center: {
               lat: 40.450078762608875,
               lng: -3.6930085080020856,
               altitude: 753.6446342341894
           },
           range: 845.7279793010093,
           tilt: 46.752510050599746,
           heading: 4.718779524265234,
       },
       point: { lat: 40.450294199999995, lng: -3.6927915, altitude: 175 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/es.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Sweden",
       camera: {
           center: {
               lat: 59.33313751316038,
               lng: 18.054618219238293,
               altitude: 16.728213706832868
           },
           range: 377.5210725830039,
           tilt: 63.59478230626709,
           heading: 98.53138488367703,
       },
       point: { lat: 59.3332093, lng: 18.0536386, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/se.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Switzerland",
       camera: {
           center: {
               lat: 47.365411056285275,
               lng: 8.525063594405356,
               altitude: 419.2348376754488
           },
           range: 166.74918737631742,
           tilt: 59.31431457129067,
           heading: -32.620415961949206,
       },
       point: { lat: 47.365452, lng: 8.5249253, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ch.svg'),
           scale: 1.0,
       },
   }
]

これで、画像のような完成したページが作成されます。ユーザーは任意の場所をクリックしてその場所に移動したり、その周辺を飛行したり、元の場所に戻ったりできます。

「スペインとスウェーデンのオフィス間を飛び回る。

Codelab はこれで終了です。次のセクションでは、この Codelab のまとめと、試す価値のある他の新機能について説明します。

セクションの解決策

このステップでは、実装を確認するためのソリューションとして、完成したページが提供されます。(コピーする場合は、必ず独自の API キーを使用してください)。

また、フラグの svg ファイル(または任意の png ファイル)を取得して、ページから見つけられるディレクトリに保存する必要があります(ここでは images フォルダに保存しています)。

<!DOCTYPE html>
<html>

<head>
   <title>Step 9 - More Places!</title>
   <style>
       body {
           height: 100vh;
           margin: 0;
       }
   </style>
</head>

<body>
   <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: "<INSERT API KEY>",
           v: "alpha",
           // 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>
       let map3D = null;

       const base = document.location.href.substr(0, document.location.href.lastIndexOf("/"));

       const europeCamera = {
           center: { lat: 46.717, lng: 7.075, altitude: 2175.130 },
           range: 5814650,
           tilt: 33,
           heading: 4.36,
       };

const officeLocations = [
   {
       name: "Google France",
       details: "8 Rue de Londres, 75009 Paris, France",
       camera: {
           center: { lat: 48.877276, lng: 2.329978, altitude: 48 },
           range: 178,
           tilt: 57.48,
           heading: -17,
       },
       point: { lat: 48.8775183, lng: 2.3299791, altitude: 60 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/fr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google UK",
       details: "6 Pancras Square, London N1C 4AG, UK",
       camera: {
           center: { lat: 51.5332, lng: -0.1260, altitude: 38.8 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 51.5332, lng: -0.1260, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gb.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Belgium",
       details: "Chau. d'Etterbeek 180, 1040 Brussel",
       camera: {
           center: { lat: 50.83930408436509, lng: 4.38052394507952, altitude: 64.38932203802196},
           range: 466.62899893119175,
           tilt: 43.61569474716178,
           heading: 51.805907046332074,
       },
       point: { lat: 50.8392653, lng: 4.3808751, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/be.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Czechia",
       details: "Stroupežnického 3191/17, 150 00 Praha 5-Smíchov",
       camera: {
           center: {
               lat: 50.07004093853976,
               lng: 14.402871475443956,
               altitude: 223.39574818495532
           },
           range: 522.0365799222782,
           tilt: 62.39511972890614,
           heading: -39.150149539328304,
       },
       point: { lat: 50.0703122, lng: 14.402668199999999, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/cz.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Denmark",
       details: "2, Sankt Petri Passage 5, 1165 København",
       camera: {
           center: {
               lat: 55.680359539635866,
               lng: 12.570460204526002,
               altitude: 30.447654757346044
           },
           range: 334.8786935049066,
           tilt: 55.38819319004654,
           heading: 149.63867461295067,
       },
       point: { lat: 55.6804504, lng: 12.570279099999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/dk.svg'),
           scale: 1.0,
       },
   },
   ,
   {
       name: "Google Greece",
       details: "Fragkokklisias 6, Athina 151 25",
       camera: {
           center: {
               lat: 38.038634694028055,
               lng: 23.802924946201266,
               altitude: 196.45884670344995
           },
           range: 343.57226336076565,
           tilt: 54.97375927639567,
           heading: -33.26775344055724,
       },
       point: { lat: 38.038619, lng: 23.8031622, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/gr.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Germany",
       details: "ABC-Straße 19, 20354 Hamburg",
       camera: {
           center: {
               lat: 53.55397683312404,
               lng: 9.986350507286808,
               altitude: 44.83610870143956
           },
           range: 375.3474077822466,
           tilt: 71.35078443829818,
           heading: -160.76930098951416,
       },
       point: { lat: 53.5540227, lng: 9.9863, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/de.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Ireland",
       details: "Gordon House, 4 Barrow St, Grand Canal Dock, Dublin 4, D04 V4X7",
       camera: {
           center: { lat: 53.339816899999995, lng: -6.2362644, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 53.339816899999995, lng: -6.2362644, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ie.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Italy",
       details: "Isola Building C, Via Federico Confalonieri, 4, 20124 Milano",
       camera: {
           center: {
               lat: 45.486361346538224,
               lng: 9.18995496294455,
               altitude: 138.55834058400072
           },
           range: 694.9398023590038,
           tilt: 57.822470255679114,
           heading: 84.10194883488619,
       },
       point: { lat: 45.4863064, lng: 9.1894762, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/it.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Lithuania",
       details: "Vilnius Tech Park, Antakalnis st. 17, 2nd building, LT-10312, Vilnius",
       camera: {
           center: {
               lat: 54.698040606567965,
               lng: 25.30965338542576,
               altitude: 111.80276944294413
           },
           range: 412.5808304977545,
           tilt: 43.50793332082195,
           heading: -29.181098269421028,
       },
       point: { lat: 54.6981204, lng: 25.3098617, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/at.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Netherlands",
       details: "Claude Debussylaan 34, 1082 MD Amsterdam",
       camera: {
           center: {
               lat: 52.33773837150874,
               lng: 4.871754560171063,
               altitude: 53.68063996154723
           },
           range: 473.1982259177312,
           tilt: 56.216523350388634,
           heading: 71.78252318033718,
       },
       point: { lat: 52.337801, lng: 4.872065999999999, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/nl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Norway",
       details: "Bryggegata 6, 0250 Oslo",
       camera: {
           center: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 59.90991209999999, lng: 10.726020799999999, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/no.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Poland",
       details: "Rondo Daszynskiego 2, 00-843 Warsaw",
       camera: {
           center: { lat: 52.22844380000001, lng: 20.9851819, altitude: 38.777415761228006 },
           range: 500,
           tilt: 56.21672368296945,
           heading: -31.15763027564165,
       },
       point: { lat: 52.22844380000001, lng: 20.9851819, altitude: 25 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pl.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Portugal",
       details: "R. Duque de Palmela 37 Piso 4, 1250-097 Lisboa",
       camera: {
           center: {
               lat: 38.7240122810727,
               lng: -9.150628263172639,
               altitude: 55.299662291551044
           },
           range: 337.7474313328639,
           tilt: 56.79772652682846,
           heading: 176.0722118222208,
       },
       point: { lat: 38.723915999999996, lng: -9.150629, altitude: 35 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/pt.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Romania",
       details: "Bulevardul Corneliu Coposu 6-8, București 030167",
       camera: {
           center: {
               lat: 44.43076650172983,
               lng: 26.109700164718586,
               altitude: 125.57895810814505
           },
           range: 364.25249956711923,
           tilt: 38.517539223834326,
           heading: -38.81294924429363,
       },
       point: { lat: 44.4309897, lng: 26.1095719, altitude: 75 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ro.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Spain",
       details: "Torre Picasso, Pl. Pablo Ruiz Picasso, 1, Tetuán, 28020 Madrid",
       camera: {
           center: {
               lat: 40.450078762608875,
               lng: -3.6930085080020856,
               altitude: 753.6446342341894
           },
           range: 845.7279793010093,
           tilt: 46.752510050599746,
           heading: 4.718779524265234,
       },
       point: { lat: 40.450294199999995, lng: -3.6927915, altitude: 175 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/es.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Sweden",
       details: "Kungsbron 2, 111 22 Stockholm",
       camera: {
           center: {
               lat: 59.33313751316038,
               lng: 18.054618219238293,
               altitude: 16.728213706832868
           },
           range: 377.5210725830039,
           tilt: 63.59478230626709,
           heading: 98.53138488367703,
       },
       point: { lat: 59.3332093, lng: 18.0536386, altitude: 50 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/se.svg'),
           scale: 1.0,
       },
   },
   {
       name: "Google Switzerland",
       details: "Brandschenkestrasse 110, 8002 Zürich",
       camera: {
           center: {
               lat: 47.365411056285275,
               lng: 8.525063594405356,
               altitude: 419.2348376754488
           },
           range: 166.74918737631742,
           tilt: 59.31431457129067,
           heading: -32.620415961949206,
       },
       point: { lat: 47.365452, lng: 8.5249253, altitude: 100 },
       pin: {
           background: 'white',
           glyph: new URL(base + '/images/ch.svg'),
           scale: 1.0,
       },
   }
]

       async function init() {
           const { Map3DElement, MapMode, Marker3DInteractiveElement } = await google.maps.importLibrary("maps3d");
           const { PinElement } = await google.maps.importLibrary('marker');

           map3D = new Map3DElement({
               ...europeCamera,
               mode: MapMode.SATELLITE,
           });

           officeLocations.forEach(office => {
               const marker = new Marker3DInteractiveElement({
                   position: office.point,
                   label: office.name,
                   altitudeMode: 'RELATIVE_TO_GROUND',
                   extruded: true,
               });

               marker.addEventListener('gmp-click', (event) => {
                   map3D.flyCameraTo({
                       endCamera: office.camera,
                       durationMillis: 2000,
                   });

                   map3D.addEventListener('gmp-animationend', () => {
                       map3D.flyCameraAround({
                           camera: office.camera,
                           durationMillis: 2000,
                           rounds: 1
                       });

                       map3D.addEventListener('gmp-animationend', () => {
                           map3D.flyCameraTo({
                               endCamera: europeCamera,
                               durationMillis: 2000,
                           });
                       }, { once: true });

                   }, { once: true });

                   event.stopPropagation();
               });

               const markerPin = new PinElement(office.pin);
               marker.append(markerPin);

               map3D.append(marker);
           });
           document.body.append(map3D);
       }
       init();
   </script>
</body>

</html>

12. 次のステップ

この Codelab では、Maps JavaScript API の 3D 機能の基本について学習しました。次は、以下の機能を地図に追加してみましょう。

  • オフィスを選択できるようにプルダウン リストを追加します。
  • 他のマーカー スタイル設定のオプションを使用して、さらに華やかにしましょう。
  • Maps JavaScript API のその他のライブラリで使用できる機能(プレイス ID を使用して各オフィスの評価を表示するなど)を確認する

Google Maps Platform とウェブ上の 3D を利用するその他の方法については、次のリンクをご覧ください。