[Vue.js] Kakao 지도 구현 01 - 설정 및 Level, Center 변경
Vue.js 프로젝트에서 Kakao 지도를 설정하고 중심 좌표와 Zoom Level을 변경하는 코드를 구현합니다.
[Vue.js] Kakao 지도 구현 01 - 설정 및 Level, Center 변경
아래와 같은 Vue.js 의 기능들을 주로 사용합니다.
- KakaoMap.vue 파일 생성 - 지도를 렌더링하는 독립적인 컴포넌트를 작성합니다.
- @click - zoomIn, zoomOut 기능, 항구 클릭으로 지도 중심 좌표 이동
- props - 지도 옵션을
KakaoMap.vue
파일에 전달함
Source Code
총 4개의 파일
- App.vue - 애플리케이션 루트 컴포넌트
- KakaoMap.vue - 카카오 지도 컴포넌트
- api.js - 백엔드 서버에서 데이터를 가져오는 모듈. 실제 서버가 없으므로 몇개의 샘플 데이터를 모듈 안에 지정한 후 사용합니다.
- index.html - kakao 지도 관련 라이브러리 로드, google font icon 스타일시트를 로드함
프로젝트 구조
프로젝트구조[ROOT]
+- public
| +- index.html (+)
+- src
+- components/map
| +- KakaoMap.vue (+)
|
+- service
| +- api.js (+)
|
+- App.vue (+)
+- main.js
src/App.vue
- 애플리케이션 루트 컴포넌트
- 지도 컨트롤 기능 + KakaoMap.vue 를 사용
src/App.vue<template>
<div>
<h3>kakao map demo(center, level)</h3>
<div class="controll">
<button @click="zoom(-1)">
<span class="material-icons"> zoom_in </span>
</button>
<button @click="zoom(1)">
<span class="material-icons"> zoom_out </span>
</button>
</div>
<div class="map-area">
<div class="harbors">
<div
class="harbor"
v-for="hbr in harbors"
:key="hbr.seq"
@click="showOnMap(hbr)"
>
<h4>{{ hbr.place }}</h4>
</div>
</div>
<KakaoMap class="kmap" :options="mapOption" />
</div>
<!-- <div class="kmap" ref="map"></div> -->
</div>
</template>
<script>
import KakaoMap from "./components/map/KakaoMap.vue";
import api from "./service/api";
export default {
components: {
KakaoMap,
},
data() {
return {
mapOption: {
center: {
lat: 33.450701,
lng: 126.570667,
},
level: 8,
},
harbors: [], // empty
};
},
mounted() {
api.harbor.all((res) => {
console.log("[항구목록]", res.harbors);
this.harbors = res.harbors;
});
},
methods: {
zoom(delta) {
// delta : 1 or -1
// console.log("[delta]", delta);
const level = Math.max(3, this.mapOption.level + delta); // min level 3
this.mapOption.level = level;
// console.log(this.mapOption.level);
},
showOnMap(harbor) {
// console.log("[center]", harbor);
this.mapOption.center = {
lat: harbor.lat,
lng: harbor.lng,
};
},
},
};
</script>
<style lang="scss">
button {
border: 1px solid transparent;
padding: 6px;
background-color: #efefefdd;
border-radius: 6px;
&:hover {
background-color: #ddd;
border-color: #ddd;
cursor: pointer;
}
&:active {
background-color: #aaa;
border-color: #aaa;
}
}
.map-area {
display: flex;
.harbors {
.harbor {
padding: 10px;
border: 1px solid transparent;
&:hover {
background-color: aliceblue;
border-color: #6a9dff;
cursor: pointer;
}
&:active {
background-color: rgb(166, 197, 224);
border-color: #4471c5;
}
h4 {
margin: 0;
}
}
}
.kmap {
flex: 1 1 auto;
}
}
</style>
src/components/map/KakaoMap.vue
- kakao 지도 렌더링용 컴포넌트
- 재사용을 위해 별도의 컴포넌트로 분리함
src/components/map/KakaoMap.vue<template>
<div ref="map"></div>
</template>
<script>
let kakao = window.kakao;
export default {
props: ["options"],
data() {
return {
mapInstance: null,
};
},
mounted() {
kakao = kakao || window.kakao;
console.log(this.$refs.map); // should be not null
var container = this.$refs.map;
const { center, level } = this.options;
this.mapInstance = new kakao.maps.Map(container, {
center: new kakao.maps.LatLng(center.lat, center.lng),
level,
});
// console.log(this.mapInstance);
},
watch: {
"options.level"(cur, prev) {
console.log(`[LEVEL CHANGED] ${prev} => ${cur}`); // for testing
this.mapInstance.setLevel(cur);
},
"options.center"(cur) {
// console.log("[NEW CENTER]", cur.lat, cur.lng); // for test
this.mapInstance.setCenter(new kakao.maps.LatLng(cur.lat, cur.lng));
},
},
};
</script>
<style>
.kmap {
height: 600px;
}
</style>
src/service/api.js
- 백엔드 서버와의 통신을 담당함
- 서버가 없으므로 몇개의 항구 데이터를 샘플로 사용합니다.
src/service/api.jsconst api = {
harbor: {
all(callback) {
// 서버가 없으므로 가짜 데이터를 사용함
const harbors = [
{
seq: 398,
place: "제주항 국제 여객 터미널",
lat: 33.52456237850086,
lng: 126.54371888191963,
},
{
seq: 399,
place: "통영항",
lat: 34.83952733985843,
lng: 128.42015935198992,
},
{
seq: 400,
place: "부산 국제 크루즈 터미널",
lat: 35.07980714092641,
lng: 129.0798233676466,
},
{
seq: 401,
place: "여수 연안 여객 터미널",
lat: 34.73912218990838,
lng: 127.7326117746759,
},
{
seq: 402,
place: "목포 연안 여객 터미널",
lat: 34.78242103832617,
lng: 126.38379614665682,
},
{
seq: 403,
place: "군산항 연안 여객 터미널",
lat: 35.97769454696543,
lng: 126.63282769595156,
},
{
seq: 404,
place: "인천항 연안 여객 터미널",
lat: 37.45340487975725,
lng: 126.59951650605112,
},
];
callback({ success: true, harbors });
},
},
};
export default api;
public/index.html
- kakao 지도 라이브러리를 include 함
- google font icon 스타일을 include 함
public/index.html<!DOCTYPE html>
<html lang="">
<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" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey=e157567be3a5d1b3d0d3f47e1f7a5e6a"
></script>
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
상세 구현에 대한 설명은 아래 문서에서 다룹니다.
0. 목록
- 지도 설정 및 테스트 - 지도 사용을 위한 설정, 올바로 작동하는지 테스트 코드 작성
- KakaoMap.vue 컴포넌트 생성 - 별도의 지도 렌더링용 컴포넌트를 준비
- Zoom 변경 버튼 준비 - zoom 변경 버튼 디자인
- Zoom Level 변경 기능 - 지도 확대/축소 기능 구현
- 지도 중심 변경 - 클릭한 항구로 지도 중심 이동