[JavaScript] 카카오맵 행정구역 동 단위 경계 표시하기

호이·2023년 3월 13일
0

JavaScript

목록 보기
4/4

1. 카카오 API

카카오맵을 사용할려면 카카오맵의 API가 필요하다. 다음의 링크에서 카카오 계정으로 로그인한다.
https://apis.map.kakao.com/

로그인을 하였다면 다음같은 페이지가 나타날 것이다. 필자의 경우는 등록된 API가 있기 때문에 어플리케이션이 존재한다. 카카오맵 API를 처음 사용한다면 전체 어플리케이션이 아무 것도 없을 것이다.

해당 페이지에서 어플리케이션 추가하기 버튼을 누르면 다음과 같은 창이 나타날 것이다.

해당 창에서 앱 아이콘과 이름 등을 입력하여 어플리케이션을 등록한다. 테스트 용도의 어플리케이션을 생성할 것이라면 앱 이름과 사업자명 란에 테스트라고 입력한 뒤 동의를 체크하고 저장을 누르면 된다. 어플리케이션을 생성한 후 해당 어플리케이션을 클릭하면 다음과 같은 페이지가 나타날 것이다.

해당 페이지에서 카카오맵의 API 키가 생성되어 있다. 여기서 필요한 것은 자바스크립트 키이다. 해당 키를 복사한다.

2. 카카오맵 API

카카오맵 API에 대한 자세한 설명은 다음의 링크를 참조하면 된다.
https://apis.map.kakao.com/web/guide/

카카오맵 API를 적용하는 방법은 아래의 코드를 추가하면 된다.

<script src="//dapi.kakao.com/v2/maps/sdk.js?appkey=카카오 API Key"></script>

카카오맵 API의 동작을 테스트하고 싶으면 기본적인 카카오맵을 생성하는 것으로 테스트할 수 있다. 다음의 코드로 기본적인 지도를 생성할 수 있다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>지도 생성하기</title>
  </head>
  <body>
    <!-- 지도를 표시할 div 입니다 -->
    <div id="map" style="width: 100%; height: 98vh"></div>
    <script src="//dapi.kakao.com/v2/maps/sdk.js?appkey=카카오 API Key"></script>
    <script>
      var mapContainer = document.getElementById("map"), // 지도를 표시할 div
        mapOption = {
          center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
          level: 3, // 지도의 확대 레벨
        };
      // 지도를 표시할 div와  지도 옵션으로  지도를 생성합니다
      var map = new kakao.maps.Map(mapContainer, mapOption);
    </script>
  </body>
</html>

3. 개발하기

행정구역 경계에 대한 데이터를 받아오기 위해 다음의 github자료를 참조하였다. 다음의 링크에서 행정구역 경계를 json형태로 저장된 데이터를 다운로드 받을 수 있다.
https://github.com/vuski/admdongkor

카카오맵의 서비스를 사용하기 위해 다음의 APIjQuery를 사용을 위한 다음의 코드를 추가한다.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<script src="//dapi.kakao.com/v2/maps/sdk.js?appkey=카카오 API Key&libraries=services,clusterer"></script>

행정구역에 마우스를 가리켰을 때 해당 행정구역 명을 또렷히 표시하기 위해 스타일 시트를 추가하였다. 해당 코드는 웹의 스타일을 바꾸어주는 용도 이므로 필요할 경우 추가하면 된다.

body {
  margin: 0px;
}
.overlaybox {
  position: relative;
  display: inline-block;
  background: #284a6e no-repeat;
  padding: 10px;
  border-radius: 10px;
  color: #fff;
}

생성한 지도를 보여주는 div태그를 생성한다.

<div id="map" style="width: 100%; height: 100vh"></div>

다음의 코드로 지도를 생성하고 행정구역 경계면을 Polygon으로 그려주는 함수를 추가한다.

