FrontEnd/Vue

[Vue] Vue3 기반 프로젝트에서 카카오맵 API를 통해 지도를 뿌려보자. (2) 지도검색 및 지도 이동

모찌바라기 2022. 3. 9. 00:38
728x90
반응형

저번 글에 이어, 주소검색 및 지도이동을 구현하려고 한다 ( 해당 글 참조 )

카카오맵API에서 함수를 다 제공하기 때문에 그냥 가져다 쓰기만 하면 된다. 그냥 API연습 겸...

 

오늘은 MapHeader.vue를 중점적으로 보려고 한다.

 

 

우선 데이터를 담을 데이터 객체를 선언해보자.

 

data() {
    return {
        keyWord : '', // 검색키워드 v-model을 통해 검색단어를 받아옴
        placeArray : [] // 검색결과를 담는 배열
    }
},

 

그리고 실제로 API를 통해 주소검색을 하는 메서드를 선언한다.

 

searchBox : function(){

    this.placeArray = []; // 배열 초기화

    let places = new kakao.maps.services.Places(); // Places객체 초기화

    let callback = (result, status) => { // 서버통신 콜백함수 선언
        if (status === kakao.maps.services.Status.OK) { 
            this.placeArray = this.placeArray.concat(result); 배열에 데이터 담음
        }
    };
    // 검색단어와 콜백함수를 인자로 하는 keywordSearch함수 호출
    // 카카오맵API에서 지원하는 함수이므로 그냥 갖다 쓰기만 하면 됨
    places.keywordSearch(this.keyWord, callback);
},

 

이렇게 까지 하면 검색은 잘 될 것이다..

 

검색결과

 

근데 주의해야 할 건 카카오맵API에는 라이브러리가 3종류로 나뉘어져 있는데,

<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=APIKEY&libraries=LIBRARY"></script>

<!-- services 라이브러리 불러오기 -->
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=APIKEY&libraries=services"></script>

<!-- services와 clusterer, drawing 라이브러리 불러오기 -->
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=APIKEY&libraries=services,clusterer,drawing"></script>

 

이렇게 3개가 있다. 주소검색은 services에 들어 있으므로, 2번째나 3번째 라이브러리를 가져와야 사용이 가능하다.

첫번째는 진짜 지도만 뿌려주는 라이브러리.. 왠만하면 그냥 3번째꺼 갖다 쓰자

 

이제 저 주소를 클릭했을 때 지도이동을 하는 함수를 호출하는데, 다음과 같이 함수를 선언하였다.

 

setLocation : function(item){ // item을 파라메터로 받음

    let mapContainer = document.getElementById('kakaoMap'), // 지도를 표시할 div 
    mapOption = { 
        center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
        level: 3 // 지도의 확대 레벨
    };
    var map = new kakao.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

    var moveLatLon = new kakao.maps.LatLng(item.y, item.x);
    // 지도 중심을 이동 시킵니다
    map.setCenter(moveLatLon);
}

 

 

검색목록의 주소를 클릭하면 해당 위치로 이동한다.

 

 

 

오늘은 검색 및 지도이동을 하였다. 전부 헤더쪽에서만 작성하였고, 스크롤바 같은 기능은 안넣고 그냥

Height만 줄였다. 필요한 사람은 그냥 스크롤바 넣으면 될 듯.. 아래는 전체 코드이다.

 

 

MapHeader.vue

<template>
    <header class="p-3 bg-dark text-white">
    <div class="container">
      <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
        <a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
          <svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap"><use xlink:href="#bootstrap"/></svg>
        </a>

        <ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
          <li><a href="#" class="nav-link px-2 text-secondary">Home</a></li>
          <li><a href="#" class="nav-link px-2 text-white">Features</a></li>
          <li><a href="#" class="nav-link px-2 text-white">Pricing</a></li>
          <li><a href="#" class="nav-link px-2 text-white">FAQs</a></li>
          <li><a href="#" class="nav-link px-2 text-white">About</a></li>
        </ul>

        <form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3" id="searchForm">
          <input type="search" class="form-control form-control-dark" placeholder="Search..." v-model="keyWord" @change="searchBox" aria-label="Search">
            <div class="d-flex gap-5 justify-content-center" id="dropdownFilter">
                <div class="dropdown-menu pt-0 mx-0 rounded-3 shadow overflow-hidden" style="height:500px; width: 280px;" v-if="placeArray.length!=0">
                <ul class="list-unstyled mb-0" v-for="item in placeArray" :key="item">
                    <a class="dropdown-item" href="#" @click="setLocation(item)">
                        <li>
                            <div class="d-flex align-items-center gap-2 py-2">
                                <span class="d-inline-block bg-success rounded-circle" style="width: .5em; height: .5em;"></span>
                                <div>{{item.place_name}}</div>
                            </div>
                            <div class="small">{{item.address_name}}</div>
                        </li>
                    </a>
                </ul>
                </div>
            </div>
        </form>

        <div class="text-end">
          <button type="button" class="btn btn-outline-light me-2">검색</button>
        </div>
      </div>
    </div>
  </header>
</template>

<script>
export default {
    data() {
        return {
            keyWord : '',
            placeArray : []
        }
    },
    methods: {
        searchBox : function(){

            this.placeArray = [];

            let places = new kakao.maps.services.Places();

            let callback = (result, status) => {
                if (status === kakao.maps.services.Status.OK) {
                    this.placeArray = this.placeArray.concat(result);
                }
            };
            places.keywordSearch(this.keyWord, callback);
        },
        setLocation : function(item){
            let mapContainer = document.getElementById('kakaoMap'), // 지도를 표시할 div 
            mapOption = { 
                center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
                level: 3 // 지도의 확대 레벨
            };
            var map = new kakao.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

            var moveLatLon = new kakao.maps.LatLng(item.y, item.x);
            // 지도 중심을 이동 시킵니다
            map.setCenter(moveLatLon);
        }
    },
}
</script>

<style>

.dropdown-menu {
  display: block;
  width: auto;
  margin: 4rem auto;
}

.form-control-dark {
  background-color: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .15);
}

#dropdownFilter {
    position: relative;
    top: -55px;
    left: 40px;
}

.small {
    font-size: 11px;
    margin-left: 17px;
}
</style>
728x90
반응형