leaflet 배경지도에 Shape File파일을 서버측 코드 없이 웹 브라우저를 통해 GeoJson으로 변환하여 올리는 방법을 알아보겠습니다. 

 

먼저 결과화면을 확인해보겠습니다.

서비스바로가기

 

※ 배경지도 라이브러리

※ shape File을 지도에 올리기 위한 js 파일

(zip포맷으로 올린 Shape File의 압축을 풀고 JavaScript의 인코딩으로 데이터를 서버 측 코드 없이 브라우저를 통해 GeoJson으로 변환 및 표출 모듈)

 

preview.js : Shap File을 GeoJson으로 변환

dbf.js : .Shape File파일의 속성부분 정의
 

1. index.jsp

    • 37행 : leaflet 지도 올리기
    • 40행 : leaflet 배경지도 Vworld로 변경
    • 42행~71행 : 속성정보를 표출
    • 72행~104행 : zip파일 형태의 Shape File을 geojson으로 변경 및 지도에 표출하는 부분
    • 77행 : loadshp 기능 실행 -> preview.js  및 perprocess.js 실행(GeoJson으로 변환 및 Shape File의 .dbf 파일 속성정보 모듈)
 

 

 

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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!doctype html>
<html lang="ko">
<head>
<title>shp loading</title>
<meta http-equiv="Content-Type" content="charset=UTF-8" />
<meta name="author" content="Gipong">
<meta name="keywords" content="shapefile,dbf,geojson,preview">
 
<link rel="stylesheet" href="<c:url value='/resources/css/leaflet/leaflet.css'/>" />
<link rel="stylesheet" href="<c:url value='/resources/css/semactic/semantic.min.css'/>" />
<link rel="stylesheet" href="<c:url value='/resources/css/demo/demo.css'/>" />
<link rel="stylesheet" href="<c:url value='/resources/css/jquery/jquery-ui.min.css'/>" />
 
<script src="<c:url value='/resources/js/pro4j/pro4j.js'/>"></script>
 
<script src="<c:url value='/resources/js/jquery/jquery-2.1.1.min.js'/>"></script>
<script src="<c:url value='/resources/js/jquery/jquery-ui.min.js'/>"></script>
<script src="<c:url value='/resources/js/leaflet/leaflet.js'/>"></script>
 
<script src="<c:url value='/resources/js/lib/jszip.js'/>"></script>
<script src="<c:url value='/resources/js/lib/jszip-utils.js'/>"></script>
<script src="<c:url value='/resources/js/lib/jszip-utils-ie.js'/>"></script>
 
<script src="<c:url value='/resources/js/semantic/semantic.min.js'/>"></script>
<script src="<c:url value='/resources/js/preprocess/dbf.js'/>"></script>
<script src="<c:url value='/resources/js/preview/preview.js'/>"></script>
 