var map = null,
  customOverlay = new kakao.maps.CustomOverlay({}),
  kkoMap = {
    // 지도 생성 및 초기화 함수
    initKko: function (o) {
      var e = o.mapId,
        t = document.getElementById(e),
        a = {
          center: new kakao.maps.LatLng(37.567509, 126.980663),
          level: 13,
        };
      (map = new kakao.maps.Map(t, a)),
        // 행정구역 경계 데이터를 가져온다.
        $.getJSON("sigu.json", function (o) {
          let e = $(o.features);
          e.each(function () {
            kkoMap.getPolycode($(this)[0]);
          });
        });
    },
    // 경계면 좌표를 가져오는 함수
    getPolycode: function (o) {
      var e = [],
        t = o.geometry;
      if ("Polygon" == t.type) {
        var a = t.coordinates[0],
          n = { name: o.properties.adm_nm, path: [] };
        for (var s in a)
          e.push({ x: p[s][1], y: p[s][0] }),
            n.path.push(new kakao.maps.LatLng(a[s][1], a[s][0]));
        kkoMap.setPolygon(n, e);
      } else if ("MultiPolygon" == t.type)
        for (var s in t.coordinates) {
          var p = t.coordinates[s],
            n = { name: o.properties.adm_nm, path: [] };
          for (var r in p[0])
            e.push({ x: p[0][r][1], y: p[0][r][0] }),
              n.path.push(new kakao.maps.LatLng(p[0][r][1], p[0][r][0]));
          kkoMap.setPolygon(n, e);
        }
    },
    // 경계면 좌표에 따라 Polygon을 그리는 함수
    setPolygon: function (o, e) {
      var t = new kakao.maps.Polygon({
        name: o.name,
        path: o.path,
        strokeWeight: 2,
        strokeColor: "#004c80",
        strokeOpacity: 0.8,
        fillColor: "#fff",
        fillOpacity: 0.7,
      });
      kakao.maps.event.addListener(t, "mouseover", function (a) {
        t.setOptions({ fillColor: "#09f" }),
          customOverlay.setPosition(kkoMap.centroid(e)),
          customOverlay.setContent(
            "<div class='overlaybox'>" + o.name + "</div>"
          ),
          customOverlay.setMap(map);
      }),
        kakao.maps.event.addListener(t, "mouseout", function () {
          t.setOptions({ fillColor: "#fff" }), customOverlay.setMap(null);
        }),
        t.setMap(map);
    },
    // 경계면의 중심좌표를 구하는 함수
    centroid: function (o) {
      var e, t, a, n, s, p, r, i, l;
      for (e = 0, r = i = l = 0, t = (a = o.length) - 1; e < a; t = e++)
        (n = o[e]),
          (s = o[t]),
          (p = n.y * s.x - s.y * n.x),
          (i += (n.x + s.x) * p),
          (l += (n.y + s.y) * p),
          (r += 3 * p);
      return new kakao.maps.LatLng(i / r, l / r);
    },
  };

해당 함수를 페이지 로드가 완료될 경우 바로 실행하기 위하여 다음의 코드를 추가한다.

$(function () {
  kkoMap.initKko({ mapId: "map" });
});

전체 코드는 다음과 같다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <script src="//dapi.kakao.com/v2/maps/sdk.js?appkey=카카오 API Key&libraries=services,clusterer"></script>
    <style>
      body {
        margin: 0px;
      }
      .overlaybox {
        position: relative;
        display: inline-block;
        background: #284a6e no-repeat;
        padding: 10px;
        border-radius: 10px;
        color: #fff;
      }
    </style>
    <script>
      var map = null,
        customOverlay = new kakao.maps.CustomOverlay({}),
        kkoMap = {
          initKko: function (o) {
            var e = o.mapId,
              t = document.getElementById(e),
              a = {
                center: new kakao.maps.LatLng(37.567509, 126.980663),
                level: 13,
              };
            (map = new kakao.maps.Map(t, a)),
              $.getJSON("./json/sigu.json", function (o) {
                let e = $(o.features);
                e.each(function () {
                  kkoMap.getPolycode($(this)[0]);
                });
              });
          },
          getPolycode: function (o) {
            var e = [],
              t = o.geometry;
            if ("Polygon" == t.type) {
              var a = t.coordinates[0],
                n = { name: o.properties.adm_nm, path: [] };
              for (var s in a)
                e.push({ x: p[s][1], y: p[s][0] }),
                  n.path.push(new kakao.maps.LatLng(a[s][1], a[s][0]));
              kkoMap.setPolygon(n, e);
            } else if ("MultiPolygon" == t.type)
              for (var s in t.coordinates) {
                var p = t.coordinates[s],
                  n = { name: o.properties.adm_nm, path: [] };
                for (var r in p[0])
                  e.push({ x: p[0][r][1], y: p[0][r][0] }),
                    n.path.push(new kakao.maps.LatLng(p[0][r][1], p[0][r][0]));
                kkoMap.setPolygon(n, e);
              }
          },
          setPolygon: function (o, e) {
            var t = new kakao.maps.Polygon({
              name: o.name,
              path: o.path,
              strokeWeight: 2,
              strokeColor: "#004c80",
              strokeOpacity: 0.8,
              fillColor: "#fff",
              fillOpacity: 0.7,
            });
            kakao.maps.event.addListener(t, "mouseover", function (a) {
              t.setOptions({ fillColor: "#09f" }),
                customOverlay.setPosition(kkoMap.centroid(e)),
                customOverlay.setContent(
                  "<div class='overlaybox'>" + o.name + "</div>"
                ),
                customOverlay.setMap(map);
            }),
              kakao.maps.event.addListener(t, "mouseout", function () {
                t.setOptions({ fillColor: "#fff" }), customOverlay.setMap(null);
              }),
              t.setMap(map);
          },
          centroid: function (o) {
            var e, t, a, n, s, p, r, i, l;
            for (e = 0, r = i = l = 0, t = (a = o.length) - 1; e < a; t = e++)
              (n = o[e]),
                (s = o[t]),
                (p = n.y * s.x - s.y * n.x),
                (i += (n.x + s.x) * p),
                (l += (n.y + s.y) * p),
                (r += 3 * p);
            return new kakao.maps.LatLng(i / r, l / r);
          },
        };
      $(function () {
        kkoMap.initKko({ mapId: "map" });
      });
    </script>
  </head>
  <body>
    <div id="map" style="width: 100%; height: 100vh"></div>
  </body>
</html>
profile
기억하기 싫어서 기록하는 작은 공간

0개의 댓글