1. 구현 영상
왼쪽 위에 주소를 입력할 수 있는 칸이 있어서 도로명 주소 또는 지번 주소를 입력하고 검색 버튼 또는 엔터 키를 누르면 해당 위치로 이동한 후 해당 지점에 대한 좌표를 표시합니다.
2. 전체 코드
<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>주소에 대한 좌표 구하기</title>
<!-- 헤드 태그 안에 style 지정 -->
<style type="text/css">
#wrap .buttons { position:absolute;top:20;left:20;z-index:1000;padding:5px; }
#wrap .buttons .control-btn { margin:0 5px 5px 0; }
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
let pop = null ;
// 검색 실행 함수
function get_lat_lng(type = "road") {
if (pop == null) {
pop = new vw.ol3.popup.Popup();
}
const address = $('#addressInput').val().trim(); // inputbox내 입력 값 가져오기
if (address === "") {
alert("주소를 입력하세요.");
return;
}
$.ajax({
url: "https://api.vworld.kr/req/address?",
type: "GET",
dataType: "jsonp",
data: {
service: "address",
request: "GetCoord",
version: "2.0",
crs: "EPSG:4326",
type: type,
address: address,
format: "json",
errorformat: "json",
key: "CEB52025-E065-364C-9DBA-44880E3B02B8"
},
success: function (result) {
if (result.response && result.response.result && result.response.result.point) {
console.log(result);
const arr = [result.response.result.point.x, result.response.result.point.y];
console.log(arr);
const coordinate = arr.map(Number);
console.log(coordinate);
// 좌표 변환 (EPSG:4326 -> EPSG:3857)
const transformedCoord = ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857");
// 지도 중심 이동
vmap.getView().setCenter(transformedCoord);
// 0.5초 후 pop 표시(비동기 처리하여 충돌 방지)
setTimeout(() => {
pop.title = "<b>주소에 대한 좌표</b><br><br>";
const content = address + " 의 좌표는 <br><br>" + result.response.result.point.x + ',<br>' + result.response.result.point.y + " 입니다.";
vmap.addOverlay(pop);
pop.show(content, transformedCoord);
}, 500);
} else if (type === "road") {
// road 검색 결과가 없으면 parcel로 재요청
console.log("검색 결과 없음. 'parcel' 타입으로 재검색합니다.");
get_lat_lng("parcel");
} else {
console.log("검색 결과를 찾을 수 없습니다.");
}
},
error: function () {
console.log("API 요청 실패");
}
});
}
// 버튼 클릭 시 검색 실행
$('#searchBtn').click(function () {
get_lat_lng();
});
// Enter 키 입력 시 검색 실행
$('#addressInput').keydown(function (event) {
if (event.key === "Enter") {
event.preventDefault(); // 폼이 제출되지 않도록 방지
get_lat_lng();
}
});
});
</script>
</head>
<body>
<!-- div 태그의 순서는 영향 없음 -->
<div id="vmap">
<div id="wrap">
<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>
<div class="buttons">
<input type="text" size="30" id="addressInput" value="">
<button id="searchBtn" type="button" >검색</button>
</div>
<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);
</script>
</div>
</div>
</body>
</html>
3. 코드 살펴보기
가. JQuery 선언 및 사용
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script type="text/javascript"> $(document).ready(function () { |
head 태그 안에서
https://code.jquery.com/jquery-3.6.0.min.js">를 이용해 jquery를 참고하도록 하고,
$로 시작하는 각종 구문을 사용합니다.
그 중 첫번째로 나오는
$(document).ready(function () {
...
});
은 'html 문서가 준비되면, 다시 말해 문서 로딩이 끝나면 안에 있는 구문을 실행하라는 의미입니다.
나. type(검색 주소 유형)을 '도로명 주소'로 지정
function get_lat_lng(type = "road") { |
주소 형태의 기본값을 도로명 주소로 지정했습니다.
다. 도로명 주소로 검색 후 에러 시 지번 주소로 검색
success: function (result) { if (result.response && result.response.result && result.response.result.point) { ... } else if (type === "road") { // road 검색 결과가 없으면 parcel로 재요청 console.log("검색 결과 없음. 'parcel' 타입으로 재검색합니다."); get_lat_lng("parcel"); } else { console.log("검색 결과를 찾을 수 없습니다."); } |
result.response와 result.response.result 가 있고, result.response.result.point가 있을 경우만 도로명 주소에 대한 좌표가 있는 것이므로 그때는 그대로 좌표값을 표시하면 되는데,
그렇지 않고 type이 'road(도로명 주소)'라면
console 창(F12키 클릭 또는 마우스 오른쪽 버튼 클릭 후 검사 메뉴 클릭)에
"검색 결과 없음. 'parcel' 타입으로 재검색합니다."라고 표시하고,
'parcel(지번 주소)' type으로 검색을 실시합니다.
라. 좌표의 작은따옴표 제거
const arr = [result.response.result.point.x, result.response.result.point.y]; console.log(arr); const coordinate = arr.map(Number); console.log(coordinate); |
[result.response.result.point.x, result.response.result.point.y]의 배열을 확인하면
아래와 같이 숫자 좌우에 작은따옴표가 있어서
EPSG:4326 기준 좌표를 "EPSG:3857"로 바꿀 때 에러가 발생하기 때문에
-> const transformedCoord = ol.proj.transform(arr, "EPSG:4326", "EPSG:3857");
좌표만 표시되고, 지도는 표시되지 않으므로
const coordinate = arr.map(Number);를 사용해서 좌표를 문자가 아닌 숫자 형식으로 바꿔야 합니다.
console.log를 이용해 확인하면 아래와 같이 작은따옴표가 제외되었습니다.
마. 지도 중심 이동
위에서 구한 transformedCoord를 이용해 주소에 해당하는 좌표로 이동합니다.
// 지도 중심 이동 vmap.getView().setCenter(transformedCoord); |
바. 지도가 제대로 이동하지 않고 popup은 표시되지 않는 문제 해결
아래와 같이 popup 창의 제목(title)과 내용(content)을 설정하고 실행하면
pop.title = "<b>주소에 대한 좌표</b><br><br>"; const content = address + " 의 좌표는 <br><br>" + result.response.result.point.x + ',<br>' + result.response.result.point.y + " 입니다."; vmap.addOverlay(pop); pop.show(content, transformedCoord); |
좌표를 표시한 후
지도가 제대로 이동하지 못하는 문제점이 있으므로
setTimeout 함수를 이용해 지도를 이동할 수 있는 시간(5초)을 확보한 후 popup 창을 표시하도록 해야 합니다. 그러면 지도도 잘 이동하고, 팝업 창도 잘 표시됩니다.
// 0.5초 후 pop 표시(비동기 처리하여 충돌 방지) setTimeout(() => { pop.title = "<b>주소에 대한 좌표</b><br><br>"; const content = address + " 의 좌표는 <br><br>" + result.response.result.point.x + ',<br>' + result.response.result.point.y + " 입니다."; vmap.addOverlay(pop); pop.show(content, transformedCoord); }, 500); |
사. 검색 버튼뿐만 아니라 엔터 키를 눌러도 되도록 코드 작성
// 버튼 클릭 시 검색 실행 $('#searchBtn').click(function () { get_lat_lng(); }); // Enter 키 입력 시 검색 실행 $('#addressInput').keydown(function (event) { if (event.key === "Enter") { event.preventDefault(); // 폼이 제출되지 않도록 방지 get_lat_lng(); } }); |
아래를 보면 검색 버튼의 id는 searchBtn이고, inputbox의 id는 addressInput라 모두 #을 앞에 붙여서 위 함수를 작성했습니다.
<div class="buttons"> <input type="text" size="30" id="addressInput" value=""> <button id="searchBtn" type="button" >검색</button> </div> |
아. 지도 위에 inputbox 및 검색 버튼 배치
<!-- 헤드 태그 안에 style 지정 --> <style type="text/css"> #wrap .buttons { position:absolute;top:20;left:20;z-index:1000;padding:5px; } #wrap .buttons .control-btn { margin:0 5px 5px 0; } </style> <!-- div 태그의 순서는 영향 없음 --> <div id="vmap"> <div id="wrap"> |
style로 id가 wrap인 div와 class가 buttons인 button의 설정을 하고,
body안에서 적용합니다.
'Map(WEB)' 카테고리의 다른 글
vworld 지도 만들기(11) - 좌표에 대한 주소 검색하기(3) (2) | 2025.02.14 |
---|---|
vworld 지도 만들기(10) - 주소에 대한 좌표 구하기(1) (0) | 2025.02.13 |
vworld 지도 만들기(9) - 좌표에 대한 주소 검색하기(2) (0) | 2025.02.12 |
vworld 지도 만들기(8) - 좌표에 대한 주소 검색하기(1) (0) | 2025.02.11 |
vworld 지도 만들기(7) - 좌표(위, 경도) 알아내기 (0) | 2025.02.10 |