우리가 흔히 사용하는 지도 웹을 보면, 여러 가지 아이콘들로 지도를 컨드롤 할 수 있다.
따라서, 우리도 지난번 생성한 Map 객체를 컨트롤하여 아래와 같은 기능들을 구현해 보겠다.
1. Layer 추가/삭제 - 기본, 위성, 하이브리드
2. Zoom in/out
3. View reset
4. Coordinates 표시
5. Map Scale 표시
또한, 컨트롤 방법을 알아보며 사용될 map
객체는 지난번 생성하여 Context API로 생성한 전역 상태의 객체이므로 아래와 같이 불러오면 된다.
import { useContext, useState } from 'react';
import MapContext from 'context/maps/mapContext';
const { mapObj } = useContext(MapContext);
const { map } = mapObj;
이번 포스팅은 React+Next 프로젝트에 적용하는 방법은 생략하였다.
OpenLayers 메서드 중심으로 알아볼 거임, 아무튼 그럴 거임. 🎃
이제 여러 가지 컨트롤 방법을 알아보자~!!
map.addLayer()
map.removeLayer()
const satelliteMap = new TileLayer({
name: 'Satellite',
visible: true,
source: new XYZ({
url: `http://api.vworld.kr/req/wmts/1.0.0/${process.env.VWORLD_API_KEY}/Satellite/{z}/{y}/{x}.jpeg`
})
});
const handleSatelliteMapButton = () => {
map.addLayer(satelliteMap);
// or
map.removeLayer(satelliteMap)
}
const hybridMap = new TileLayer({
name: 'Hybrid',
visible: true,
source: new XYZ({
url: `http://api.vworld.kr/req/wmts/1.0.0/${process.env.VWORLD_API_KEY}/Hybrid/{z}/{y}/{x}.png`
})
});
const handleHybridButtonClick = () => {
map.addLayer(hybridMap);
// or
map.removeLayer(hybridMap);
};
여러 지도(Base, Satellite, Hybrid)에 맞는 형식은 Vworld 공식 문서에서 확인할 수 있다.
Vworld 공식 문서 - WMTS
map.getView().setView()
const handleZoomInClick = () => {
const zoom = map.getView().getZoom() + 1;
map.getView().setView(zoom);
};
const handleZoomOutClick = () => {
const zoom = map.getView().getZoom() - 1;
map.getView().setView(zoom);
};
const handleZoomInClick = () => {
const zoom = map.getView().getZoom() + 1;
map.getView().animate({
zoom,
duration: 500
});
};
const handleZoomOutClick = () => {
const zoom = map.getView().getZoom() - 1;
map.getView().animate({
zoom,
duration: 500
});
};
컨트롤에는 animation을 적용/미적용 할 수 있는데,
본 포스팅에서는 default 값으로 적용하였다. 조금 더 자연스럽게 변화하기 때문이다.
아래 컨트롤할 부분들도 동일하니 참고하면 좋겠다.
map.getView().setCenter()
const center = fromLonLat([126.30574134206182, 33.35570244202401]);
const handleHomeClick = () => {
map.getView().setCenter(center);
};
const center = fromLonLat([126.30574134206182, 33.35570244202401]);
const handleHomeClick = () => {
map.getView().animate({
center,
duration: 1500
});
};
지도에서 마우스 위치 값에 따른 경/위도를 표시해 주는 방법이다.
기존에 생성한 Map 객체에 값을 추가해 주어야 하며, Map 객체를 생성할 때처럼 Element도 추가해 주어야 한다.
// ./map/map.js
import { MousePosition } from 'ol/control';
import { createStringXY } from 'ol/coordinate';
const Map = ({ children }) => {
// ...
useEffect(() => {
// 마우스 위치에 따른 좌표값 생성
let mousePositionCtrl = new MousePosition({
coordinateFormat: createStringXY(4), // / 4: 좌표 소숫점 이하 자리수
projection: 'EPSG:4326', // 좌표계 변환
className: 'mouse-position', // style 적용할 className 설정
target: 'mouse-position', // element id 값
undefinedHTML: 'lon, lat' // 마우스 위치 값 없을 때 초기 값
});
// Map 객체 controls에 추가
const map = new OlMap({
controls: defaultControls({ zoom: false, rotate: false }).extend([mousePositionCtrl]),
// ...
});
// ...
}, []);
// ...
};
export default Map;
// ./pages/index.js
import Head from 'next/head';
import { useContext, useState } from 'react';
import MapContext from 'context/maps/mapContext';
export default function Home() {
const { mapObj } = useContext(MapContext);
const { map } = mapObj;
return (
<div>
<Head>
<title>OpenLayers Practice</title>
</Head>
<div id='map'></div>
<div id='mouse-position'></div>
</div>
);
}
OpenLayers 공식 문서 - MousePosition
import { ScaleLine } from 'ol/control';
const Map = ({ children }) => {
// ...
useEffect(() => {
// Map 객체 생성 후 Scale 추가
const map = new OlMap({
// ...
});
map.addControl(new ScaleLine());
// ...
}, []);
// ...
};
export default Map;
Scale를 추가하는 방법은 아주 간단하다. OpenLayers에서 제공해 주는 메서드를 사용하여 객체를 생성한 후 추가해 주면 된다.
하지만, css가 매우 이상하게 적용된다. 필자는 scale element의 className을 찾아서 새로 설정해 주었다.
.ol-scale-line
에 css를 적용할 수 있다.
OpenLayers와 조금은 친해진 것 같다 ^__^;
안녕하세요. 글 잘보고 갑니다. 혹시 point나 polygon 그리는 글도 올려주세요. 감사합니다. ^^;