Openlayers3에서 사용자가 지정한 위치를 표시하고 Map을 PDF로 저장하는 방법을 알아보겠습니다.

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

서비스바로가기

 
 
배경지도는 Openlayers3를 이용하였으며, 지도를 PDF로 저장하기 위해 아래 모듈을 사용하였습니다.

1. mapExport.jsp

 

위에 첨부한 파일은 원하시는 이클립스 디렉토리에 저장하셔서 사용하시면 되겠습니다.

1
<script src="<c:url value='/js/FileSaver/fileSaver.js'/>"></script>
cs

<script></script>부분부터 확인해보도록 하겠습니다. 

    • 3행 : 사용자가 원하는 위치를 클릭시 사용할 마커 이미지 및 정보를 iconStyle에 등록합니다.
    • 11행 : 클릭한 위치의 정보와 마커이미지를 vectorSource에 담아두기 위해 선언합니다.
    • 13행 : 지도에 표시하기 위해 vectorLayer에 vectorSource를 담아두겠습니다.
    • 16행 : 지도 불러오기
    • 24행 : 화면에 표출되는 지도의 좌표정보를 등록하는 곳입니다.
    • 32행 : 지도 클릭 이벤트
    • 38행 : iconFeature에 클릭한 위치의 좌표정보를 등록합니다.
    • 42행 : iconFeature에 3행에서 등록한 이미지 및 정보를 넣어줍니다.
    • 44행 : 42행를 통해 등록한 정보를 vectorSource에 담아줍니다. ==> 담아준 정보는 지도 불러오기 중 지도의 layers부분(21행)을 통해 지도에 표시됩니다.
    • 48행 : 지도부분을 PDF로 Export하는 부분입니다. Export를 위해서 위쪽에 올려드린 첨부파일이 필요합니다.
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
<script type="text/javascript">
$(document).ready(function(){
    var iconStyle = new ol.style.Style({
        image: new ol.style.Icon(({
            anchorXUnits: 'fraction',
            anchorYUnits: 'pixels',
            src: '/images/common/waypoint.png',
            scale: 0.5
        }))
    });
    var vectorSource = new ol.source.Vector();
    
    var vectorLayer = new ol.layer.Vector({
        source: vectorSource
    });
    var map = new ol.Map({
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            }),
            vectorLayer
        ],
        target: 'map',
        view: new ol.View({
            center: [1987706.31,4522199.26],
            zoom: 3,
            minZoom: 3,
            maxZoom: 19
        })
    });
    
    map.on('click',function(evt){
        var coordinate = evt.coordinate;
        
        var coordLon = coordinate[0];
        var coordLat = coordinate[1];
        
        var iconFeature = new ol.Feature({
            geometry: new ol.geom.Point([coordLon,coordLat])
          });
        
        iconFeature.setStyle(iconStyle);
        
        vectorSource.addFeature(iconFeature);
        
    });
    
    document.getElementById('export-png').addEventListener('click'function() {
        map.once('postcompose'function(event) {
            var canvas = event.context.canvas;
            canvas.toBlob(function(blob) {
                saveAs(blob, 'UserMap.png');
            });
        });
        map.renderSync();
    });
});
 
</script>
cs

<body></body>부분입니다.

1
2
3
4
<body>
    <div id="map"></div>
    <a id="export-png" class="btn btn-default"><i class="fa fa-download"></i> Download PNG</a>
</body>
cs

2. 결과화면

Openlayers3에서 전세계 공항의 위치 정보를 이용한 지도 표출을 알아보겠습니다. 먼저 결과화면을 확인해보겠습니다.

 

배경지도는 Openlayers3를 이용하였으며, 공항 위치정보 데이터 또한 Openlayers에서 제공하는 데이터를 이용하였습니다.
원래는 국내공항의 위치정보를 이용하여 기능을 보여드리려 하였지만 비행이동이 화려하게 표현되지 못해 Openlayers에서 제공하는 데이터를 그대로 사용하였습니다. 
 
전세계 공항 정보 .json 데이터는 아래에 첨부파일 다운로드 받으시면 됩니다.
flights.json
다운로드

그리고 위 화면처럼 타원을 그리며 비행기가 날아가도록 하기위해 별도의 모듈을 이용했습니다.

