티스토리 뷰

Skill/OpenLayers

[OpenLayers] OpenLayers3 와 VWORLD

진열사랑 2020. 9. 20. 21:07

[출처] OpenLayers3 와 VWORLD 를 사용해보자|작성자 곰구리

 

지도 서비스 하면 국내에서 유명한 것에는 네이버지도, 다음(카카오)지도, 구글지도 등이 있다.

워낙 다양하게 쓰이고 기능도 좋고.. 뭐든 다 좋다.. 검색도 엄청난 데이터를 기반으로 짜잔 하고 뿌려주니.. 정말 대단하다 라고 밖에 말할 수 없는 듯 싶다.

하지만, 이것을 내가 만든 프로그램에 넣을순 있어도 기능을 넣어보는 것은 쉽지가 않다. 특히 내가 모아놓은 좌표정보를 거기에다가 뿌리려면.... 어휴;;

 

이런 부분들을 공부해보려 하면.. GIS 엔진으로 어쩌구 저쩌구 하면서.. 디게 복잡한 이야기가 나오던데... 이건.. 혼자 해보기에는 너무 어렵다..

그래서 블로그나 카페들에서 가끔 다루는 오픈소스기반 GIS 를 써서.. 맵을 얹어서 해야한다는데.. 하하하..... 이것도 이해를 잘 못하겠다 ㄱ-;;;

그래도 어쩔수 없지.. 일단 정보를 수집해보자.

 

OpenLayers3 사이트  :  https://openlayers.org/ 

Leaflet 사이트 : http://leafletjs.com/

VWORLD 사이트  :  http://map.vworld.kr

 

OpenLayer(이하 OL3) 와 Leaflet 은 오픈소스기반 GIS 엔진이라고 말하시는 분도 있고.. 웹에서 지도서비스를 쉽게 구축하기 위한 도구라고도 말하는데 뭐 같은 의미인듯 싶다.

 

Leaflet 과 OL3 로 지도서비스 환경을 구축하고, GoogleMap 이나 OpenStreetMap 등을 올리면 되는데.. 

VWORLD 라고 공간사업진흥청?(왠지 국가기관 같다..) 거기서 제공하는 국산지도도 있길래 이 포스팅에서는 이 VWORLD를 사용해볼까 한다.

일단 국산이니까.. 국내지리정보에 대한 것은 더 잘 나와있지 않을까..... (구글지도가 더 좋으려나;;)

 

Leaflet 과 OL3 둘 중에 무엇을 사용해볼까 하고 참 고심을 많이 해보았는데.. 

구글링 해보니, Leaflet 보다 OpenLayers 자동완성이 더 많길래.. 자료 많은 것으로 방향을 잡아 볼까 한다 ㄱ-;; 

 

 

일단 OpenLayers 에 대한 정보가 있는 페이지들을 다 모아보자.

 

 - 위에서도 적었지만, OpenLayers 사이트를 방문하면 Examples 가 있는데 꼭 대충 훑어보자. 기본 제공되는 예제가 참 많다.

 - 그다음은 정말 정리가 잘 되어 있는 국내 블로그가 있어서 링크를 걸어둔다. (http://blog.naver.com/junddang2/30133261952

   여기서는 개념정리 뿐만 아니라, 예제 코드도 많이 있는데, 약간 염려스러운건 2012년 블로그라는 것이다.. 버전이 바뀌면 메소드도 바뀌는지라.. 음;;

 - http://openlayersbook.github.io 여기는 github 에서 제공하는지 아닌지는 모르겠지만 초보자가이드 같은 느낌? OL3 홈페이지의 Example 과 비슷하긴 하지만, 

   약간 더 쉽게 정리도 되어있고, 그러해서 참고가 많이 되는듯 싶다.

 

OL3 라이브러리는.. https://github.com/openlayers/openlayers 여기에 가서 다운로드 받아서 찾아보면 있긴한데.. 찾는데 한참 걸려서..

일단 압축해서 올려놀까 싶다. (압축한 파일에는, 여기에 정리한 부분의 예제파일(html)도 같이 첨부하도록 하겠다)

 

 

1. js 라이브러리 및 페이지 디자인 하기

  - 가장 먼저 할 일은, 라이브러리를 추가하는 일이다.

  - 라이브러리 파일들을 알아서 잘~ 좋은 위치에 두고, html 파일에 추가하고, 간단하게 페이지 디자인도 해주자.

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->

    <script src="resources/jquery/jquery-1.11.3.min.js"></script>

 

<!-- openlayers -->

    <link href="resources/openlayers/ol.css"rel="stylesheet">

    <script src="resources/openlayers/ol.js"></script>

 

    <script src="resources/js/proj4.js"></script>

 

    <!--  지도 스타일 -->

    <style type="text/css">

    #map {

        width: 600px;

        height: 400px;

        border: 2px solid #ccc;

    }

    

    table.list_t1 { 

        margin:10px 0; text-align:center;border-collapse:collapse; width:600px;

        border-top:2px solid #005aa1; border-bottom:1px solid #e3e8e9;

    }

    table.list_t1 th, table.list_t1 td {

        border-right:1px solid #e3e8e9;border-bottom:1px solid #e3e8e9;font-size:13px;

    }

    table.list_t1 td {

        padding:2px; height:25px;

    }

    table.list_t1 th {

        background:#f6f6f6;padding:9px 10px;text-align:center;

    }

    table.list_t1 th:last-child,table.list_t1 td:last-child {

        border-right:none;

    }

    </style>

    

