olrlobt
[Java] 카카오 지도 / 시도 시군구 행정구역 폴리곤으로 구분하기 본문
시도 시군구 행정구역 폴리곤으로 구분하기
카카오 맵 API에서는 지도 위에 원, 선, 다각형 등을 표시하고 이벤트를 넣을 수 있는데,
이를 활용하여 우리나라의 시도/시군구/행정구역을 폴리곤(다각형)으로 표시할 수 있다.
카카오 지도 API 다각형 그리기
카카오 지도 API에서는 아래와 같은 방법으로 다각형을 그릴 수 있다.
카카오 지도 API 공식 홈페이지 - 다각형 그리기 :
https://apis.map.kakao.com/web/sample/drawShape/
// 다각형을 구성하는 좌표 배열입니다. 이 좌표들을 이어서 다각형을 표시합니다
var polygonPath = [
new kakao.maps.LatLng(33.45133510810506, 126.57159381623066),
new kakao.maps.LatLng(33.44955812811862, 126.5713551811832),
new kakao.maps.LatLng(33.449986291544086, 126.57263296172184),
new kakao.maps.LatLng(33.450682513554554, 126.57321034054742),
new kakao.maps.LatLng(33.451346760004206, 126.57235740081413)
];
// 지도에 표시할 다각형을 생성합니다
var polygon = new kakao.maps.Polygon({
path:polygonPath, // 그려질 다각형의 좌표 배열입니다
strokeWeight: 3, // 선의 두께입니다
strokeColor: '#39DE2A', // 선의 색깔입니다
strokeOpacity: 0.8, // 선의 불투명도 입니다 1에서 0 사이의 값이며 0에 가까울수록 투명합니다
strokeStyle: 'longdash', // 선의 스타일입니다
fillColor: '#A2FF99', // 채우기 색깔입니다
fillOpacity: 0.7 // 채우기 불투명도 입니다
});
// 지도에 다각형을 표시합니다
polygon.setMap(map);
이 방법을 이용해서, 아래와 같이 행정 구역을 다각형으로 나누어 줄 것이다.
대한민국 행정구역 다운로드
http://www.gisdeveloper.co.kr/?p=2332
먼저 위 링크에서 행정구역을 나누기 위한 모델링 파일을 다운로드한다.
여기서 다운로드한 파일들은. shp 등의 파일로, 사용하기 위해서는 Json 변환이 필요하다.
아니면, 아래과정을 일부 생략하고, 내가 사용했던 아래파일을 받아도 무방하다.
시/도 :
시/군/구 :
원하는 구현 정도에 따라, 알맞은 파일을 받아서 사용하면 되고,
나의 경우에는 줌인, 줌 아웃에 따라 보이는 정도를 달라지게 할 것이기 때문에,
시, 도 / 시, 군, 구 / 두 파일을 사용했다.
폴리곤 간소화와 JSON 변경
대한민국 행정구역의 경계는 일직선이 아니기 때문에 매우 복잡한 다각형으로 되어 있다.
이에 따라 용량도 꽤나 크고, 다각형의 각의 개수도 많기 때문에 카카오 맵 API에서 폴리곤을 Load 할 때까지의 시간이 오래 걸리게 된다.
따라서, 이 로딩 시간을 줄이기 위하여, 폴리곤을 간소화하는 방법을 사용했다.
위 사이트를 이용하여 폴리곤을 간소화하고 Json으로 추출해 보자.
위 사이트에 접속하면 아래와 같은 화면이 나온다.
여기에 앞선 홈페이지에서 다운로드한. shp 파일을 로드한다.
Import를 해 주면,
위처럼, 폴리곤의 형태를 미리 보기로 볼 수 있다.
여기서 폴리곤을 간소화하기 위해, 우측 상단의 Simplify를 누른다.
그럼 위와 같은 설정 창이 하나 뜬다.
Prevent shape removal : 폴리곤을 간소화하면서, 완전히 삭제되지는 않게 하는 설정이다.
Method : 폴리곤을 간소화하는 알고리즘을 선택한다.
여기서 나는, 아무것도 건들지 않고 기본 설정으로 넘어갔다.
그러면 상단에, 간소화 정도를 설정할 수 있는 드래그바가 생성이 되고 이를 조절하여 폴리곤을 간소화할 수 있다.
너무 높은 수치를 사용하면, 용량과 점의 개수가 많아 로딩 시간이 오래 걸리게 되고,
너무 낮은 수치를 사용하면, 생략되어 사라져 버리는 지점이 있기 때문에 적당한 지점을 찾아서 설정해 주자.
개인적으로 15% ~ 5%가 사라지는 지점 없이 적당하다고 생각된다.
간소화를 마쳤다면, Export를 눌러 Json 형식으로 추출해 주자.
코드 구현
let mapContainer = document.getElementById('map'), // 지도를 표시할 div
mapOption = {
center: new kakao.maps.LatLng(37.566826, 126.9786567), // 지도의 중심좌표
level: 12 // 지도의 확대 레벨
};
let map = new kakao.maps.Map(mapContainer, mapOption),
customOverlay = new kakao.maps.CustomOverlay({})
let detailMode = false; // level에 따라 다른 json 파일 사용
let level = '';
let polygons = [];
init("json/sido.json") // 초기 시작
kakao.maps.event.addListener(map, 'zoom_changed', function () {
level = map.getLevel()
if (!detailMode && level <= 10) { // level 에 따라 다른 json 파일을 사용한다.
detailMode = true;
removePolygon();
init("json/sig.json")
} else if (detailMode && level > 10) { // level 에 따라 다른 json 파일을 사용한다.
detailMode = false;
removePolygon();
init("json/sido.json")
}
});
// 모든 폴리곤을 지우는 함수
function removePolygon() {
for (let i = 0; i < polygons.length; i++) {
polygons[i].setMap(null);
}
areas = [];
polygons = [];
}
// 폴리곤 생성
function init(path) {
//path 경로의 json 파일 파싱
$.getJSON(path, function (geojson) {
var units = geojson.features; // json key값이 "features"인 것의 value를 통으로 가져온다.
$.each(units, function (index, unit) { // 1개 지역씩 꺼내서 사용. val은 그 1개 지역에 대한 정보를 담는다
var coordinates = []; //좌표 저장할 배열
var name = ''; // 지역 이름
var cd_location = '';
coordinates = unit.geometry.coordinates; // 1개 지역의 영역을 구성하는 다각형의 모든 좌표 배열
name = unit.properties.SIG_KOR_NM; // 1개 지역의 이름
cd_location = unit.properties.SIG_CD;
var ob = new Object();
ob.name = name;
ob.path = [];
ob.location = cd_location;
$.each(coordinates[0], function (index, coordinate) {
ob.path
.push(new kakao.maps.LatLng(coordinate[1],
coordinate[0]));
});
areas[index] = ob;
});//each
});//getJSON
// 지도에 영역데이터를 폴리곤으로 표시
for (var i = 0, len = areas.length; i < len; i++) {
displayArea(areas[i]);
}
function displayArea(area) {
var polygon = new kakao.maps.Polygon({
map: map,
path: area.path,
strokeWeight: 2,
strokeColor: '#004c80',
strokeOpacity: 0.8,
fillColor: '#fff',
fillOpacity: 0.7
});
polygons.push(polygon);
kakao.maps.event.addListener(polygon, 'mouseover', function (mouseEvent) {
polygon.setOptions({fillColor: '#09f'});
customOverlay.setContent('<div class="area">' + area.name + '</div>');
customOverlay.setPosition(mouseEvent.latLng);
customOverlay.setMap(map);
});
kakao.maps.event.addListener(polygon, 'mousemove', function (mouseEvent) {
customOverlay.setPosition(mouseEvent.latLng);
});
kakao.maps.event.addListener(polygon, 'mouseout', function () {
polygon.setOptions({fillColor: '#fff'});
customOverlay.setMap(null);
});
kakao.maps.event.addListener(polygon, 'click', function (mouseEvent) {
if (!detailMode) {
map.setLevel(10); // level에 따라 이벤트 변경
var latlng = mouseEvent.latLng;
// 지도의 중심을 부드럽게 클릭한 위치로 이동시킵니다.
map.panTo(latlng);
} else {
// 클릭 이벤트 함수
// callFunctionWithRegionCode(area.location);
}
});
}
}
코드는 주석으로 설명이 되어 있고,
카카오 공식 홈페이지를 참고하며 이해하면 큰 문제없이 해결할 수 있을 것이라 생각되어,
자세한 설명은 생략하려 한다.
결과
시작하게 되면, 시/도로 이루어진 폴리곤이 보이고,
레벨에 따라, 시/도 폴리곤과 시/군/구 폴리곤이 알맞게 나오게 설정하였다.
또한,
시/도에서 클릭하게 되면, 시/군/구로 이루어진 폴리곤이 나오게 확대되고,
시/군/구 에서 클릭하게 되면, 내가 원하는 데이터의 좌표에 마커가 찍히게끔 구현하였다.
'Spring > Maps' 카테고리의 다른 글
[Spring] 카카오 지도 / Kakao Map Web API 여러개의 마커를 클러스터러로 표기해보기 (1) | 2023.01.19 |
---|---|
[Spring] 카카오 지도 / Kakao Map Web API 마커, 마커 인포윈도우, 마커 이미지 변경 (0) | 2023.01.16 |
[Spring] 카카오 지도 / Kakao Map Web API 사용해보기 (5) | 2023.01.16 |