WEB JS

웹 개발, 어플리케이션에서 활용될 수 있도록 Javascript로 제공되는 지도 플랫폼 입니다.

Geo-fencing 생성

소개

이 튜토리얼에서는 사용자 위치를 이용하여 구역 검색 API(행정 면형 정보 API) 호출, 그 결과를 토대로 행정경계를 표시하고 어느 행정경계에 포함되는지 안내하는 과정에 대해 설명합니다.

준비

1. 기본 지도 생성

기본 지도를 생성합니다.

// js
$(function () {
  // 1. 기본 지도 생성
  const options = {
    // 지도 초기 위치
    center: { lat : 37.5100, lng: 127.0504 },
    // 지도 로딩 시 최초 표시 레벨
    zoom: 16,
    // 지도 최소 표시 레벨
    minZoom: 7,
    // 지도 최대 표시 레벨
    maxZoom: 19,
    // 지도 회전 가능 여부
    enableRotation: true,
    // 키보드 단축키로 지도 이동 가능 여부
    keyboardShortcuts: false
  };
  const map = new routo.maps.Map('map', options);
});
<!-- html -->
<!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>
</head>
<body>
    <div id="map" style="width:100%;height:500px;"></div>
</body>
</html>

2. 현재 사용자의 위치 표시

Javascript navigator.geolocation를 이용하여 현재 사용자의 위치를 지도에 마커로 표시합니다.

// js
$(function () {
  // 1. 기본 지도 생성
  const options = {
    // 지도 초기 위치
    center: { lat : 37.5100, lng: 127.0504 },
    // 지도 로딩 시 최초 표시 레벨
    zoom: 16,
    // 지도 최소 표시 레벨
    minZoom: 7,
    // 지도 최대 표시 레벨
    maxZoom: 19,
    // 지도 회전 가능 여부
    enableRotation: true,
    // 키보드 단축키로 지도 이동 가능 여부
    keyboardShortcuts: false
  };
  const map = new routo.maps.Map('map', options);

  // 2. 현재 사용자의 위치 표시
  const getLocation = () => {
    if (navigator.geolocation) { // GPS를 지원하면
      navigator.geolocation.getCurrentPosition(function(position) {
        // 좌표 표시
        $('#coordinates').html(`<p style="margin-top:10px;font-size:15px;text-align: left;">현재 사용자 위치: ${position.coords.latitude + ' ' + position.coords.longitude}</p>`);

        // 마커 추가
        const lng = position.coords.longitude;
        const lat = position.coords.latitude;

        const markerOption = {
          position: {
            lat: lat,
            lng: lng
          },
          map: map
        };

        const userPositionMarker = new routo.maps.Marker(markerOption);

        // 마커로 지도 이동
        map.setCenter(markerOption.position);

      }, function(error) {
        console.error(error);
      }, {
        enableHighAccuracy: false,
        maximumAge: 0,
        timeout: Infinity
      });
    } else {
      alert('GPS를 지원하지 않습니다');
    }
  }
  getLocation();
});
<!-- html -->
<!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>
</head>
<body>
    <div id="map" style="width:100%;height:500px;"></div>
    <div id="coordinates" style="background-color: beige;"></div>
</body>
</html>

3. 구역 검색 API를 이용한 행정경계 표시

사용자 위치 기반으로 구역 검색 API를 호출하여 행정경계 Polygon을 지도에 표시합니다.

// js
$(function () {
  // 1. 기본 지도 생성
  const options = {
    // 지도 초기 위치
    center: { lat : 37.5100, lng: 127.0504 },
    // 지도 로딩 시 최초 표시 레벨
    zoom: 16,
    // 지도 최소 표시 레벨
    minZoom: 7,
    // 지도 최대 표시 레벨
    maxZoom: 19,
    // 지도 회전 가능 여부
    enableRotation: true,
    // 키보드 단축키로 지도 이동 가능 여부
    keyboardShortcuts: false
  };
  const map = new routo.maps.Map('map', options);

  // 2. 현재 사용자의 위치 표시
  const getLocation = () => {
    if (navigator.geolocation) { // GPS를 지원하면
      navigator.geolocation.getCurrentPosition((position) => {
        // 좌표 표시
        $('#coordinates').html(`<p style="margin-top:10px;font-size:15px;text-align: left;">현재 사용자 위치: ${position.coords.latitude + ' ' + position.coords.longitude}</p>`);
        
        // 마커 추가
        const lng = position.coords.longitude;
        const lat = position.coords.latitude;

        const markerOption = {
          position: {
            lat: lat,
            lng: lng
          },
          map: map
        };

        const userPositionMarker = new routo.maps.Marker(markerOption);

        // 마커로 지도 이동
        map.setCenter(markerOption.position);

        // 3.구역 검색 API를 이용한 행정경계 표시
        callDistrict(markerOption.position);

      }, function(error) {
        console.error(error);
      }, {
        enableHighAccuracy: false,
        maximumAge: 0,
        timeout: Infinity
      });
    } else {
      alert('GPS를 지원하지 않습니다');
    }
  }
  getLocation();


  // 구역 검색 API를 이용한 행정경계 표시
  const callDistrict = (position) => {
    const key = `               `;
    const districtApiUrl = `https://api.routo.com/v1/district?latlng=${position.lat},${position.lng}&kind=gemd&option=shape&key=${key}`;
    fetch(districtApiUrl).then(function(response) {
      return response.json();
    }).then(function(data) {
      // 행정경계 생성
      const prop = { ...data };
      delete prop.geometry;

      // Geometry 좌표 타입 변환(Array => LatLng)
      const convertGeom = [];
      for(let i in data.geometry.coordinates){
        const coordinates = data.geometry.coordinates[i];
        const coords = [];
        for(let j in coordinates){
          const coord = coordinates[j];
          const latlng = new routo.maps.LatLng(coord[1], coord[0]);
          const latlngJson = latlng.toJSON();
          coords.push(latlngJson);
        }
        convertGeom.push(coords);
      }

      // Polygon 생성
      const polygon = new routo.maps.Data.Polygon(convertGeom);

      // 행정경계 추가
      map.data.add({
        id: 1,
        geometry: polygon,
        properties: prop
      });

      // 지도 이동
      map.fitBounds(polygon.getBounds(), [100, 100, 100, 100]);
    }).catch(function(error) {
      console.log(error);
    });
  }
});
<!-- html -->
<!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>
</head>
<body>
    <div id="map" style="width:100%;height:500px;"></div>
