[Vue.js] Implementing Kakao Maps 02 - Creating a Marker click listener
add the marker creation and click listener code to the map functionality (change level, center) we created in the previous article.
[Vue.js] Kakao Map Implementation 02 - Create Marker click listener
Source Code
- MarkerHandler.js - Class for marker creation and management functions (added)
- App.vue - Application Root Component (Modified)
The rest of the files are unmodified
project Structure
Project Structure[ROOT]
+- public
| +- index.html
+- src
+- components/map
| +- KakaoMap.vue
| +- marker-handler.js (+)
|Β
+- service
| +- api.js
|Β
+- App.vue (E)
+- main.js
src/components/map/marker-handler.js
class responsible for creating and managing markers. currently we only implement marker creation, but functionality such as deleting or temporarily hiding markers will be added here.
src/components/map/marker-handler.jsconst kakao = window.kakao;
class MarkerHandler {
constructor(vueKakaoMap, options) {
this.vueMap = vueKakaoMap;
this.options = options;
}
add(userData, fnConv) {
userData.forEach((data) => {
const option = fnConv(data); // this is harbor
const markerInstance = new kakao.maps.Marker({
map: this.vueMap.mapInstance,
position: new kakao.maps.LatLng(option.lat, option.lng),
});
markerInstance.$$ = {
data,
};
if (this.options.markerClicked) {
kakao.maps.event.addListener(markerInstance, "click", () => {
this.options.markerClicked(markerInstance.$$.data);
});
}
});
}
}
export default MarkerHandler;
src/App.vue
use an instance of MarkerHandler
.
src/App.vue<template> <div>
<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_in </span> </button>
<span class="material-icons"> zoom_out </span>
</button>
</div>
<div class="map-area"> <div class="harbors">
<div class="harbors">
<div
class="harbor"
v-for="hbr in harbors"
:key="hbr.seq"
@click="showOnMap(hbr)"
:class="{ active: hbr === activeHarbor }"
>
<h4>{{ hbr.place }}</h4>
</div>
</div>
<!-- KakaoMap implementor reference is required -->
<KakaoMap ref="kmap" class="kmap" :options="mapOption" />
</div>
</div>
</template>
<script> <script>
import KakaoMap from "./components/map/KakaoMap.vue";
import api from "./service/api";
import MarkerHandler from "./components/map/marker-handler";
export default {
components: {
KakaoMap,
},
data() {
return {
mapOption: {
center: {
lat: 33.450701,
lng: 126.570667,
},
level: 8,
},
harbors: [],
markers: null, // (+) instance of MarkerHandler
activeHarbor: null, // (+) reference to the currently selected harbar
};
},
mounted() {
const vueKakaoMap = this.$refs.kmap;
this.markers = new MarkerHandler(vueKakaoMap, {
markerClicked: (harbor) => {
console.log("[clicked ]", harbor);
// this.activeHarbor = harbor;
this.showOnMap(harbor);
},
});
api.harbor.all((res) => {
console.log("[List of harbors]", res.harbors);
this.harbors = res.harbors;
// create markers
this.markers.add(this.harbors, (harbor) => {
return { lat: harbor.lat, lng: harbor.lng };
});
});
},
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) {
this.activeHarbor = 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;
}
&.active {
background-color: rgb(253, 229, 150);
border-color: rgb(211, 173, 3);
}
h4 {
margin: 0;
}
}
}
.kmap {
flex: 1 1 auto;
}
}
</style>