- OpenLayers를 여행하는 개발자를 위한 안내서 - 25. WebGL로 초대용량 데이터 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 24. Heat Map 표현하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 23. Cluster Map 표현하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 22. WFS Transaction으로 데이터 삭제하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 21. WFS Transaction으로 데이터 수정하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 20. WFS Transaction으로 데이터 추가하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 19. WMS에 팝업 붙이기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 18. WFS에 팝업 붙이기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 17. WFS 객체에 상호작용 추가하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 16. WMS GetImage를 사용하여 지도에 이미지 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 15. WFS GetFeature를 사용하여 지도에 객체 표시하기
👀 OpenLayers를 여행하는 개발자를 위한 안내서 - 14. 지도에 사용자의 위치 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 13. 브라우저에서 사용자 위치정보 수집하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 12. 맵의 유용한 정보 표시하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 11. VWorld 맵 만들기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 10. Open Street Map(OSM) 맵 만들기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 9. 데이터 필터링하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 8. 공간정보 데이터를 주문하는 법. OGC
- OpenLayers를 여행하는 개발자를 위한 안내서 - 7. 공간정보 데이터를 관리하는 법. GeoServer
- OpenLayers를 여행하는 개발자를 위한 안내서 - 6. 공간정보의 DB화
- OpenLayers를 여행하는 개발자를 위한 안내서 - 5. OpenLayers
- OpenLayers를 여행하는 개발자를 위한 안내서 - 4. QGIS 체험하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 3. 좌표계
- OpenLayers를 여행하는 개발자를 위한 안내서 - 2. GIS랑 인사하기
- OpenLayers를 여행하는 개발자를 위한 안내서 - 1. 머릿말
Table of Contents
지오로케이션 응용하기 🔗
사용자의 위치를 기반으로 다양한 서비스를 제공할 수 있겠지만, 그 중에서 가장 기본적인 기능은 사용자의 위치를 지도 상에 직접 표시하는 것이다.
이전 장에서 설명한 지오로케이션을 토대로, OpenLayers를 활용하여 위치를 지도에 표시한다.
지도에 사용자의 위치를 표시한다는 것은 곧 피쳐(Feature)를 하나 추가한다는 의미다. 피쳐를 관리하는 1차적인 주체는 소스고, 소스는 레이어가 관리하므로, 피쳐를 추가할 레이어를 선택하는 것이 우선이다.
이를 위해, 사용자의 위치 표시용 레이어를 추가하는 작업이 선행되야한다. 이후 해당 레이어에 피쳐를 추가하면 된다. 따라서 아래와 같은 동작 흐름을 가진다.
- 버튼 컴포넌트의 렌더링 과정에서, 전용 레이어로 사용할
VectorLayer
를 하나 추가한다. - 버튼 클릭 시, 지오로케이션을 수행하여 사용자의 위치를 구한다.
VectorSource
를 생성하여 레이어에 추가한다.- 사용자의 위치를 활용하여
Feature
를 생성한다. - 생성한 피쳐를
VectorSource
에 추가한다.
"기존에 이미 추가된 레이어를 활용하면 되지 않나?"라고 생각할 수도 있겠지만, 전용 레이어를 하나 두는 것이 관리 측면에서 훨씬 유용하다.
기존의 레이어를 활용할 경우, 해당 레이어가 원래 지니고있던 Source
객체에 원치않는 영향을 줄수도 있으며, 레이어들 중 VectorLayer
가 없을 경우 결국 하나 추가해줘야한다.
현재 위치 이동 및 표시 버튼 컴포넌트 만들기 🔗
TSX
0 | /** |
1 | * 위치 마커 추가 버튼 Element 반환 메서드 |
2 | * |
3 | * @param {SubProps} props: 프로퍼티 |
4 | * |
5 | * @returns {JSX.Element} Element |
6 | */ |
7 | export function LocationWithMarker({ map }: SubProps) |
8 | { |
9 | // 맵 객체가 유효할 경우 |
10 | if (map) |
11 | { |
12 | // 드래그 할 경우, 레이어의 Feature를 전부 초기화 |
13 | map.on('pointerdrag', () => |
14 | { |
15 | map.getAllLayers().filter(layer => layer.get('name') === 'location')[0].getSource().clear(); |
16 | }); |
17 | |
18 | // location 벡터 레이어가 없을 경우 |
19 | if (map.getAllLayers().filter(layer => layer.get('name') === 'location').length === 0) |
20 | { |
21 | // 전용 레이어를 하나 추가함 |
22 | map.addLayer(new VectorLayer({ |
23 | source: new VectorSource(), |
24 | properties: { |
25 | name: 'location' |
26 | }, |
27 | style: new Style({ |
28 | image: new Icon({ |
29 | src: 'https://tsauerwein.github.io/ol3/animation-flights/examples/data/icon.png' |
30 | }) |
31 | }), |
32 | minZoom: 15, |
33 | zIndex: 10 |
34 | })); |
35 | } |
36 | |
37 | const onClick = () => |
38 | { |
39 | // 지오로케이션 사용이 가능할 경우 |
40 | if ('geolocation' in navigator) |
41 | { |
42 | const tag = document.querySelector('button.location') as HTMLButtonElement; |
43 | |
44 | navigator.geolocation.getCurrentPosition(position => |
45 | { |
46 | const { latitude, longitude } = position.coords; |
47 | |
48 | // 지도 이동 |
49 | map.getView().setCenter([ longitude, latitude ]); |
50 | |
51 | // location 레이어의 Source에 Feature를 추가 |
52 | map.getAllLayers().filter(layer => layer.get('name') === 'location')[0].getSource().addFeature(new Feature({ |
53 | geometry: new Point([ longitude, latitude ]) |
54 | })); |
55 | }, () => alert('실패'), { enableHighAccuracy: true }); |
56 | } |
57 | |
58 | // 아닐 경우 |
59 | else |
60 | { |
61 | alert('사용자 위치를 확인할 수 없습니다.'); |
62 | } |
63 | }; |
64 | |
65 | return ( |
66 | <button className='location' title='현재 위치 이동' onClick={onClick}><BiCurrentLocation size={25} color="white" /></button> |
67 | ); |
68 | } |
69 | |
70 | // 아닐 경우 |
71 | else |
72 | { |
73 | return null; |
74 | } |
75 | } |
큰 틀은 이전 장의 Location
컴포넌트와 동일하지만, 몇 가지 차이점이 존재한다.
- 드래그 이벤트
TYPESCRIPT
0 | // 드래그 할 경우, 레이어의 Feature를 전부 초기화 |
1 | map.on('pointerdrag', () => |
2 | { |
3 | map.getAllLayers().filter(layer => layer.get('name') === 'location')[0].getSource().clear(); |
4 | }); |
드래그 이벤트를 추가하여, 지도를 드래그할 때마다 location 레이어의 Feature를 전부 초기화하도록 구성한다.
즉, 사용자가 지도를 드래그할 경우, 지도에 표시된 사용자의 현재 위치는 삭제된다.
- 전용 레이어 추가
TYPESCRIPT
0 | // location 벡터 레이어가 없을 경우 |
1 | if (map.getAllLayers().filter(layer => layer.get('name') === 'location').length === 0) |
2 | { |
3 | // 전용 레이어를 하나 추가함 |
4 | map.addLayer(new VectorLayer({ |
5 | source: new VectorSource(), |
6 | properties: { |
7 | name: 'location' |
8 | }, |
9 | style: new Style({ |
10 | image: new Icon({ |
11 | src: 'https://tsauerwein.github.io/ol3/animation-flights/examples/data/icon.png' |
12 | }) |
13 | }), |
14 | minZoom: 15, |
15 | zIndex: 10 |
16 | })); |
17 | } |
전용 레이어가 없을 경우, 해당 레이어를 하나 추가해준다. 이러한 구성으로 LocationWithMarker
컴포넌트를 단순히 사용하는 것만으로 전용 레이어 추가가 가능하다.
- Feature 추가
TYPESCRIPT
0 | // location 레이어의 Source에 Feature를 추가 |
1 | map.getAllLayers().filter(layer => layer.get('name') === 'location')[0].getSource().addFeature(new Feature({ |
2 | geometry: new Point([ longitude, latitude ]) |
3 | })); |
Geolocation을 통해 수집한 위치 정보로 Feature
를 생성하여 추가한다.
TSX
0 | <LocationWithMarker map={mapState} /> |
사용법은 위와 같다. 만약, map
을 프로퍼티로 지정하지 않을 경우 null
을 반환하도록 구성하여 버튼이 표시되지 않도록한다.
이러한 기능은 해당 프로젝트의 MapInteraction
컴포넌트의 하위 LocationWithMarker
컴포넌트로 구현되어있다.
예제 확인하기 🔗
OpenLayers6 Sandbox - Feature에서 이를 구현한 예제를 확인할 수 있다.
좌측 하단의 녹색 버튼을 클릭하여 사용자의 위치로 이동되며, 위치를 파란색 원으로 표시해준다.
인터넷 회선 구성에 따라, 사용자의 실제 위치가 아닌 회선 서버의 물리적 위치가 뜨는 경우도 있으니 참고할 것.
LTE나 5G 같은 모바일 인터넷은 이러한 문제가 발생하지 않으나, LAN 같은 유선 인터넷 중에선 간혹 자신의 위치가 아닌 서버 위치가 뜨는 경우가 왕왕 있다.
📆 작성일
2022-04-03 Sun 16:56:03
📚 카테고리
🏷️ 태그