Mapbox GL JS를 React의 함수 구성 요소로 표시
소개
이전에 투고한 React의 함수 구성 요소에서 Mapbox GL JS를 표시하는 데모 라고 하는 것이, 비교적 담백한 any를 사용하고 있거나 데모라고 말할 수 있을지 수상한 할 수 있었으므로, 그 리바이스를 겸해, 보다 넉넉한 샘플 구현을 나타냅니다.
조건
환경 구축
①React+Typescript 프로젝트 구축
npx create-react-app react-mapbox-demo --template typescript
※템플릿의대로라면 React의 형태 정의가 잘 적용되지 않을지도, 그 경우 다시
npm install
하면 괜찮습니다.②Mapbox GL JS와 형 정의를 인스톨
npm install [email protected] @types/mapbox-gl
③서버 세우다
npm start
구성 요소 샘플
import React, { useEffect, useState, useRef } from 'react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// Mapbox Style
const mapStyle: mapboxgl.Style = {
version: 8,
sources: {
OSM: {
type: 'raster',
tiles: ['http://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution:
'<a href="http://osm.org/copyright">© OpenStreetMap contributors</a>',
},
},
layers: [
{
id: 'OSM',
type: 'raster',
source: 'OSM',
minzoom: 0,
maxzoom: 18,
},
],
};
const Map: React.FC = () => {
// mapboxgl.Mapのインスタンスへの参照を保存するためのuseState
const [mapInstance, setMapInstance] = useState<mapboxgl.Map>();
// 地図表示するDiv要素を特定するためのuseRef
const mapContainer = useRef<HTMLDivElement | null>(null);
useEffect(() => {
// mapContainer.currentはnullになり得るので型ガード(ていねい)
if (!mapContainer.current) return;
const map = new mapboxgl.Map({
container: mapContainer.current, // ていねいな型ガードのおかげで必ずHTMLDivElementとして扱える、current!でも可
style: mapStyle,
center: [142.0, 40.0],
zoom: 4,
});
// mapboxgl.Mapのインスタンスへの参照を保存
setMapInstance(map);
}, []);
return <div style={{ height: 800 }} ref={mapContainer} />;
};
export default Map;
무사히 지도 화면이 표시되었습니다.
TIPS: 지도의 레이어 구성 조작에 대해
※이하의 구성은 상기의 코드 약간 다릅니다만, 말하고 싶은 것에 변함은 없으므로 적절히 읽어 주세요
실제 지도 애플리케이션 개발에서는 지도의 레이어 구성을 동적으로 업데이트하고 싶을 수 있습니다. Mapbox GL JS에서는, 그 때, addSource() 하고, addLayer() 하고, 하지만 그 때 source가 이미 존재하고 있으면… 그래서 이러한 API는 일절 사용하지 않고, Style 자체를 조작하는 방법을 추천합니다. 다음이 구현 예.
import React, { useEffect, useState, useRef } from 'react';
import styled from 'styled-components';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
const MapDiv = styled.div`
height: 800px;
`;
// Mapbox Style
const initMapStyle: mapboxgl.Style = {
version: 8,
sources: {
OSM: {
type: 'raster',
tiles: ['http://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution:
'<a href="http://osm.org/copyright">© OpenStreetMap contributors</a>',
},
},
layers: [
{
id: 'OSM',
type: 'raster',
source: 'OSM',
minzoom: 0,
maxzoom: 18,
},
],
};
const emptyMapStyle: mapboxgl.Style = {
version: 8,
sources: {},
layers: [],
};
const Map: React.FC = () => {
// mapboxgl.Mapのインスタンスへの参照を保存するためのuseState
const [mapInstance, setMapInstance] = useState<mapboxgl.Map>();
// 地図表示するDiv要素をHTML要素を特定するためのuseRef
const mapContainer = useRef<HTMLDivElement | null>(null);
// 地図スタイルをstate管理
const [mapStyle, setMapStyle] = useState<mapboxgl.Style>(initMapStyle);
const [flag, setFlag] = useState(false);
// mapStyleの変更時に走る処理
useEffect(() => {
if (!mapInstance) {
// nullチェック
return;
}
// MapインスタンスのsetStyle()を実行
mapInstance.setStyle(mapStyle);
}, [mapStyle]);
useEffect(() => {
// 初回時のみ走る処理
if (!mapInstance) {
if (!mapContainer.current) {
// mapContainer.currentはnullになり得るので型ガード
return;
}
const map = new mapboxgl.Map({
container: mapContainer.current, // 型ガードのおかげで必ずHTMLDivElementとして扱える
style: mapStyle,
center: [142.0, 40.0],
zoom: 4,
});
// mapboxgl.Mapのインスタンスへの参照を保存
setMapInstance(map);
}
}, [mapInstance]);
return (
<MapDiv
ref={mapContainer}
onClick={() => {
// 以下のようにReactのstateを操作するとMapインスタンス側でsetStyle()が走る
setMapStyle(flag ? emptyMapStyle : initMapStyle);
setFlag(!flag);
}}
/>
);
};
export default Map;
간단하게 OSM 스타일과 하늘 스타일을 오가는 샘플입니다만, React측의 변수의 조작만으로 Map 인스턴스의 setStyle()를 발화시킬 수가 있습니다. 데이터의 흐름도 매우 간단합니다 (React의 스타일 변수의 변경으로부터, 항상 한 방향으로 Map 인스턴스에 반영된다). 만약 여기저기에서 addSource()나 addLayer()를 반복하면(자), Style의 관리가 매우 복잡하게 됩니다(행수도 증가해 버려 아무것도 좋은 일이 없습니다).
이것은 라이브러리 자체의 할 수 있다고 생각합니다만, setStyle()는 스타일 전부를 재렌더링하는 일은 없고, 변경 부분만을 다시 그려 주는 것 같기 때문에 퍼포먼스에의 영향은 없습니다(아마).
Reference
이 문제에 관하여(Mapbox GL JS를 React의 함수 구성 요소로 표시), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/Kanahiro/items/cddabb26f3faf77dd81d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)