arc.js
다운로드

 

1. Flights.jsp

1
2
3
4
5
6
7
8
9
10
<head>
<title>flights</title>
<meta charset="utf-8">
 
<link type="text/css" rel="stylesheet" href="<c:url value='/css/openlayers/ol.css'/>" />
 
<script src="<c:url value='/js/openlayers/ol.js'/>"></script>
<script src="<c:url value='/js/arc/arc.js'/>"></script>
 
</head>
cs

지금까지 등록된 Openlayers 예제를 보셨다면 소스는 쉽게 이해하실 수 있으실 겁니다. 먼저 <script></script>부분을 살펴보도록하겠습니다.

    • 3행~21행 : Openlayers3 지도 로드
    • 23행 : 비행 이동 경로(라인) 스타일
    • 31행 : 66행을 통해 비행 이동 시작 및 flightsSource에 feature 정보 넣기
    • 40행 : 66행을 통해 비행 이동 도착
    • 66행 : 공항 위치정보 json에 있는 위치정보를 이용하여 시작점/도착점 설정
    • 100행 : 비행이동 경로 지도에 표출
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
<script type="text/javascript">
$(document).ready(function(){
    var map = new ol.Map({
        target: 'map',
        layers: [
            new ol.layer.Tile({
                source: new ol.source.Stamen({
                    wrapX: false,
                    layer: 'toner'
                })
            })
        ],
        view: new ol.View({
            //경도,위도
            center: [1987706.31,4522199.26],
            zoom: 3,
            minZoom: 3,
            maxZoom: 19
        }),
        
      });
    
    var style = new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: '#FF4233',
            width: 2
        })
    });
    
    var flightsSource;
    var addLater = function(feature, timeout) {
        window.setTimeout(function() {
            feature.set('start'new Date().getTime());
            flightsSource.addFeature(feature);
        }, timeout);
    };
    
    var pointsPerMs = 0.1;
    
    var animateFlights = function(event) {
        var vectorContext = event.vectorContext;
        var frameState = event.frameState;
        vectorContext.setStyle(style);
        
        var features = flightsSource.getFeatures();
        for (var i = 0; i < features.length; i++) {
            var feature = features[i];
            if (!feature.get('finished')) {
                var coords = feature.getGeometry().getCoordinates();
                var elapsedTime = frameState.time - feature.get('start');
                var elapsedPoints = elapsedTime * pointsPerMs;
                
                if (elapsedPoints >= coords.length) {
                    feature.set('finished'true);
                }
                
                var maxIndex = Math.min(elapsedPoints, coords.length);
                var currentLine = new ol.geom.LineString(coords.slice(0, maxIndex));
            
                vectorContext.drawGeometry(currentLine);
            }
        }
        map.render();
    };
    
    flightsSource = new ol.source.Vector({
        wrapX: false,
        loader: function() {
            var url = "/js/data/geojson/flights.json";
            fetch(url).then(function(response) {
                return response.json();
            }).then(function(json) {
                var flightsData = json.flights;
                for (var i = 0; i < flightsData.length; i++) {
                    var flight = flightsData[i];
                    var from = flight[0];
                    var to = flight[1];
                    
                    var arcGenerator = new arc.GreatCircle(
                        {x: from[1], y: from[0]},
                        {x: to[1], y: to[0]});
                    
                    var arcLine = arcGenerator.Arc(100, {offset: 10});
                    if (arcLine.geometries.length === 1) {
                        var line = new ol.geom.LineString(arcLine.geometries[0].coords);
                        line.transform(ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
                        
                        var feature = new ol.Feature({
                            geometry: line,
                            finished: false
                        });
                        addLater(feature, i * 50);
                    }
                }
            map.on('postcompose', animateFlights);
            });
        }
    });
 
    var flightsLayer = new ol.layer.Vector({
        source: flightsSource,
        style: function(feature) {
            if (feature.get('finished')) {
                return style;
            } else {
              return null;
            }
        }
    });
    map.addLayer(flightsLayer);
});
 
</script>
 
cs

<body></body>및 <style></style>부분입니다.

1
2
3
4
5
6
7
8
9
<style>
#map {
    height:730px;
}
</style>
 
<body>
    <div id="map"></div>
</body>
cs

2. 결과화면

+ Recent posts