| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- <template>
- <div class="map--google">
- <div id="ran_detail_map" style="height: 100%;"></div>
- </div>
- </template>
- <script setup>
- /***********************
- * import
- ************************/
- import { useI18n } from "vue-i18n";
- import useUtil from "@/composables/useUtil";
- /***********************
- * plugins inject
- ************************/
- const { $toast, $log, $dayjs, $eventBus } = useNuxtApp()
- // props
- const props = defineProps({
- centerPosition: Object,
- currNeInfo: Object,
- neList: Array
- })
- // 참조가능 데이터 설정
- defineExpose({})
- // 발신 이벤트 선언
- const emit = defineEmits([""])
- const i18n = useI18n()
-
- /***********************
- * data & created
- ************************/
- const map = ref(null) // 카카오 맵 객체
- const markers = ref([])
- const neArr = ref([])
- neArr.value = _cloneDeep(props.neList)
- onMounted(() => {
- fnInit()
- })
-
- watch(() => props.neList, (newV, oldV) => {
- neArr.value = _cloneDeep(props.neList)
- fnDrawMarker()
- },{ deep: true })
-
- watch(() => props.currNeInfo, (newV, oldV) => {
- neArr.value.forEach((item, idx) => {
- if(item.neName === props.currNeInfo.neName) {
- let position = new kakao.maps.LatLng(item.neLocLatitude, item.neLocLongitude)
- map.value.panTo(position)
- setTimeout(() => {
- // 정보 레이어 오픈
- fnGetInfo(markers.value[idx].data, idx)
- }, 1);
- }
- })
- },{ deep: true })
- /***********************
- * Methods
- ************************/
- /**
- * 초기 실행
- */
- function fnInit(){
- nextTick().then(() => {
- if (window.kakao && window.kakao.maps) {
- loadMap()
- } else {
- loadScript()
- }
- })
- }
- /**
- * kakao 스크립트 로드
- */
- function loadScript() {
- const script = document.createElement('script')
- script.async = true
- script.onload = () => {
- window.kakao.maps.load(loadMap)
- }
- script.src = `//dapi.kakao.com/v2/maps/sdk.js?autoload=false&libraries=services,clusterer,drawing&appkey=${import.meta.env.VITE_APP_KAKAO_APP_KEY}`
- document.head.appendChild(script)
- }
- /**
- * kakao 지도 로드
- */
- async function loadMap() {
- const mapContainer = document.getElementById('ran_detail_map')
- let mapOption = {
- center: new kakao.maps.LatLng(props.centerPosition.lat, props.centerPosition.lng), // 지도의 중심좌표
- level: 3, // 지도의 확대 레벨
- }
- map.value = new kakao.maps.Map(mapContainer, mapOption)
- let zoomControl = new kakao.maps.ZoomControl()
- // map.value.addControl(zoomControl, kakao.maps.ControlPosition.BOTTOMRIGHT)
- // fnSetEventListener() // 지도 이벤트 등록
- fnDrawMarker()
- }
- function fnClearMarker(){
- markers.value.forEach(marker => marker.markers.setMap(null));
- fnCloseMarkerInfoOverlay()
- markers.value = []
- }
- /**
- * 마커 생성 데이터 세팅
- */
- function fnDrawMarker(){
- fnClearMarker()
- neArr.value.map((item, index) => {
- let position = new kakao.maps.LatLng(item.neLocLatitude, item.neLocLongitude)
- let markerObj = {
- overlay: null,
- markers: null,
- data: item,
- click: false,
- position: position
- }
- markers.value.push(markerObj)
- markers.value[index].markers = fnCreateMarker(position, index)
- if(index == 0) {
- map.value.panTo(position)
- }
- })
- }
- import { filename } from 'pathe/utils'
- // 이미지 가져오기 (vite문법)
- const glob = import.meta.glob('~/assets/img/ico_*.{png,svg}', { eager: true })
- const getImages = Object.fromEntries(
- Object.entries(glob).map(([key, value]) => [filename(key), value.default])
- )
- // NE 수 > 이벤트 단계 클래스
- const getNeEventCls = computed(() => {
- return (obj) => {
- let eventCls = ''
- if(!_isEmpty(obj)) {
- if(obj.minCnt > 0) eventCls = 'black'
- if(obj.majCnt > 0) eventCls = 'blue'
- if(obj.criCnt > 0) eventCls = 'red'
- }
- return eventCls
- }
- })
- // 마커 이미지 파일명 세팅
- function fnGetMarkerImage(index){
- let color = getNeEventCls.value(props.neList[index])
- if(color == 'red') return 'ico_red_pin'
- else if(color == 'blue') return 'ico_blue_pin'
- else if(color == 'black') return 'ico_black_pin'
- else return 'ico_gray_pin'
- }
- /**
- * 마커 생성
- */
- function fnCreateMarker(position, index) {
- // 마커 이미지 설정
- const markerImageSrc = getImages[fnGetMarkerImage(index)] // assets 폴더의 이미지 경로
- const markerImageSize = new kakao.maps.Size(40, 40); // 마커 이미지 사이즈
- const markerImage = new kakao.maps.MarkerImage(markerImageSrc, markerImageSize);
- let markerOption = {
- map: map.value, // 마커를 표시할 지도
- position: position, // 마커의 위치
- clickable: true,
- image: markerImage,
- zIndex: 1,
- }
- let marker = new kakao.maps.Marker(markerOption)
- // 마커 클릭 이벤트등록
- kakao.maps.event.addListener(marker,'click', fnClickMarker(index))
- return marker
- }
- /**
- * 마커 클릭
- */
- function fnClickMarker(index) {
- const clickData = markers.value[index].data
- const openInfoWindow = function () {
- // 마커 클릭 > 상태변경 > z-index 및 맵 이동
- fnMarkerClickChk(index)
- fnGetInfo(clickData, index)
- }
- return openInfoWindow
- }
- /**
- * 마커 클릭 이벤트
- */
- function fnMarkerClickChk(index) {
- fnSetUnClickMarker()
- markers.value[index].click = true
- markers.value[index].markers.setZIndex(3)
- let moveLatLng = markers.value[index].position
- map.value.panTo(moveLatLng)
- }
- /**
- * 마커 클릭 상태 해제 및 z인덱스 초기화
- */
- function fnSetUnClickMarker() {
- markers.value.forEach((item) => {
- item.click = false
- item.markers.setZIndex(2)
- })
- }
- function fnGetInfo(data, index){
- // 열려 있던 오버레이 닫기
- fnCloseMarkerInfoOverlay()
- // 오버레이 생성
- markers.value[index].overlay = fnCreateCustomOverlay(data, index)
- // 오버레이 z-index 설정
- markers.value[index].overlay.setZIndex(999)
- // 오버레이 열기
- markers.value[index].overlay.setMap(map.value)
- // 오버레이 이벤트 등록
- fnCustomOverlayAddEventListener()
- }
- /**
- * 커스텀 오버레이 생성
- */
- function fnCreateCustomOverlay(data, index) {
- // style="top: -10.7rem; right: -6rem;"
- let cpu = JSON.parse(data.cpu)
- let memory = JSON.parse(data.mem)
- let content = `
- <div class="map--pop">
- <div class="titles">
- <h2 style="overflow:hidden; text-overflow:ellipsis;">${data.neName}</h2>
- <v-btn class="custom-btn mini close--pop--btn" id="overlayCloseBtn" />
- </div>
- <ul>
- <li>
- <span class="critical">STATUS</span>
- <span>ACTIVE</span>
- </li>
- <li>
- <span class="major">CPU</span>
- <span>${cpu.AVG_CPU_L}%</span>
- </li>
- <li>
- <span class="minor">MEMORY</span>
- <span>${memory.AVG_MEM_L}%</span>
- </li>
- <li>
- <span>DISK</span>
- <span>${data.disk}</span>
- </li>
- </ul>
- </div>`
- // 커스텀 오버레이 생성
- let customOverlay = new kakao.maps.CustomOverlay({
- position: markers.value[index].position,
- content: content
- })
- return customOverlay
- }
- /**
- * 커스텀 오버레이 이벤트 등록
- */
- function fnCustomOverlayAddEventListener(){
- // 오버레이 닫기 버튼
- const closeBtn = document.querySelector('#overlayCloseBtn')
- closeBtn.addEventListener('click', fnCloseBtnOverlay)
- }
- /**
- * 마커 정보 오버레이 닫기 버튼
- */
- function fnCloseBtnOverlay() {
- fnCloseMarkerInfoOverlay()
- fnSetUnClickMarker()
- }
- /**
- * 모든 마커 정보 오버레이 닫기
- */
- function fnCloseMarkerInfoOverlay() {
- for (var i = 0; i < markers.value.length; i++) {
- if (markers.value[i].overlay) {
- markers.value[i].overlay.setMap(null)
- markers.value[i].overlay = null
- }
- }
- }
- </script>
|