안녕하세요 캡틴개구리입니다.

이번시간은 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.824512570.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: [1010],
                    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: [150],
          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 &nbsp;</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에서 거리재기를 이용하기 위해서는 라이브러리가 필요합니다. 

leaflet.measure.css

leaflet.measure.js


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.5247030824278714129046.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


결과화면은 아래와 같습니다.


서비스바로가기

+ Recent posts