投稿日:2021年3月29日
この記事では前回のPart1のMapの描画位置を動かした際に処理を追加する方法について解説しています。コードはPart1のものを使いまわします。
記事のサンプル中のコードは有料のAPIを使うことに注意してください。
Google Maps APIは月$200ドルまで無料枠として利用できるためローカルで動かす分にはほとんど問題になりませんがその都度GoogleMapsPlatformでAPIの利用回数は確認しておきましょう。
この記事のコードは以下の環境で確認されています。
はじめに簡単に解説します。
GoogleMapReactコンポーネントのonChangeプロパティに関数を渡すことでマウスやジェスチャで地図の描画位置などが変更された際にカスタムの処理を加えることができます。
表示している地図の位置や範囲などを取得したい場合にはこのプロパティを利用しましょう。
※onBoundsChangeというプロパティもMapの状態が変更された際の処理を組み込めますが、これは現在非推奨です。onChangeを使ってください。
前回のPartで作成したコンポーネントに以下のような機能を追加します。
では早速onChangeプロパティを使って希望の機能を作成しましょう。
import React, { useEffect, useState } from "react";
import GoogleMapReact, { ChangeEventValue } from "google-map-react";
/**
* Mapに使用するプロパティ
*/
interface MapProps {
center: {
lat: number;
lng: number;
};
zoom: number;
}
/**
* MapのPropsの初期値
*/
const initialMapProps: MapProps = {
center: {
lat: 35.39,
lng: 139.44,
},
zoom: 18,
};
/**
* APIキー
*/
const API_KEY = "************"; // TODO: 自分のキーをここに入力
/**
* サンプルとして地図を表示するコンポーネント
*/
const SampleMap = () => {
const [mapProps, setMapProps] = useState<MapProps>(initialMapProps);
/**
* 地図の状態が変更された際にstateを更新する
* @param v
*/
const changeMap = (v: ChangeEventValue) => {
const nextMapProps = {
center: v.center,
zoom: v.zoom,
};
setMapProps(nextMapProps);
};
useEffect(() => {
// TODO: 表示位置に合わせて処理を入れる
console.log(mapProps);
}, [mapProps]);
return (
<div style={{ width: "100vw", height: "100vh" }}>
({mapProps.center.lat},{mapProps.center.lng}),zoom:{mapProps.zoom}
<GoogleMapReact
bootstrapURLKeys={{ key: API_KEY }}
defaultCenter={mapProps.center}
defaultZoom={mapProps.zoom}
onChange={changeMap}
/>
</div>
);
};
export default SampleMap;
これでMapの表示位置の変更にたいしてコンポーネントのstateが更新されるようになりました。
更新されるstateとその他のGoogle Maps APIを活用することで様々な機能を実装できるようになります。
ここでは例としてGeoconding APIを使ってみます。
以下のコードを動かすにはGoogleMapPlatformでGeocoding APIを有効化する必要があります。
import React, { useEffect, useState } from "react";
import GoogleMapReact, { ChangeEventValue } from "google-map-react";
/**
* GeoLocationAPIのレスポンス
* 今回使うな部分のみ
*/
interface GeocodingAPIResponse {
plus_code: {
compound_code: string;
global_code: string;
};
}
/**
* Mapに使用するプロパティ
*/
interface MapProps {
center: {
lat: number;
lng: number;
};
zoom: number;
}
/**
* MapのPropsの初期値
*/
const initialMapProps: MapProps = {
center: {
lat: 35.39,
lng: 139.44,
},
zoom: 18,
};
/**
* APIキー
*/
const API_KEY = "********"; // TODO: 自分のキーをここに入力
/**
* サンプルとして地図を表示するコンポーネント
*/
const SampleMap = () => {
const [mapProps, setMapProps] = useState<MapProps>(initialMapProps);
const [location, setLocation] = useState<string>("");
/**
* 地図の状態が変更された際にstateを更新する
* @param v
*/
const changeMap = (v: ChangeEventValue) => {
const nextMapProps = {
center: v.center,
zoom: v.zoom,
};
setMapProps(nextMapProps);
};
/**
* GeocodingAPIを使って現在の地図の中心を表す文字列を返す
* @returns
*/
async function callGeocodingAPI(): Promise<GeocodingAPIResponse> {
const url = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${mapProps.center.lat},${mapProps.center.lng}&key=${API_KEY}`;
const response = await fetch(url);
const body = (await response.json()) as GeocodingAPIResponse;
return body;
}
/**
* 地図の表示が変更された時locationを更新する
*/
useEffect(() => {
const callAPI = async () => {
const response = await callGeocodingAPI();
setLocation(response.plus_code.compound_code);
};
callAPI();
}, [mapProps]);
/**
* 描画
*/
return (
<div style={{ width: "100vw", height: "100vh" }}>
({mapProps.center.lat},{mapProps.center.lng}),zoom:{mapProps.zoom}
{location}
<GoogleMapReact
bootstrapURLKeys={{ key: API_KEY }}
defaultCenter={initialMapProps.center}
center={mapProps.center}
defaultZoom={initialMapProps.zoom}
zoom={mapProps.zoom}
onChange={changeMap}
/>
</div>
);
};
export default SampleMap;
このコンポーネントは下の様に中心の地名を表示してくれます。
上の例では地図をいじるたびに毎回有料のAPIが呼ばれてしまいます。
本来このような呼び方は無駄にお金がかかるため理想的では無いことに注意してください。