📖

ReactでGoogleMapの実装をしてみた

2022/12/21に公開

https://qiita.com/advent-calendar/2022/miraito-inc

はじめに

web制作をメインでやっていた時に毎回と言うほどGoogleMapのカスタムを実装していました。

当時はJqueryで実装していたのですが、Reactの場合はどんな感じで実装するんだろうと気になって試してみました!

この記事でわかること

  • Reactを使ったGoogleMapの実装
  • 簡単なカスタマイズ方法

事前準備編

GoogleMapを描画するライブラリを探す

選定をnpmtrends使って簡単に行いました。

DL数と更新頻度が新しいreact-google-maps-apiを使う事にしました。
https://github.com/JustFly1984/react-google-maps-api

GoogleMapを表示する時に使うGoogle Maps API Keyを取得する

API Keyがないと地図を描画できないため、取得します。

手順は公式のドキュメントを見ながら出来ました。
カードの登録が必要だから、ちょっとだけ手間。
https://developers.google.com/maps/documentation/javascript/get-api-key

実装編

Reactは18を使います。
スタイルはChakra UIを使ってやっていきます。

GoogleMapを表示する

ミライトデザインの事務所を初期位置にして地図を表示してみましょう。


地図が表示される事を確認

ソースコードはこちら。
https://github.com/bucchi-kitamura/react-google-map/blob/4ddf179690b0b1101d9e4be6f21e2772a8538eda/src/Components/useMap.ts#L11-L26

補足しておくと、公式のデモコードはLoadScriptを使っていますが、useJsApiLoaderで実装するのが新しい書き方っぽいのでそちらを使っています。
https://react-google-maps-api-docs.netlify.app/#section-getting-started

実装したコードは以下のコミットに入っています。
https://github.com/bucchi-kitamura/react-google-map/commit/912d89ff64b0f6408490106206fd8bf14fdee768

今のままだと、どの場所を表示しているのかわからないので改善しましょう。

マーカーを設置する

MarkerComponentを使います

MarkersOnGoogleMap.tsx
+ const markerLabel: google.maps.MarkerLabel = {
+    text: "ミライトデザイン",
+    fontFamily: "sans-serif",
+    fontSize: "15px",
+    fontWeight: "bold",
+  };

  return (
    <>
      {isLoaded ? (
        <GoogleMapComponent mapContainerStyle={containerStyle} onLoad={onLoad}>
+          <MarkerF position={props.defaultPosition} label={markerLabel} />
        </GoogleMapComponent>
      ) : (
        "loading"
      )}
    </>
  );

見慣れた赤いピンが出てきましたね。テキストも挿入できます。
このままだと見た目がよろしくないので実用的ではないですね。

名前とかではなくてA・B・Cとか1・2・3みたいに1文字で使いたい時に使うものかもしれないですね🤔

マーカーにホバーした時に吹き出しを表示するみたい事も出来るようなので、合わせ技なら使い道は全然ありそうです。

実装したコードは以下のコミットに入っています。
https://github.com/bucchi-kitamura/react-google-map/commit/94b199e5f63d3563e77fe941c3efcdceeda1f75b

吹き出しを設置する

infowindowComponentを使います。
吹き出しの中には自由にhtmlを設置出来るので、こちらの方が使い勝手は良さそうですね。

サンプルでは1つしか書いていないですが、複数の設置も可能です。

InfoBoxOnGoogleMap.tsx
  return (
    <>
      {isLoaded ? (
        <GoogleMapComponent mapContainerStyle={containerStyle} onLoad={onLoad}>
+	<InfoWindowF position={props.defaultPosition}>
+            <>
+              <Text
+                fontSize={16}
+                as={"p"}
+                align={"center"}
+                fontWeight={"bold"}
+                color={"green.400"}
+              >
+                会社のロゴ
+              </Text>
+              <img
+                width="150px"
+                src="https://miraito-+inc.co.jp/images/fix_logomark_A_flat%20.png"
+                alt=""
+              />
+            </>
+          </InfoWindowF>
        </GoogleMapComponent>
      ) : (
        "loading"
      )}
    </>
  );

GoogleMapのデザインを変える

web制作していた時に毎回やってたやつ。
意外と知らない人もいるかもしれないですが、GoogleMapのデザインってカスタマイズ出来るんです。

自分はよくこのサイトを使ってました。
ベースとなるデザインをここから選定して、細かいデザインの調整をするって感じの使い方をしてました。
https://snazzymaps.com/

適当に好きなデザインを選択して、左下にあるソースコードをコピーしましょう。

InfoBoxOnGoogleMap.tsx
+ import { InterfaceMap } from "./GoogleMapStyles";
+ const googleMapOptions = {
+  styles: InterfaceMap,
+};

  return (
    <>
      {isLoaded ? (
        <GoogleMapComponent
+         options={googleMapOptions}
          zoom={zoom}
          mapContainerStyle={containerStyle}
          onLoad={onLoad}
        ></GoogleMapComponent>
      ) : (
        "loading"
      )}
    </>
  );


デフォルト


Interface map


Subtle Grayscale

自分はInterface mapが見やすくて好きですね。
こんな感じでサイトのコンセプトに合わせたデザインにしたい時はsnazzymapsを使ってベースとなるスタイルを選定するのはおすすめです。

GoogleMapStyles.tsの中身はここに置いてます。
https://github.com/bucchi-kitamura/react-google-map/blob/dd6be741cd9010d9e8ce43fda410ad0ddc113266/src/Components/GoogleMapStyles.ts

終わりに

ライブラリの使い方自体に手こずりはしましたが、実装は割とサクッといけました。

ドキュメントにもReact18用の実装方法を書いてあったらハマらなくて良かったのですが、ドキュメントの更新が追いついていないのかもしれないですね。

困った時はissueから情報を得るというのが経験として入ったので良しとしましょう。

もう少し凝った実装を紹介したいのですが長くなりそうなので別の記事にしようかと思います。
DirectionsApiを使ってルート検索も出来るみたいなので試してみたいです。

次はtomoさんによる【MySQL】UNION,UNION ALLのクエリ実行速度比較の記事になります!

Discussion