🗺️

React Google Maps ライブラリ で Photorealistic 3D マップを表示する

2024/08/20に公開

こんにちは
クラウドエース株式会社 フロントエンド・UI/UX 部の雪村です。

Google Maps Platform の Maps JavaScript API に Photorealistic 3D Maps 機能が追加されました
(2024/6/17 現在 pre-GA(一般提供前)の試験運用版です。)
今回はこの機能を React Google Maps ライブラリを使用してお試しする方法をご紹介します。

この記事で嬉しいこと

最近リリースされた React Google Maps ライブラリを利用した React アプリケーションを構築しつつ、Google Maps Platform の新機能を試すことができるようになります。

今後、新しい機能がリリースされた場合も、ライブラリの更新を待たずに試すことができます。

3D Maps 機能について

3D Maps 機能は従来の 2D マップ表示とは異なり、Maps を 3D で表示することができる機能です。Google Maps Platform が持つ建物の 3D データが Maps に反映されています。
追加でポリラインやポリゴンも 3D マップ上で表現できるため、今までよりも表現が豊かになります。

具体的には以下のようなメリットがあるのかなと思います。

  • 「このビルの〇階」という表現をビルの立体的な形と位置で示すことができる
  • イベント会場までの道のりにあるランドマークを分かりやすく示すことができる

3D Maps の導入

React で Google Maps Platform を導入する際には React Google Maps ライブラリを使用することができます。

しかし、3D Maps 機能については 2024年6月17日現在、ライブラリから使用することはできません。
そこで React Maps Platform ライブラリを使用しつつ、3D Maps 機能など試験的な機能を試す方法についてご紹介します。

React Google Maps ライブラリの導入

React Google Maps ライブラリ @vis.gl/react-google-maps をインストールします。

npm install @vis.gl/react-google-maps

APIProvider の使用

ライブラリのインストールが完了したら、コンポーネントを用意していきます。
APIProvider コンポーネントを使用すると、Maps JavaScript API のインストールが簡単に行えます。

api-provider.tsx
<APIProvider apiKey={apiKey}>
  // この中に Maps や  AdvancedMarker を記載すると、地図やマーカーを表示できる
</APIProvider>

前述した通り Photorealistic 3D Maps 機能についてはライブラリで用意されていないため、
ここからは少しトリッキーな手段で導入します。

今回のようにまだパブリックリリースになっていない機能を使用する場合、
APIProvider のオプションで alpha を指定します。

api-provider-option.tsx
<APIProvider apiKey={apiKey} version="alpha">
</APIProvider>

もう一つオプションを追加します。
libraries3d-maps を指定します。

api-provider-option-2.tsx
<APIProvider apiKey={apiKey} version="alpha" libraries={['maps3d']}>
</APIProvider>

これで準備は完了です。

上記の 2つを指定したものをスクリプト読み込みタグを使用した場合は以下のようになります。
(現在は Dynamic Library Import が推奨されていますが、個人的に慣れている方でご紹介します。)

script-load.html
<script async src="https://maps.googleapis.com/maps/api/js?key=<YOUR_KEY>&v=alpha&libraries=maps3d"></script>

<gmp-map-3d> の導入

APIProvider コンポーネント内で <gmp-map-3d> を使用することができます。

実装時、少し詰まるポイントとして TypeScript を使用した場合、Linter で警告が出ることがあります。

少し強引ですが、型を any に定義して対応します。

gmp-map-3d.tsx
declare global {
  namespace JSX {
    interface IntrinsicElements {
      'gmp-map-3d': any;
      'gmp-polygon-3d': any;
    }
  }
}

gmp-polygon-3d は 3D マップ上でポリゴンを表示するためのタグです。
こちらも警告が出ていたので、回避策として any で定義しています。

繰り返しになりますが、試験的に導入するための暫定的な対応です。
本番環境での導入をお考えの方は、3D Maps 機能が正式リリースを待ち、
型を明確に定義しましょう。

コードサンプル

東京タワーをポリゴンで囲うサンプルをご紹介します。

tokyo-tower.tsx
declare global {
  namespace JSX {
    interface IntrinsicElements {
      'gmp-map-3d': any;
      'gmp-polygon-3d': any;
    }
  }
}

import { APIProvider } from '@vis.gl/react-google-maps';
import { useEffect, useState } from 'react';


export default function MapView3d({ apiKey }: { apiKey: string }) {
  const [polygons, setPolygons] = useState([] as any[]);
  const [steadyChangeEvent, setSteadyChangeEvent] = useState(false);

  useEffect(() => {
    google.maps.importLibrary('maps3d').then(({ SteadyChangeEvent }: any) => {
      setSteadyChangeEvent(SteadyChangeEvent.isSteady);
      setPolygons(document.querySelector('gmp-polygon-3d') as any);
  });

  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);  

  useEffect(() => {
    if (polygons) {
      (polygons as any).outerCoordinates = [
        { lat: 35.6595, lng: 139.74484, altitude: 333 },
        { lat: 35.6587191, lng: 139.7465, altitude: 333 },
        { lat: 35.6575, lng: 139.746, altitude: 333 },
        { lat: 35.658535, lng: 139.744, altitude: 333 },
      ];
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [steadyChangeEvent]);

  return (
    <>
      <APIProvider apiKey={apiKey} version="alpha" libraries={['maps3d']}>
        <div className="grid grid-cols-4 h-screen">
          <div className="col-span-1 p-4 max-h-svh overflow-auto bg-white">
            <div className="block mb-4">
              <p className="text-gray-700 font-bold my-8">操作方法</p>
              <p className="text-gray-700 my-4">
                左クリックしながらマウス操作で地図移動 <br /><br />
                マウスホイールでズームイン/アウト <br /><br />
                マウスホイールを押しながらマウス操作で地図の回転 <br />
              </p>
            </div>
          </div>
          <div className="col-span-3 block w-full h-full">
            <gmp-map-3d center="35.654, 139.746, 525" tilt="60">
              <gmp-polygon-3d altitude-mode="relative-to-ground" fill-color="#ff0000" fill-opacity="0.5" stroke-color="#0000ff" stroke-width="8" extruded></gmp-polygon-3d>
            </gmp-map-3d>
          </div>
        </div>
      </APIProvider>
    </>
  );
}

このような画面が表示されると思います。
(プレビュー段階のため表示が変更になる場合があります。)

Photorealistic 3D Maps demo

ポリゴンについて

ポリゴンについて少しだけ解説します。

(polygons as any).outerCoordinates = [
  { lat: 35.6595, lng: 139.74484, altitude: 333 },
  { lat: 35.6587191, lng: 139.7465, altitude: 333 },
  { lat: 35.6575, lng: 139.746, altitude: 333 },
  { lat: 35.658535, lng: 139.744, altitude: 333 },
];

ポリゴンは地図上の点と点を結んでいき、3点以上結んだ時にできる面のことです。
この場合は4点を指定しているので、四角形ができます。

3D の場合は緯度経度に加えて高さ(altitude)を指定することで立体を表現できます。
高さを 333m に指定しているので、ちょうど東京タワーと同じ高さの立体ポリゴンを表現できますね。

まとめ

今回は Photorealistic 3D Maps と、プレビュー段階のサービスのお試し方法についてご紹介しました。

マップが 3D になることで高さを表現することができることで表現の幅は一気に拡がります。
まだまだ試験的な段階ではありますが、今のうちに色々な表現方法を考えていきたいですね!

参考

Discussion