前回記事に引き続き、ReactでGoogleMapsAPIを触っていきます。
今回はカスタムコントロールを追加してみます。
地図の上部にInputボックスを入れるこんなやつを作ります。
前回作ったコンポーネントの確認
こんな感じでTest.jsとMap.jsを作ってました。
前回記事でMarkerコンポーネントを作っていますが、今回はここは無関係。
Test.js
import { Wrapper} from "@googlemaps/react-wrapper";
import Map from "./Map";
import Marker from "./Marker";
export default function Test(){
const positions =[
{
lat: 35.6809591,
lng: 139.7673068,
},
{
lat: 35.675069,
lng: 139.763328,
}
]
return (
<Wrapper apiKey={"ここにAPIkey"} >
<MyMap>
{positions.map(p=><Marker position={p}/>)}
</MyMap>
</Wrapper>
)
}
Map.js
import React,{useRef,useEffect,useState} from 'react';
export default function Map({children}){
const ref = useRef(null);
const [map, setMap] = useState();
useEffect(() => {
if (ref.current && !map) {
setMap(new window.google.maps.Map(ref.current, {
center:{
lat: 35.6809591,
lng: 139.7673068,
},
zoom:14,
mapTypeControl: false,
streetViewControl: false,
fullscreenControl: false,
}));
}
}, [ref, map]);
return( <>
<div ref={ref} style={{height:500, width:500}} />
{React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { map });
}
})}
</>
)
}
SearchBoxコンポーネントを作る。
地図内の上部に表示する検索窓を作るため、コンポーネントを作ります。
SearchBox.js
import React,{useRef,useEffect,useState} from 'react';
export default function SearchBox(props){
const searchRef = useRef(null);
useEffect(() => {
if (props.map) {
props.map.controls[google.maps.ControlPosition.TOP_CENTER].push(searchRef.current);
}},[props.map])
return(
<input
type="text"
placeholder="ここに入力してください!"
ref={searchRef}
style={{
border : "2px solid #fff",
borderRadius : "3px",
boxShadow : "0 2px 6px rgba(0,0,0,.3)",
marginTop : "8px",
textAlign:"center",
width:400,
height:40,
}}
/>
)
}
2点ほどポイントを説明すると、
#####親コンポーネント(Test.js)から子コンポーネント(Search.js)にmapインスタンスを渡す
前回記事でMarkerを追加した際にTest.jsは以下のように子コンポーネントにmapインスタンスを渡せるようにしました。
Test.js
return( <>
<div ref={ref} style={{height:500, width:500}} />
{React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { map });
}
})}
</>
)
上記により子コンポーネント(SearchBox)では受け取ったmapが使える。
SearchBoxコンポーネント内、useEffectを用いて以下を記載することで、地図内上部中央にカスタムコントロールを表示できます。
SearchBox.js
useEffect(() => {
if (props.map) {
props.map.controls[google.maps.ControlPosition.TOP_CENTER].push(searchRef.current);
}},[props.map])
親コンポーネントを書き換える。
SearchBoxを作ったので親コンポーネントである(Test.js)に追加します。
import { Wrapper} from "@googlemaps/react-wrapper";
import Map from "./Map";
import Marker from "./Marker";
import SearchBox from "./SearchBox";
export default function Test(){
const positions =[
{
lat: 35.6809591,
lng: 139.7673068,
},
{
lat: 35.675069,
lng: 139.763328,
}
]
return (
<Wrapper apiKey={"ここにAPIキー"} >
<Map>
{positions.map((p,index)=><Marker position={p} key={index}/>)}
<SearchBox/>
</Map>
</Wrapper>
)
}