React와 OpenLayers를 사용한 기능 포스팅을 몇 개 올렸지만 가장 기본적인 지도를 화면에 출력하는 방법에 대한 포스팅을 이제 올리게 되었다.
여기서 React의 provider와 context 개념이 필요한데, 이에 대해서는 후에 다른 포스팅으로 자세히 설명하려고 한다.
프로젝트 생성 및 라이브러리 설치
프로젝트 생성
npx create-react-app react-context-openlayer
cd react-context-openlayer
OpenLayers 라이브러리 설치
npm install ol
yarn과 npm이 있는데 npm을 사용하여 OpeLayers 라이브러리인 ol을 설치하였다.
화면에 Map 출력하기
MapContext 생성
./Map/MapContext.js
import React from "react";
const MapContext = new React.createContext({});
export default MapContext;
MapContext는 map 객체를 저장할 저장소로 보면 된다.
Map Provider 생성
MapContext에서 지도(sampleMap)을 쉽게 핸들링할 수 있도록 하는 Provider를 작성한다.
OpenLayers 객체를 통해 초기에 셋팅해야 할 사항들을 설정해주고 지도를 Provider에 저장한다.
./Map/SampleMap.jsx
import { useEffect, useState } from "react"
import { Map as OlMap, View } from 'ol';
import { defaults as defaultControls } from 'ol/control';
import { fromLonLat, get as getProjection } from 'ol/proj';
import { Tile as TileLayer } from 'ol/layer';
import { OSM } from 'ol/source';
import MapContext from "./MapContext";
import 'ol/ol.css';
const SampleMap = ({children}) => {
const [mapObj, setMapObj] = useState({});
useEffect(() => {
// Map 객체 생성 및 OSM 배경지도 추가
const sampleMap = new OlMap({
controls: defaultControls({zoom: false, rotate: false}).extend([]),
layers: [
new TileLayer({
source: new OSM(),
})
// 지도를 그리는 layer
],
target: 'sampleMap', // 하위 요소 중 id가 sampleMap인 element가 있어야 함
// 처음 지도가 로딩될 때 기준이 될 중심 좌표와 좌표계
view: new View({
projection: getProjection('EPSG:4326'),
center: fromLonLat([126.9706440, 37.5545380], getProjection('EPSG:4326')),
zoom: 19,
}),
});
setMapObj({sampleMap});
return () => sampleMap.setTarget(undefined);
}, []);
// MapContext.Provider에 객체 저장
return <MapContext.Provider value={mapObj}>{children}</MapContext.Provider>
};
export default SampleMap;
OSM은 OpenStreetMap에서 제공되는 지도 source이다.
TileLayer 외에 다른 Layer와 지도 source를 사용하여 지도 레이어를 만들 수 있다.(VWorld, Google 지도 등)
그 밖에 layers[] 배열 내부에 다른 원하는 레이어들을 추가하여 지도가 처음 로드될 때 레이어들을 초기화할 수 있다.
Map 가져오기
./Map/index.js
export {default as SampleMap} from "./SampleMap";
Provider를 import 할 때 경로만을 가져올 수 있도록 한다.
./index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { SampleMap } from './Map';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<SampleMap>
<App />
</SampleMap>
</React.StrictMode>
);
reportWebVitals();
프로젝트가 처음 생성될 때 만들어지는 index 파일에 앞에서 만든 Context.Provider로 자식요소를 감싼다.
Provider에서 저장한 객체를 사용하기 위해서는 위와 같이 자식요소를 Provider로 감싸야 한다.
./App.js
import { useContext } from "react";
import MapContext from "./Map/MapContext";
function App() {
// context에 저장되어 있는 객체를 가져옴
const { sampleMap } = useContext(MapContext);
// zoom-in
const handleZoomInClick = () => {
sampleMap.getView().setZoom(sampleMap.getView().getZoom() + 1);
};
// zoom-out
const handleZoomOutClick = () => {
sampleMap.getView().setZoom(sampleMap.getView().getZoom() - 1);
};
return (
<>
<button onClick={handleZoomInClick}>zoomIn</button>
<button onClick={handleZoomOutClick}>zoomOut</button>
<div id="sampleMap" style={{width:'100%', height:600}} />
</>
);
}
export default App;
zoomIn과 zoomOut 버튼까지 생성하여 지도를 출력할 수 있다.
지도의 height 설정을 부여하지 않으면 지도가 보이지 않기 때문에 높이를 지정해주어야 한다.
번외
지도에서 내가 보고 있는 위치가 어디인지 지도로 바로 확인하고 싶을 땐 provider를 만들 때 해당 요소를 함께 초기화하여 저장하면 된다.
아래 작성된 코드의 기능은 지도 위에 마우스 커서를 올렸을 때 커서가 지도에서 어느 좌표인지를 알려주는 기능이다.
import { defaults as defaultControls, MousePosition } from 'ol/control';
// ...
const mousePositionControl = new MousePosition({
coordinateFormat: (coordinate) => {
const formattedCoordinate = coordinate.map((coord) => coord.toFixed(8));
return formattedCoordinate.toString();
},
projection: 'EPSG:4326',
className: 'custom-mouse-position',
target: document.getElementById('mouse-position'),
});
const sampleMap = new OlMap({
controls: defaultControls({zoom: false, rotate: false}).extend([mousePositionControl]),
// ...
useEffect 내부의 지도를 생성하는 변수를 초기화 하기 전 mousePosition API(mousePositionControl)를 추가한다.
이 API를 지도에 추가하면 지도 왼쪽 상단에 마우스 커서가 위치한 좌표가 무엇인지 출력된다.
[ 참고 ]
https://songjang.tistory.com/25
https://openlayers.org/en/latest/examples/mouse-position.html
'공부 기록 > GIS' 카테고리의 다른 글
[OpenLayers] 한 지도에서 여러 개의 레이어 지우기 (0) | 2024.04.09 |
---|---|
[OpenLayers] 특정 레이어와 레이어의 marker 제거하기 (2) | 2023.11.27 |
[OpenLayers] 지도에 geoServer의 WMS 레이어 적용하기 (0) | 2023.11.09 |
[OpenLayers] 지도 클릭시 좌표 출력하기 (0) | 2023.10.26 |
[OpenLayers] OpenLayers의 특정 Layer만 선택(select)하기 (0) | 2023.06.26 |