</head>
<script type="text/javascript" charset="UTF-8">
$(document).ready(function() {
 
    var map = L.map('map').setView([36.3991782860765514129048.150024414], 7),
    file,
    vector;
    L.tileLayer('http://xdworld.vworld.kr:8080/2d/Base/201802/{z}/{x}/{y}.png').addTo(map);
    
    function initVector () {
        vector = L.geoJson([], {
            style: function (feature) {
                return feature.properties.style;
            },
            onEachFeature: function (feature, layer) {
 
                layer.on({click: function(e) {
                    vector.eachLayer(function(l) {
                        vector.resetStyle(l);
                    });
 
                    $('.tbodyContent').remove();
                    var tbody = '<tbody class="tbodyContent">';
                    for (var key in e.target.feature.properties) {
                        tbody +=
                            ('<tr class="center aligned"><td>'+ key + '</td><td>' + e.target.feature.properties[key] + '</td></tr>');
                    }
                    $('#attribute').append(tbody + '</tbody>');
                    $('#attr').fadeIn(300);
                    map.panTo(e.latlng);
 
                    if('setStyle' in e.target) e.target.setStyle({
                        fillColor: '#FF0',
                        fillOpacity: 0.6
                    });
                }});
            }
        }).addTo(map);
    }
    function loadShpZip() {
        var epsg = ($('#epsg').val() == '') ? 4326 : $('#epsg').val(),
        encoding = ($('#encoding').val() == '') ? 'UTF-8' : $('#encoding').val();
        if(file.name.split('.')[1== 'zip') {
            if(file) $('.dimmer').addClass('active');
            loadshp({
                url: file,
                encoding: encoding,
                EPSG: epsg
            }, function(data) {
                var URL = window.URL || window.webkitURL || window.mozURL || window.msURL,
                url = URL.createObjectURL(new Blob([JSON.stringify(data)], {type: "application/json"}));
 
                $('.shp-modal').toggleClass('effect');
                $('.overlay').toggleClass('effect');
                $('#wrap').toggleClass('blur');
 
                vector.addData(data);
                map.fitBounds([
                    [data.bbox[1], data.bbox[0]], [data.bbox[3], data.bbox[2]]
                ]);
                $('.dimmer').removeClass('active');
                $('#preview').addClass('disabled');
                $('#epsg').val('');
                $('#encoding').val('');
                $('#info').addClass('picInfo');
                $('#option').slideUp(500);
            });
        } else {
            alert("ZIP 포맷으로 사용해주십시오.")
            return;
        }
    }
    initVector();
 
    $("#file").change(function(evt) {
        file = evt.target.files[0];
        var fileSize = Math.round(file.size);
        console.log(fileSize);
        if(file.size > 600000) {
            alert("600KB 이햐의 데이터를 이용하여 주십시오.")
            return;
        }else{
            $('#dataInfo').text(' ').append(file.name+' , '+file.size+' kb');
            $('#option').slideDown(500);
            $('#preview').removeClass('disabled');
        }
    });
 
    $('#preview').click(function() {
        loadShpZip();
    });
 
    $('#addZipfile').click(function() {
        $('.shp-modal').toggleClass('effect');
        $('.overlay').toggleClass('effect');
        $('#wrap').toggleClass('blur');
    });
    $('#cancel').click(function() {
        $('.shp-modal').toggleClass('effect');
        $('.overlay').toggleClass('effect');
        $('#wrap').toggleClass('blur');
    });
    $('#removeLayer').click(function() {
        $('#attr').fadeOut(300);
        window.location.reload();
    });
    
    $('#encoding').dropdown();
    
    $("#attr").draggable({ containment: $(this).parent().parent(), scrollfalse, cursor: "move" });
    $('#cancelAttr').click(function(){ $('#attr').slideUp(300); });
});
</script>
    
<body>
    <div id="wrap" class="wrap">
        <div id="map" ></div>
        
        <div id="attr">
            <div class="tableDisplay">
                <table id="attribute" class="ui small celled unstackable table">
                    <thead id="attrHead">
                        <tr class="center aligned">
                            <th>Attribute</th>
                            <th>Value</th>
                        </tr>
                    </thead>
                    <tbody class="tbodyContent">
                    </tbody>
                </table>
            </div>
            <div class="ui red icon button" id="cancelAttr">닫기</div>
        </div>
 
        <footer id="footer">
            <div class="ui page grid">
                <div class="sixteen wide column center aligned">
                    <div id="addZipfile" class="tips large ui positive right labeled icon button">레이어 추가(zip)</div>
                    <div id="removeLayer" class="negative large ui button">레이어 초기화</div>
                </div>
            </div>
        </footer>
    </div>
 
    <div id="shp" class="shp-modal">
        <div class="ui page grid">
            <div class="sixteen wide aligned column">
                <div class="ui form segment">
                    <div class="field">
                        <div class="ui teal fluid labeled icon button upload" id="zipfile" data-variation="inverted large">레이어 불러오기
                            <input type="file" id="file" accept=".zip">
                        </div>
                    </div>
                    <div class="field" id="dataInfo"></div>
    
                    <div id="option">
                        <div class="field ui labeled input" id="epsgField">
                            <div class="ui label">EPSG</div>
                            <input type="text" placeholder="Default : 4326" id="epsg" class="v" onfocus="this.value='';">
                        </div>
                        <div class="field ui labeled input" style="top:-7px;">
                            <div class="ui label" >Encoding</div>
                            <input type="text" placeholder="Encoding UTF-8, EUC-KR, Big5, Big5-HKSCS ... " id="encoding" class="v" onfocus="this.value='';">
                        </div>
                    </div>
                    <div class="two fields" style="padding: 0px 97px;">
                        <div class="field">
                            <div class="ui teal fluid labeled icon disabled button" id="preview"    style="margin: 5px 40px;">레이어 등록</div>
                        </div>
                        <div id="cancel" class="negative right ui button"    style="margin: 5px 40px;">닫기</div>
                    </div>
                </div>
                <div class="ui inverted dimmer">
                    <div class="ui large text loader">데이터를 불러오고있습니다...</div>
                </div>
            </div>
         </div>
     </div>
    <div class="overlay"></div>
 
 
</body>
</html>
 
cs

 


2. 실행 조건

    • Shape File 용량 제한

=> 서버를 이용하지 않고 웹 브라우저를 통해 shapeFile을 GeoJson 형태로 올리기 위해서 Shape File의 용량을 제한

    • EPSG 코드 입력
=>Default로 4326을 설정하였으며, Zip파일 내에 .prj파일이 존재하는 경우, 사용자가 입력한 EPSG로 변경되지 않음 (.prj파일 우선순위)
    • Encoding
=> Encoding을 정확히 입력하여야 속성정보 깨짐이 없음
 
 
3. 결과화면
 
 

+ Recent posts