やりたいこと
GoogleMapのAPIでは、Markerをクリック等したりするとInfoWindowと呼ばれる吹き出しが表示できます。
Reactでどのように実装すればよいか検索すると、Markerが単一のときの実装例はあるのですが、複数ある場合の実装例があまりなかったので紹介します。
前提等
- 地図用のライブラリとして、google-maps-reactを使います。
- ライブラリの使い方やReactの実装方式やMarkerのstateの管理は、【React】GoogleMapで地図をドラッグして移動した後にMarkerを更新すると同様とします。
- 実装についてStackOverflowの記事React and google-maps-react. Not displaying InfoWindowを参考にしています。
イメージ
複数Markerが表示されていて、Markerをクリックすると該当店舗の画像が表示されるイメージになります。
サンプル
※ reducerやstoreの実装内容は割愛
GoogleMapComponent.js
import React, { useContext, useState } from "react";
import { GoogleApiWrapper, InfoWindow, Marker, Map } from "google-maps-react";
import { MapStore } from "../../store/MapStore";
export const GoogleMapComponent = ({ google }) => {
const { state, dispatch } = useContext(MapStore);
const location = state.currentLocation;
var markerList = [];
// InfoWindowの情報はローカルステートで管理
const [infoWindowState, setInfoWindowState] = useState({
markerInfo: {},
visible: false,
});
// グローバルステートの情報でMarkerを作成
state.markerList.map((m, i) => {
return markerList.push(
<Marker
key={s.id}
name={s.id}
title={s.name}
label={s.name}
onClick={onMarkerClick}
position={{ lat: m.latitude, lng: m.longitude }}
/>
);
});
const onMarkerClick = (_, marker) => {
// markerListから該当のレコードを取得
const markerInfo = state.displayStoreList.find((m) => m.id === marker.name);
if (markerInfo) {
setInfoWindowState({
activeMarker: marker,
markerInfo: markerInfo,
visible: true,
});
}
};
function onInfoWindowClose() {
setInfoWindowState({
markerInfo: {},
visible: false,
});
}
return (
<Map
google={google}
zoom={15}
center={{ lat: location.latitude, lng: location.longitude }}
initialCenter={{ lat: location.latitude, lng: location.longitude }}
>
{markerList}
<InfoWindow
marker={infoWindowState.activeMarker}
onClose={onInfoWindowClose}
visible={infoWindowState.visible}
>
<img
src={infoWindowState.markerInfo.image}
alt={infoWindowState.markerInfo.name}
/>
</InfoWindow>
</Map>
);
};
export default GoogleApiWrapper({
apiKey: process.env.REACT_APP_GOOGLE_MAP_API_KEY,
})(GoogleMapComponent);