</head>

<body>

    

    <div id="content_wp">

    <div id="content">

 

        <div class="custom-popup" id="map">

                    

        </div>

        <input id="base-layer" type="button" value="지도" onclick="baseChange('satellite')">

        <input type="button" value="포인트" onclick="mapSubmit()">

        

        <table class="list_t1" id="gisTable">

            <tr>

                <th>위치</th>

                <th>경도</th>

                <th>위도</th>

            </tr>

        </table>

    </div>

    </div>

 

</body>

 

2. 지도 뿌리기

  - 먼저 VWORLD 지도를 id=map 인 div 에 뿌려보도록 하겠다.

// 지도

    var layers = {};

    layers['vworld'= new ol.layer.Tile({

        title : 'VWorld Gray Map',

        visible : true,

        type : 'base',

        source : new ol.source.XYZ({

            url : 'http://xdworld.vworld.kr:8080/2d/Base/201612/{z}/{x}/{y}.png'

        })

    });

    

    // vectorSource 선언

    var vectorSource = new ol.source.Vector({

        projection: 'EPSG:4326'

    });

 

    // vectorLayer 선언

    var vectorLayer = new ol.layer.Vector({

        source: vectorSource

    });

     

    // 지도뿌리기

    var map = new ol.Map({

 

        layers : [ layers['vworld'], vectorLayer ],

        target : 'map',

        view : new ol.View({

            // center: ol.proj.transform([getLongi, getLati ], 'EPSG:4326', 'EPSG:3857'),

            center: ol.proj.fromLonLat([127.536]),        // center 좌표

            zoom: 7,                                        // 초기화면 zoom level

            minZoom: 6,                                        // 최소 zoom level

            maxZoom: 19                                        // 최대 zoom level

        })

    });

  - 위와 같이 하면, layers['vworld'] 라는 레이어가 map 이라는 target 에 들어가며, center 좌표값, 현재줌 등을 설정을 할 수 있다.

  - 실제로 지도만 뿌리는건 위가 끝이다. 

  - 여기서 중요한건, 첫번째 메소드 내에 url을 보면 지도 이미지 정보를 받는 주소가 있는데, 테스트용으로 알고 있다.

    실제로 사용하려면, api-key를 받아서 사용을 해야 한다는데, 그냥 VWORLD 사이트 가입 후 신청하면 보내준다고 하는거 같다.

 

3. 지도 바꾸기

  - 네이버지도나 구글지도를 보면, 위성사진 보기 기능이 있다. 우리도 그 기능을 넣어보도록 하자.

  - 뷰페이지쪽에 보면 벌써 버튼을 만들어 놓았다. (id=base-layer)

  - 이 버튼을 누르면 지도가 위성으로 바뀌고, 다시 누르면 원래 지도로 돌아가는 것을 추가해보자.

  - 먼저 위성지도 부분을 작성하자. (

    // 지도

    var layers = {};

    layers['vworld'= new ol.layer.Tile({

        title : 'VWorld Gray Map',

        visible : true,

        type : 'base',

        source : new ol.source.XYZ({

            url : 'http://xdworld.vworld.kr:8080/2d/Base/201612/{z}/{x}/{y}.png'

        })

    });

    layers['satellite'= new ol.layer.Tile({

        title : 'VWorld Gray Map',

        visible : true,

        type : 'base',

        source : new ol.source.XYZ({

            url : 'http://xdworld.vworld.kr:8080/2d/Satellite/201612/{z}/{x}/{y}.jpeg'

        })

    });

 

    // vectorSource 선언

    var vectorSource = new ol.source.Vector({

        projection: 'EPSG:4326'

    });

  - 위와 같이 layers['satellite'] 를 추가해주고 (여기에서는 위성사진 이미지를 받아온다)

  - 아래와 같이 버튼을 눌렀을때 지도를 바꿔주는 메서드를 추가해주자.

    // 버튼 클릭시, 해당 타일(지도와 위성)로 변경

    function baseChange(data){

        if(data=="satellite"){    // 위성으로 변경

            $("#base-layer").val("위성");

            $("#base-layer").attr("onclick""baseChange('vworld')");

            

        } else {                // 지도로 변경

            $("#base-layer").val("지도");

            $("#base-layer").attr("onclick""baseChange('satellite')");

        }

        

        var layer = layers[data];

        if (layer) {

            layer.setOpacity(1);

            updateRenderEdgesOnLayer(layer);

            map.getLayers().setAt(0, layer);

        }

    }

 

    // 타일 변경

    var updateRenderEdgesOnLayer = function(layer) {

        if (layer instanceof ol.layer.Tile) {

            var source = layer.getSource();

        }

    };

  - 생각보다 쉬워보인다. 뭔말인지는 잘 모르는 부분은 많지만.. 일단 여기까지 해보면 버튼을 누를때 배경지도가 바뀌는 것을 확인할 수 있다.

 

4. 지도에 포인트 찍기.

  - 작동방식을 보자면, 포인트버튼(mapSubmit())을 누르면 좌표정보를 전역변수 선언을 한 svyData 라는 변수에 담은 후,     addFeature() 라는 메서드를 이용해서, 이 변수 안에 들어있는 좌표정보 및 기타 정보들을 iconFeature 라는 변수에 담고.    그 iconFeature 를 iconFeatures 라는 배열에 담은 후, 지도 생성할때 선언한 vectorSource에 add를 하여 포인트를 찍는다.

  - 그 생성된 포인트에는 iconFeature를 생성하면서 넣은 정보가 들어있으면, map.on() 메소드를 이용하여 클릭 시 그 정보를 alert으로 띄우게 하며,    DragBox 이벤트를 이용하여 선택한 포인트들(features)에 대한 정보를 table 에 뿌린다.

    (드래그는, Ctrl+마우스드래그 로 작동한다)

  - 는 것이 기본 작동방식이다.

  - 이부분에 대해서는 파일로 첨부한 것을 참고하면 쉽게 이해할 수 있을 것이라 보긴하는데.. mapSubmit() 메서드 부분만 짧게 추가적으로 적어보자면

    function mapSubmit(){

        // get  // 이 부분은 나중에 ajax 등을 통해서 좌표 값을 json object 형태로 가져와서 data 에 넣어주면 됨.

        var data = new Array();

        

        var coord = new Object();

        coord.svy_name = "약진너머해수욕장";

        coord.svy_longi = 126.233439;

        coord.svy_lati = 37.180287;

        data.push(coord);

        var coord = new Object();

        coord.svy_name = "떼뿌루해수욕장";

        coord.svy_longi = 126.175860;

        coord.svy_lati = 37.211874;

        data.push(coord);

        // get

    

        svyData = data;

        var jsonData = JSON.stringify(data) ;

        

        addFeatures();     

    }

  - 지금 위의 코드를 보면, json object 형태로 데이터를 생성하고 있다.

    실제로 위와같이 쓰일일은 없을 듯 싶고, mysql 등의 DB에서 값을 가져다가 json 형태로 리턴해줬을때로 가정을 하고 작성을 했다.

   // get 사이 부분을 ajax json 으로 만들어서 쓰면 간단하게 응용해서 쓸 수 있을것이라 생각된다.

 

5. 실제실행 모습

 

 

 

6. 추가

지도에 보면 우측 아래에 아이콘 같은 것이 있다. Attribution 이라 부르는 것 같던데. 이거 없앨 수가 있다고 한다.

var map 정의하는 곳에 이거 한줄 추가해주면 된다.

    var map = new ol.Map({

 

        layers : [ layers['vworld'], layers['bng'], vectorLayer ],

        logo : false,

        target : 'map',

        view : ........

    });

 

7. 전체 소스

<!DOCTYPE html>
<html>
<head>
<!-- jQuery -->
    <script src="https://code.jquery.com/jquery-1.8.3.min.js"></script>
 
<!-- openlayers -->
<!-- Openlayers 6 -->
<link rel="stylesheet" href="/js-lib/openlayers/ol6/ol.css"/>
<script type="text/javascript" src="/js-lib/openlayers/ol6/ol.js"></script>
<script type="text/javascript" src="/js-lib/openlayers/ol6/ol-ext.js"></script>
<script type="text/javascript" src="/js-lib/openlayers/ol6/proj4-src.js"></script>

<!-- proj4.js -->
<script type="text/javascript" src="/js-lib/openlayers/ol2/proj4.js"></script>  
 
    <!-- <script src="resources/js/proj4.js"></script> -->
 
    <!--  지도 스타일 -->
    <style type="text/css">
    #map {
        width: 600px;
        height: 400px;
        border: 2px solid #ccc;
    }
    
    table.list_t1 { 
        margin:10px 0; text-align:center;border-collapse:collapse; width:600px;
        border-top:2px solid #005aa1; border-bottom:1px solid #e3e8e9;
    }
    table.list_t1 th, table.list_t1 td {
        border-right:1px solid #e3e8e9;border-bottom:1px solid #e3e8e9;font-size:13px;
    }
    table.list_t1 td {
        padding:2px; height:25px;
    }
    table.list_t1 th {
        background:#f6f6f6;padding:9px 10px;text-align:center;
    }
    table.list_t1 th:last-child,table.list_t1 td:last-child {
        border-right:none;
    }
    </style>
    

</head>
<body>
    
    <div id="content_wp">
    <div id="content">
 
        <div class="custom-popup" id="map">
                    
        </div>
        <input id="base-layer" type="button" value="지도" onclick="baseChange('satellite')">
        <input type="button" value="포인트" onclick="mapSubmit()">
        
        <table class="list_t1" id="gisTable">
            <tr>
                <th>위치</th>
                <th>경도</th>
                <th>위도</th>
            </tr>
        </table>
    </div>
    </div>

<script type="text/javascript">
//지도
var layers = {};
layers['vworld'] = new ol.layer.Tile({
    title : 'VWorld Gray Map',
    visible : true,
    type : 'base',
    source : new ol.source.XYZ({
        url : 'http://xdworld.vworld.kr:8080/2d/Base/201612/{z}/{x}/{y}.png'
    })
});
layers['satellite'] = new ol.layer.Tile({
    title : 'VWorld Gray Map',
    visible : true,
    type : 'base',
    source : new ol.source.XYZ({
        url : 'http://xdworld.vworld.kr:8080/2d/Satellite/201612/{z}/{x}/{y}.jpeg'
    })
});

// vectorSource 선언
var vectorSource = new ol.source.Vector({
    projection: 'EPSG:4326'
});

// vectorLayer 선언
var vectorLayer = new ol.layer.Vector({
    source: vectorSource
});
 
// 지도뿌리기
var map = new ol.Map({

    layers : [ layers['vworld'], vectorLayer ],
    target : 'map',
    view : new ol.View({
        //center: ol.proj.transform([127.5, 36 ], 'EPSG:4326', 'EPSG:3857'),
        center: ol.proj.fromLonLat([127.5, 36]),        // center 좌표
        zoom: 7,                                        // 초기화면 zoom level
        minZoom: 6,                                        // 최소 zoom level
        maxZoom: 19                                        // 최대 zoom level
    })
});

// 버튼 클릭시, 해당 타일(지도와 위성)로 변경
function baseChange(data){
    if(data=="satellite"){    // 위성으로 변경
        $("#base-layer").val("위성");
        $("#base-layer").attr("onclick", "baseChange('vworld')");
        
    } else {                // 지도로 변경
        $("#base-layer").val("지도");
        $("#base-layer").attr("onclick", "baseChange('satellite')");
    }
    
    var layer = layers[data];
    if (layer) {
        layer.setOpacity(1);
        updateRenderEdgesOnLayer(layer);
        map.getLayers().setAt(0, layer);
    }
}

// 타일 변경
var updateRenderEdgesOnLayer = function(layer) {
    if (layer instanceof ol.layer.Tile) {
        var source = layer.getSource();
    }
};

</script> 
</body>
</html>
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함