vworld 지도 만들기(7) - 좌표(위, 경도) 알아내기
1. vworld에서 사용하고 있는 좌표계
vworld는 우리에게 친숙한 위, 경도를 사용하지 않고, 아래와 같이 14129709.590359,4512313.7639686와 같은 이상한 숫자(좌표)를 사용하고 있습니다.
<div class="buttons"> <button type="button" onclick="javascript:move(14129709.590359,4512313.7639686,15);" >여의도</button> <button type="button" onclick="javascript:move(14679304.585522275, 4472545.1240446,18);" >독도</button> </div> |
그래서 찾아보니 2D지도 API 2.0은 메카르도(EPSG:3857) 좌표계를 사용하고 있다고 합니다.
2. 좌표계의 종류
좌표계는 종류도 많고, 상호 간에 변환 문제가 있어 매우 복잡합니다.
Q&A를 찾아보면 이것에 대한 질문이 꽤 많이 있고,
FAQ를 검색하니 WMS에서 지원하는 좌표계 목록은 아래와 같다고 합니다.
그런데, 위 API 레퍼런스에서는 메카르도(Mercator) 좌표계의 EPSG 번호가 3857로 표시되는데, 여기서는 Google Mercator의 좌표계가 900913으로 표시됩니다.
3. 지도 클릭 시 좌표 가져오기
가. vworld 지도의 클릭한 지점의 좌표 가져오기
클릭 시 좌표를 가져오는 코드는
브이월드API(20201205) 파일(소통공간 - 자료실 - '브이월드 API 샘플' 중 2020-12-05 자료)의
'7.지오코딩 폴더'내 '5.좌표값으로 역지오코더 위치 확인.html'에 있습니다.
/* 클릭 이벤트 제어 */ vmap.on("click", function(evt) { let coordinate = evt.coordinate //좌표정보 ...... }); |
위 코드를 이용해서 지도 클릭 시 좌표값을 반환하는 코드를 만들어보면 아래와 같습니다.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, shrink-to-fit=no">
<title>vworld 위,경도 알아내기</title>
</head>
<body>
<div id="vmap">
<script type="text/javascript" src="https://map.vworld.kr/js/vworldMapInit.js.do?version=2.0&apiKey=CEB52025-E065-364C-9DBA-44880E3B02B8&domain=localhost:8080"></script>
<script type="text/javascript">
vw.ol3.MapOptions = {
basemapType: vw.ol3.BasemapType.GRAPHIC
, controlDensity: vw.ol3.DensityType.EMPTY
, interactionDensity: vw.ol3.DensityType.BASIC
, controlsAutoArrange: true
, homePosition: vw.ol3.CameraPosition
, initPosition: vw.ol3.CameraPosition
};
let vmap = new vw.ol3.Map("vmap", vw.ol3.MapOptions);
vmap.getView().setCenter([14129132.729661161, 4512073.703926638]);
vmap.getView().setZoom(18);
vmap.on("click", function(evt) {
let coordinate = evt.coordinate //좌표정보(EPSG:900913)
alert(coordinate);
});
</script>
</body>
</html>
서버에 올린 후 실행하면 역시나 좌표가 141... 식으로 일반 위, 경도와 다르게 표시됩니다.
나. vworld 지도의 좌표를 위, 경도 좌표로 변환하기
TotalCommander 프로그램을 이용해 위 샘플 파일 폴더인 '브이월드 API(20201205)' 아래서 '위경도 좌표계 변환'이란 문자열이 포함된 파일을 찾으니 아래와 같이 2개가 나옵니다.
2개 중 위 파일을 열어 '위경도 좌표계 변환'이란 글자를 찾으니,
위경도 좌표계를 변환할 때
ol.proj.transform([126.9380517322744,37.16792263658907], 'EPSG:4326', 'EPSG:900913')
을 사용한다는 것을 알 수 있습니다.
그런데 우리에게 친숙한 위 경도를 알기 위해서는 'EPSG:900913'를 'EPSG:4326'형식으로 바꿔야 하므로
ol.proj.transform(coordinate, 'EPSG:900913', 'EPSG:4326')으로 앞뒤를 바꾸면 됩니다.
따라서, 아래 코드와 같은 코드를 추가합니다.
// EPSG:900913 좌표를 EPSG:4326형식으로 변환 var latlng_4326 = ol.proj.transform(coordinate, 'EPSG:900913', 'EPSG:4326'); alert(latlng_4326); |
그리고 실행하면 alert(경고) 창이 두 번 표시되며, 두 번째 표시되는 창은 아래와 같이 경도와 위도로 표시됩니다.
4. 두 가지 좌표를 한 번에 표시하기 1 - 복사 안됨
좌표 2개를 한 번에 표시하기 위해 첫 번째 alert문은 주석 처리하고,
두 번째 alert문을
alert(coordinate + '\n' + latlng_4326);
우로 수정하고 실행하니 좌표가 복사되지 않습니다.
5. 두 가지 좌표를 한 번에 표시하기 2 - SweetAlert2 라이브러리 이용, 복사됨
ChatGPT에게 물어보니 SweetAlert2 라이브러리를 이용하라고 하면서 예제 코드를 아래와 같이 알려줍니다.
<!-- SweetAlert2 라이브러리 추가 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
Swal.fire({
title: "<strong>굵은 글씨</strong>", // 제목을 굵게
html: "여기에 <b>굵은 텍스트</b>를 사용할 수 있어요!", // 본문에 HTML 사용 가능
icon: "info"
});
</script>
위를 참고하여 위 코드 중
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>는 head 태그의 맨 아래에 추가하고,
위, 경도를 표시하는 부분은 아래와 같이 코드를 수정합니다.
글자 크기가 너무 커서 font-size를 12px로 하는 부분을 추가하고, 좌표계 표시의 글자를 굵게(<b>) 하고, 왼쪽 정렬(text-align:left)하고, 창의 너비(width)도 380px로 작게 했습니다.
Swal.fire({
title:"<p style='font-size:14px;'>위,경도</p>",
html: "<p style='font-size:12px;text-align:left'><b>EPSG:900913 - </b>" + coordinate + "<br>" + "<b>EPSG:4326 - </b>" +latlng_4326 + "</p>",
width:"380px" //heigth 옵션은 없어서 style로 정해야 함
});
그리고 기존 alert문을 주석처리하고 실행하면 아래와 같이 표시됩니다.
마우스로 긁어서 복사가 되니 너무 편리합니다.
6. 전체 코드
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, shrink-to-fit=no">
<title>vworld 위,경도 알아내기</title>
<!-- SweetAlert2 라이브러리 활용 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</head>
<body>
<div id="vmap">
<script type="text/javascript" src="https://map.vworld.kr/js/vworldMapInit.js.do?version=2.0&apiKey=CEB52025-E065-364C-9DBA-44880E3B02B8&domain=localhost:8080"></script>
<script type="text/javascript">
vw.ol3.MapOptions = {
basemapType: vw.ol3.BasemapType.GRAPHIC
, controlDensity: vw.ol3.DensityType.EMPTY
, interactionDensity: vw.ol3.DensityType.BASIC
, controlsAutoArrange: true
, homePosition: vw.ol3.CameraPosition
, initPosition: vw.ol3.CameraPosition
};
let vmap = new vw.ol3.Map("vmap", vw.ol3.MapOptions);
vmap.getView().setCenter([14129132.729661161, 4512073.703926638]);
vmap.getView().setZoom(18);
vmap.on("click", function(evt) {
let coordinate = evt.coordinate //좌표정보(EPSG:900913)
<!-- alert(coordinate); -->
// EPSG:900913 좌표를 EPSG:4326형식으로 변환
var latlng_4326 = ol.proj.transform(coordinate, 'EPSG:900913', 'EPSG:4326');
<!-- alert(latlng_4326); -->
<!-- alert(coordinate + '\n' + latlng_4326); -->
// 경고 창을 2줄로 표시하면서 복사 가능하게 함
Swal.fire({
title:"<p style='font-size:14px;'>위,경도</p>",
html: "<p style='font-size:12px;text-align:left'><b>EPSG:900913 - </b>" + coordinate + "<br>" + "<b>EPSG:4326 - </b>" +latlng_4326 + "</p>",
width:"380px"
});
});
</script>
</body>
</html>