참고
https://www.youtube.com/watch?v=FHXnPSM6rHk
https://apis.map.kakao.com/web/documentation/#Map_setCenter
지난 시간에 경로 삭제 및 생성 중이던 경로 작업을 취소하는 구현이다.
새로운 경로
버튼을 눌러 지도에 경로를 추가할 수 있을 때 현재는 해제
버튼만 존재하는데,
작업 중간에 취소하기 위해 해제
버튼을 완료
버튼으로, 그리고 취소
버튼을 추가해준다.
//App.vue
<div class="map-wrapper" ref="kakaomap">
<div class="map-controll" v-if="activeSegment">
<button class="btn-commit-seg" @click="commitPath()">완료</button
><!-- 경로 종료할 때 버튼 -->
<button @click="cancelPath()">취소</button>
</div>
</div>
취소
버튼 클릭 이벤트 핸들러인 cancelPath()
메서드는 현재 활성화된 activeSegment 는 dipsose
되게하고, 완료
와 취소
버튼이 사라지게 한다. segment 의 dipsose
메서드는 바로 설명하겠다.
//App.vue
cancelPath() {
this.activeSegment.dispose(); //경로 제거용
this.activeSegment = null; //버튼 사라지게 함
},
dispose
메서드는 경로를 제거하는 역할을 한다. 일단 커서 복귀를 위해 함수 내에서 commit
메서드를 실행하는데, 이때 추가된 코드로 존재하는 currentSegment 는 null 로 초기화시킴으로써 아예 segment 를 없앨 수 있다.
//segment.js
commit() {
//경로 작성 완료
this.done = true;
//리스너 해제해야함
window.kakao.maps.event.removeListener(
this.map,
"click",
this.listeners.click
);
//커서를 가져오는 API가 없기에
this.map.setCursor(DEFAULT_KAKAOMAP_CURSOR);
console.log("해제 완료");
//+추가
if (this.currentSegment) {
this.currentSegment = null;
}
}
dispose() {
console.log("경로 제거");
this.commit(); //커서 복귀
this.poly.setMap(null);
}
그리고 지도로 그려놓았던 Polyline 즉 경로들을 지도에서 제거하기 위해서 setMap(null)
메서드를 실행한다.
이미 생성된 경로는 목록으로 렌더링이 되게 구현해놓았다.
그렇다면 생성된 경로 삭제를 위해서는 목록 옆에 각각의 항목에 삭제
버튼이 존재해야한다.
<div class="list-of-seg">
<div class="segment" v-for="(seg, index) in segments" :key="index">
<h4>{{ seg.name }}</h4>
<button @click="deletePath(seg, index)">삭제</button>
</div>
</div>
v-for 바인딩을 통해 존재하는 경로들의 배열인 segments 들을 반복문을 돌며 seg.name 과 삭제
버튼이 렌더링된다. 삭제
버튼 클릭 이벤트 핸들러는 deletePath(seg,index)
이다.
/**
* @param seg 지울 세그먼트(경로)
* @param index 인덱스값
*/
deletePath(seg, index) {
this.segments.splice(index, 1); //1개만 삭제
seg.dispose();
},
deletePath
메서드의 매개변수인 seg 는 생성된 경로를 의미하고, index 는 segments 배열들 중 해당 경로가 어떤 인덱스인지 가리킨다. 이 메서드는 이미 생성된 경로를 삭제하는 것이기 때문에 단지 segements 배열에서 해당 인덱스 하나를 삭제 시켜주면 되기에 splice 배열 메서드를 사용하게 제거한다. 그리고 또한 dipose
시켜줌으로써 아예 세그먼트에서 삭제시킨다.
<template>
<div id="app">
<div class="path-list">
<h3>경로</h3>
<button @click="processNewPath()">새로운 경로</button>
<div class="list-of-seg">
<div class="segment" v-for="(seg, index) in segments" :key="index">
<h4>{{ seg.name }}</h4>
<button @click="deletePath(seg, index)">삭제</button>
</div>
</div>
</div>
<div class="map-wrapper" ref="kakaomap">
<div class="map-controll" v-if="activeSegment">
<button class="btn-commit-seg" @click="commitPath()">완료</button
><!-- 경로 종료할 때 버튼 -->
<button @click="cancelPath()">취소</button>
</div>
</div>
</div>
</template>
<script>
import startSegment from "./segment";
export default {
name: "App",
components: {
// KakaoMap,
},
data() {
return {
mapInstance: null,
activeSegment: null,
segments: [], //list of pathes
};
},
mounted() {
//init map here
var container = this.$refs.kakaomap;
var options = {
center: new window.kakao.maps.LatLng(33.450701, 126.570667),
level: 3,
};
//지도 생성 및 객체 리턴
this.mapInstance = new window.kakao.maps.Map(container, options);
},
methods: {
processNewPath() {
console.log("[new path] start");
//지도 객체 전달
this.activeSegment = startSegment(this.mapInstance);
},
commitPath() {
this.activeSegment.commit();
this.segments.push(this.activeSegment);
this.activeSegment = null; //버튼 사라지게 함
},
cancelPath() {
this.activeSegment.dispose(); //경로 제거용
this.activeSegment = null; //버튼 사라지게 함
},
/**
* @param seg 지울 세그먼트(경로)
* @param index 인덱스값
*/
deletePath(seg, index) {
this.segments.splice(index, 1); //1개만 삭제
seg.dispose();
},
},
};
</script>
<style lang="scss">
html,
body {
height: 100%;
margin: 0;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
.path-list {
width: 240px;
}
.list-of-seg {
.segment {
display: flex;
padding-right: 8px;
margin: 4px 0px;
h4 {
margin: 0;
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 4px 8px;
}
button {
white-space: nowrap;
padding: 4px 8px;
border: 1px solid #ccc;
background-color: white;
border-radius: 4px;
color: #777;
&:hover {
background-color: #efefef;
color: #333;
cursor: pointer;
}
&:active {
background-color: #ddd;
color: #000;
}
}
}
}
.map-wrapper {
flex: 1 1 auto;
.map-controll {
position: absolute;
top: 5px;
left: 5px;
z-index: 1000;
}
}
}
</style>
const DEFAULT_KAKAOMAP_CURSOR =
"url("http://t1.daumcdn.net/mapjsapi/images/2x/cursor/openhand.cur.ico") 7 5, url("http://t1.daumcdn.net/mapjsapi/images/2x/cursor/openhand.cur.ico"), default";
/*
* 경로를 나타내는 클래스
*/
class Segment {
/**
*
* @param {kakao.maps.Map} mapInstance 지도 인스턴스
* @param {object} props 경로 메타 정보들(이름 거리 등..)
*/
constructor(mapInstance, props) {
this.map = mapInstance;
this.done = false;
this.points = []; //list for LatLng
this.poly = new window.kakao.maps.Polyline({
map: this.map,
path: [],
strokeWeight: 2,
strokeColor: "#FF00FF",
strokeOpacity: 0.8,
strokeStyle: "solid", //실선
});
this.listeners = {};
this.props = props || {};
this.installListners();
}
get name() {
return this.props.name || "NO NAME";
}
installListners() {
//클릭 리스너 등록
const adder = (e) => {
console.log("[pos]", e.latLng);
this.points.push(e.latLng); //각 점을 등록
this.render();
};
// this.listeners.click = { click: null };
this.listeners.click = adder;
window.kakao.maps.event.addListener(this.map, "click", adder);
this.map.setCursor("crosshair");
}
render() {
//경로를 그림
this.poly.setPath(this.points);
}
commit() {
//경로 작성 완료
this.done = true;
//리스너 해제해야함
window.kakao.maps.event.removeListener(
this.map,
"click",
this.listeners.click
);
//커서를 가져오는 API가 없기에
this.map.setCursor(DEFAULT_KAKAOMAP_CURSOR);
console.log("해제 완료");
if (this.currentSegment) {
this.currentSegment = null;
}
}
dispose() {
console.log("경로 제거");
this.commit(); //커서 복귀
this.poly.setMap(null);
}
}
let currentSegment;
const startSegment = (mapInstance) => {
currentSegment = new Segment(mapInstance);
return currentSegment;
};
export default startSegment;
지난 polyline 을 배우고 segment 생성자를 시작한 터라 오늘 배운 삭제 부분은 쉽게 느껴졌다. dispose 메서드를 통해 커서 복귀를 시키고 생성된 경로 폴리라인은 setMap(null) 을 통해 제거되는 것과 세그먼트 객체인 currentSegment 또한 null로 만들어주면서 지도에서 아예 제거되는 것을 알게되었다. 경로 생성, 삭제를 알아보았으니 다음은 편집이다.