안녕하세요 캡틴개구리입니다.
이번시간은 Openlayers3(OL3)와 Leaflet에 User Control(거리재기)을 올려보겠습니다.
그전에 결과화면부터 보겠습니다.
> 서비스바로가기
Openlayers3 와 Leaflet 라이브러리를 받을 수 있는 곳은 아래와 같습니다.
OpenLayers3 : https://openlayers.org/
Leaflet : http://leafletjs.com/
VWORLD : http://map.vworld.kr
거리재기 기능을 이용하기 위해서는 Openlayers3의 경우 별도의 라이브러리 추가가 필요없지만, Leaflet의 경우 거리재기를 이용하기 위해 별도의 라이브러리가 필요합니다.
1. Openlayers3 User Control(거리재기 & 면적재기) 추가
활용라이브러리 : ol.Map, ol.layer.Tile, ol.source.Vector, ol.layer.Vector, ol.geom.Polygon, ol.geom.LinString, ol.View, ol.interaction.Draw, ol.style.Style, ol.style.Fill, ol.style.Stroke, ol.style.Circle, ol.Overlay
먼저 Openlayers3(이하 OL3) <script></script>부분입니다. 참고로 OL3를 이용하기 위해서는 라이브러리 추가합니다.
1 2 3 4 | <link type="text/css" rel="stylesheet" href="<c:url value='/css/openlayers/ol.css'/>" /> <script src="<c:url value='/js/openlayers/ol.js'/>"></script> | cs |
OL3 지도 띄우기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <script type="text/javascript"> //openlayers 지도 띄우기 //레스터 지도 var raster = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png' }) }); var vectorSource = new ol.source.Vector(); //벡터스타일 var vector = new ol.layer.Vector({ source: vectorSource, style: new ol.style.Style({ fill: new ol.style.Fill({ color: 'rgba(255, 255, 255, 0.2)' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 255, 1.0)', width: 2 }), image: new ol.style.Circle({ radius: 7, fill: new ol.style.Fill({ color: '#ffcc33' }) }) }) }); //지도띄우기 var map = new ol.Map({ layers: [raster,vector], target: document.getElementById('map'), view: new ol.View({ center: [14128579.82, 4512570.74], maxZoom: 19, zoom: 14 }) }); </script> | cs |
다음은 User Control 거리재기를 가져오도록 하겠습니다. 거리재기의 경우, OL3에서 기본적으로 제공하는 기능이며 또한 거리재기와 함께 면적을 구하는 기능을 함께 보여드리겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | <script type="text/javascript"> //거리재기 var sketch; var helpTooltipElement; var helpTooltip; var measureTooltipElement; var measureTooltip; var continuePolygonMsg = 'Click to continue drawing the polygon'; var continueLineMsg = 'Click to continue drawing the line'; var pointerMoveHandler = function(evt) { if (evt.dragging) { return; } /** @type {string} */ var helpMsg = 'Click to start drawing'; if (sketch) { var geom = (sketch.getGeometry()); if (geom instanceof ol.geom.Polygon) { helpMsg = continuePolygonMsg; } else if (geom instanceof ol.geom.LineString) { helpMsg = continueLineMsg; } } helpTooltipElement.innerHTML = helpMsg; helpTooltip.setPosition(evt.coordinate); helpTooltipElement.classList.remove('hidden'); }; map.on('pointermove', pointerMoveHandler); map.getViewport().addEventListener('mouseout', function() { helpTooltipElement.classList.add('hidden'); }); var typeSelect = document.getElementById('type'); var draw; var formatLength = function(line) { var length; length = Math.round(line.getLength() * 100) / 100; console.log(length); var output; if (length > 100) { output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; } else { output = (Math.round(length * 100) / 100) + ' ' + 'm'; } console.log(output); return output; }; var formatArea = function(polygon) { var area; area = polygon.getArea(); var output; if (area > 10000) { output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>'; } else { output = (Math.round(area * 100) / 100) + ' ' + 'm<sup>2</sup>'; } return output; }; function addInteraction() { var type = (typeSelect.value == 'area' ? 'Polygon' : 'LineString'); draw = new ol.interaction.Draw({ source: vectorSource, type: (type), style: new ol.style.Style({ fill: new ol.style.Fill({ color: 'rgba(255, 255, 255, 0.2)' }), stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.5)', lineDash: [10, 10], width: 2 }), image: new ol.style.Circle({ radius: 5, stroke: new ol.style.Stroke({ color: 'rgba(0, 0, 0, 0.7)' }), fill: new ol.style.Fill({ color: 'rgba(255, 255, 255, 0.2)' }) }) }) }); map.addInteraction(draw); createMeasureTooltip(); createHelpTooltip(); var listener; draw.on('drawstart', function(evt) { sketch = evt.feature; var tooltipCoord = evt.coordinate; listener = sketch.getGeometry().on('change', function(evt) { var geom = evt.target; var output; if (geom instanceof ol.geom.Polygon) { output = formatArea(geom); tooltipCoord = geom.getInteriorPoint().getCoordinates(); } else if (geom instanceof ol.geom.LineString) { output = formatLength(geom); tooltipCoord = geom.getLastCoordinate(); } measureTooltipElement.innerHTML = output; measureTooltip.setPosition(tooltipCoord); }); }, this); draw.on('drawend', function() { measureTooltipElement.className = 'tooltip tooltip-static'; measureTooltip.setOffset([0, -7]); sketch = null; measureTooltipElement = null; createMeasureTooltip(); ol.Observable.unByKey(listener); }, this); } function createHelpTooltip() { if (helpTooltipElement) { helpTooltipElement.parentNode.removeChild(helpTooltipElement); } helpTooltipElement = document.createElement('div'); helpTooltipElement.className = 'tooltip hidden'; helpTooltip = new ol.Overlay({ element: helpTooltipElement, offset: [15, 0], positioning: 'center-left' }); map.addOverlay(helpTooltip); } function createMeasureTooltip() { if (measureTooltipElement) { measureTooltipElement.parentNode.removeChild(measureTooltipElement); } measureTooltipElement = document.createElement('div'); measureTooltipElement.className = 'tooltip tooltip-measure'; measureTooltip = new ol.Overlay({ element: measureTooltipElement, offset: [0, -15], positioning: 'bottom-center' }); map.addOverlay(measureTooltip); } /* function removeInteractionMeasure() { vector.getSource().clear(measureTooltipElement); map.removeInteraction(draw); } */ typeSelect.onchange = function() { vector.getSource().clear(measureTooltipElement); map.removeInteraction(draw); map.removeOverlay(measureTooltip); $('.tooltip-static').remove(); addInteraction(); }; addInteraction(); </script> | cs |
12번행~38행 pointerMoveHandler는 거리재기 및 면적재기 기능이 활성화 되었을 경우, 그에 맞는 ToolTip 메세지를 제공하는 부분
40행 : id를 이용하여 선택된 기능의 Type 확인
43행~ 54행 : 거리재기 단위 변경 및 output 제공
59행~71행 : 면적재기 단위 변경 및 output 제공
73행~135행 : 거리재기 및 면적재기 기능 구현 부분
137행~176행 : 기능에 따른 해당 Tooltip 제공
OL3 User Control 거리재기 및 면적재기 <body></body>입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <body> <div class="container-fluid"> <div class="row content"> <div class="col-sm-6" style="border-right: 1px solid; height: 700px;"> <h1>Oepnlayers 3</h1> <div id="map"></div> </div> </div> <div class="row content"> <form class="form-inline" style="padding: 13px;"> <label>Measurement type </label> <select id="type"> <option value="length">거리재기</option> <option value="area">면적재기</option> </select> </form> </div> </div> </body> | cs |
스타일 부분입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <style> /* 거리재기 스타일_openlayers3 */ .tooltip { position: relative; background: rgba(0, 0, 0, 0.5); border-radius: 4px; color: white; padding: 4px 8px; opacity: 0.7; white-space: nowrap; } .tooltip-measure { opacity: 1; font-weight: bold; } .tooltip-static { background-color: #ffcc33; color: black; border: 1px solid white; } .tooltip-measure:before, .tooltip-static:before { border-top: 6px solid rgba(0, 0, 0, 0.5); border-right: 6px solid transparent; border-left: 6px solid transparent; content: ""; position: absolute; bottom: -6px; margin-left: -7px; left: 50%; } .tooltip-static:before { border-top-color: #ffcc33; } </style> | cs |
2. Leaflet User Control(거리재기) 추가
활용라이브러리 : L.map, L.tileLayer, L.control.measure
위에서 언급드린것 처럼 Leaflet에서 거리재기를 이용하기 위해서는 라이브러리가 필요합니다.
1 2 3 | <script src="<c:url value='/js/leaflet/leaflet.js'/>"></script> <script src="<c:url value='/js/leaflet/leaflet.measure.js'/>"></script> <link type="text/css" rel="stylesheet" href="<c:url value='/css/leaflet/leaflet.measure.css'/>" /> | cs |
먼저 leaflet <script></script>부분입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <script> //leaflet 지도 띄우기 var leafletMap = L.map('leafletMap').setView([37.52470308242787, 14129046.928310394],14) //Vworld Tile 변경 L.tileLayer('http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png').addTo(leafletMap); var plugin = L.control.measure({ // control position position: 'topleft', // weather to use keyboard control for this plugin keyboard: true, // shortcut to activate measure activeKeyCode: 'M'.charCodeAt(0), //거리재기 초기화 코드 //shortcut to cancel measure, defaults to 'Esc' cancelKeyCode: 27, // line color lineColor: 'red', // line weight lineWeight: 5, // line dash lineDashArray: '6, 6', // line opacity lineOpacity: 1, // distance formatter // formatDistance: function (val) { // return Math.round(1000 * val / 1609.344) / 1000 + 'mile'; // } }).addTo(leafletMap) </script> | cs |
OL3에 비해 매우 간략합니다. 이유는 라이브러리를 이용하였기 때문이라 생각됩니다.
이번에도 지도는 VWORLD를 이용했습니다.
3행~ 5행 : 지도 띄우기
7행~28행 : 거리재기를 위한 기능 부분으로 <script>부분에서는 옵션값 부분만 설정합니다. 그리고 Leaflet에서는 KeyCode라는것을 사용하는데
15행에 보시면 cancelKeyCode : 27은 ESC를 이용하여 기능을 초기화 시키는 코드입니다.
다음은 <body></body>입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <body> <div class="container-fluid"> <div class="row content"> <div class="col-sm-6" style="border-left: 1px solid; height: 700px;"> <h1>leaflet</h1> <div id="leafletMap"></div> </div> </div> </div> </body> <style> /* 거리재기_leaflet */ #leafletDt{ text-align: center; padding-left: 283px; } </style> | cs |
결과화면은 아래와 같습니다.
> 서비스바로가기
'꿀팁 - OpenLayers, Leaflet' 카테고리의 다른 글
Openlayers3와 Leaflet에서 Feature Click Event (0) | 2019.02.22 |
---|---|
Openlayers3와 Leaflet에서 D3 TopoJson 이용하기 (0) | 2019.01.30 |
OpenLayers와 Leaflet에서 Feature 이벤트 연동 (2) | 2018.11.29 |
OpenLayers와 Leaflet에서 Image Overlay (0) | 2018.11.28 |
OpenLayers와 Leaflet에서 Feature Clustering (0) | 2018.11.22 |