</body>
</html>

4. 결과 확인

사용자 위치가 현재 어떤 행정경계에 속하였는지 표시합니다.

// js
$(function () {
  // 1. 기본 지도 생성
  const options = {
    // 지도 초기 위치
    center: { lat : 37.5100, lng: 127.0504 },
    // 지도 로딩 시 최초 표시 레벨
    zoom: 16,
    // 지도 최소 표시 레벨
    minZoom: 7,
    // 지도 최대 표시 레벨
    maxZoom: 19,
    // 지도 회전 가능 여부
    enableRotation: true,
    // 키보드 단축키로 지도 이동 가능 여부
    keyboardShortcuts: false
  };
  const map = new routo.maps.Map('map', options);

  // 2. 현재 사용자의 위치 표시
  const getLocation = () => {
    if (navigator.geolocation) { // GPS를 지원하면
      navigator.geolocation.getCurrentPosition((position) => {
        // 좌표 표시
        $('#coordinates').html(`<p style="margin-top:10px;font-size:15px;text-align: left;">현재 사용자 위치: ${position.coords.latitude + ' ' + position.coords.longitude}</p>`);

        // 마커 추가
        const lng = position.coords.longitude;
        const lat = position.coords.latitude;

        const markerOption = {
          position: {
            lat: lat,
            lng: lng
          },
          map: map
        };

        const userPositionMarker = new routo.maps.Marker(markerOption);

        // 마커로 지도 이동
        map.setCenter(markerOption.position);

        // 3.구역 검색 API를 이용한 행정경계 표시
        callDistrict(markerOption.position);

      }, function(error) {
        console.error(error);
      }, {
        enableHighAccuracy: false,
        maximumAge: 0,
        timeout: Infinity
      });
    } else {
      alert('GPS를 지원하지 않습니다');
    }
  }
  getLocation();


  // 구역 검색 API를 이용한 행정경계 표시
  const callDistrict = (position) => {
    const key = `                `;
    const districtApiUrl = `https://api.routo.com/v1/district?latlng=${position.lat},${position.lng}&kind=gemd&option=shape&key=${key}`;
    fetch(districtApiUrl).then(function(response) {
      return response.json();
    }).then(function(data) {
      // 행정경계 생성
      const prop = { ...data };
      delete prop.geometry;

      // Geometry 좌표 타입 변환(Array => LatLng)
      const convertGeom = [];
      for(let i in data.geometry.coordinates){
        const coordinates = data.geometry.coordinates[i];
        const coords = [];
        for(let j in coordinates){
          const coord = coordinates[j];
          const latlng = new routo.maps.LatLng(coord[1], coord[0]);
          const latlngJson = latlng.toJSON();
          coords.push(latlngJson);
        }
        convertGeom.push(coords);
      }

      // Polygon 생성
      const polygon = new routo.maps.Data.Polygon(convertGeom);

      // 행정경계 추가
      map.data.add({
        id: 1,
        geometry: polygon,
        properties: prop
      });

      // 지도 이동
      map.fitBounds(polygon.getBounds(), [100, 100, 100, 100]);

      // 4. 결과 확인
      let tag = `당신은 ${prop['state']} ${prop['city']} ${prop['town']} 에 있습니다.`;
      for(let k in prop){
        const attr = k;
        const value = prop[k];
        tag += `<p style="margin-top:10px;font-size:15px;text-align: left;">- ${attr}: ${value}</p>`;
      }
      $('#result').html(tag);
    }).catch(function(error) {
      console.log(error);
    });
  }
});
<!-- html -->
<!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>
</head>
<body>
    <div id="map" style="width:100%;height:500px;"></div>
    <div id="result" style="background-color: beige;"></div>
</body>
</html>