본문 바로가기
Develop/JPA

전기차 충전소 API (6)

by ys2ys2 2024. 11. 14.

 

마지막 작업 내용 : 팝업창에 나온 전기차 충전소 위치를 충전소 길 찾기로 전달해서 도착지점 설정하기

 

오늘 작업 내용 : ✅리스트 불러올 때 지도에 마커 전부 표시, 해당 마커 클릭시 팝업창 뜨게하기

 


 

오늘 오전엔 팀원들 작업 내용 다 합치고 다시 배포하느라 한게 많이 없다!

 

 

✅ 리스트 불러올 때 지도에 마커 전부 표시, 해당 마커 클릭시 팝업창 뜨게하기

 

기존에 사용하던 코드에서 약간 수정했다.

// 마지막으로 생성된 마커를 추적할 전역 변수
let lastMarker = null;

// displayResults 함수에서 전역 매핑 객체 사용
function displayResults(items) {
    const resultList = document.querySelector(".searchlist ul");
    resultList.innerHTML = ""; // 기존 리스트 초기화

    const stationNameCount = {}; // 충전소명 중복 여부 확인할 객체

    for (let i = 0; i < items.length; i++) {
        const statNm = items[i].getElementsByTagName("statNm")[0].textContent;  // 충전소명
        const busiNm = items[i].getElementsByTagName("busiNm")[0].textContent;	// 운영기관명
        const busiCall = items[i].getElementsByTagName("busiCall")[0].textContent;	//운영기관 연락처
        const addr = items[i].getElementsByTagName("addr")[0].textContent;      // 주소
        const addrDetail = items[i].getElementsByTagName("addrDetail")[0].textContent; //상세주소
        const useTime = items[i].getElementsByTagName("useTime")[0].textContent; // 이용 가능 시간
        const output = items[i].getElementsByTagName("output")[0].textContent;   // 충전 용량
        const type = items[i].getElementsByTagName("chgerType")[0].textContent;  // 충전기 타입
        const stat = items[i].getElementsByTagName("stat")[0].textContent;       // 충전기 상태
        const statUpdDt = items[i].getElementsByTagName("statUpdDt")[0].textContent; // 상태갱신일시
        const lastTsdt = items[i].getElementsByTagName("lastTsdt")[0].textContent; // 마지막 충전시작일시
        const lastTedt = items[i].getElementsByTagName("lastTedt")[0].textContent; // 마지막 충전종료일시
        const nowTsdt = items[i].getElementsByTagName("nowTsdt")[0].textContent; // 충전중 시작일시
        const note = items[i].getElementsByTagName("note")[0].textContent;	// 충전소 안내
        const limitDetail = items[i].getElementsByTagName("limitDetail")[0]?.textContent || ""; // 제한 사항
        const lat = parseFloat(items[i].getElementsByTagName("lat")[0].textContent); // 위도
        const lng = parseFloat(items[i].getElementsByTagName("lng")[0].textContent); // 경도

        // 타입과 상태 텍스트 변환
        const typeText = chargerTypeMap[type] || "알 수 없는 타입";
        const statusInfo = chargerStatusMap[stat] || { text: "알 수 없는 상태", class: "status-unknown" };

        // 중복된 충전소명에 번호 붙이기
        if (stationNameCount[statNm]) {
            stationNameCount[statNm] += 1; // 중복 카운트 증가
        } else {
            stationNameCount[statNm] = 1; // 처음 등장하는 충전소명
        }

        const displayName = stationNameCount[statNm] > 1 ? ${statNm} (${stationNameCount[statNm]}) : statNm;

        const listItem = document.createElement("li");
        listItem.className = "search-item";
        listItem.dataset.lat = lat;
        listItem.dataset.lng = lng;

        listItem.innerHTML = 
            <div class="info">
                <h3>${displayName}</h3>
                <p>${addr}</p>
                <div class="status">
                    <span class="stat ${statusInfo.class}">${statusInfo.text}</span>
                    <span class="fast">⚡ ${output}kW</span>
                    <span class="type">타입: ${typeText}</span>
                </div>
                <p>이용시간: ${useTime}</p>
                <p>이용자 제한사항: ${limitDetail ? limitDetail : "제한 없음"}</p>
            </div>
        ;

        listItem.addEventListener("click", function () {
            const stationData = {
                name: displayName,             // 충전소명 (중복 구분 포함)
                operator: busiNm,              // 운영기관명
                contact: busiCall,             // 운영기관 연락처
                address: addr,                 // 주소
                addressDetail: addrDetail,     // 상세주소
                useTime: useTime,              // 이용 가능 시간
                output: output,                // 충전 용량
                type: type,                    // 충전기 타입 코드
                status: stat,                  // 충전기 상태 코드
                statusUpdateDate: statUpdDt,   // 상태갱신일시
                lastStart: lastTsdt,           // 마지막 충전 시작 일시
                lastEnd: lastTedt,             // 마지막 충전 종료 일시
                chargingStart: nowTsdt,        // 현재 충전 시작 일시
                note: note,                    // 충전소 안내
                limitDetail: limitDetail,      // 이용 제한 사항
                lat: lat,                      // 위도
                lng: lng                       // 경도
            };


            showStationInfoPopup(stationData);

            // 기존 마커가 있다면 지도에서 제거
            if (lastMarker) {
                lastMarker.setMap(null);
            }

            // 새로운 마커 추가 및 lastMarker에 저장
            const selectedLocation = new kakao.maps.LatLng(lat, lng);
            map.setCenter(selectedLocation);

            lastMarker = new kakao.maps.Marker({
                position: selectedLocation,
                map: map
            });
        });

        resultList.appendChild(listItem);
    }
}

 

 

원래는 검색 후 리스트로 반환된 상태에서 리스트를 누르면 맵에 마커가 찍히면서 그 부분으로 화면이 이동되게 했었는데.

 

사용자 편의성을 위해 검색한 지역의 리스트를 받고 그 리스트에 해당하는 충전소의 마커를 전부 지도에 표시했다.

 

마커 클릭 시 팝업 열리는 기능도 그대로 가져가기!

 

 

// 마지막으로 생성된 마커를 추적할 전역 변수
let lastMarker = null;
let markers = []; // 지도에 표시될 마커를 관리할 배열

// displayResults 함수에서 전역 매핑 객체 사용
function displayResults(items) {
    const resultList = document.querySelector(".searchlist ul");
    resultList.innerHTML = ""; // 기존 리스트 초기화

    const stationNameCount = {}; // 충전소명 중복 여부 확인할 객체

    // 기존 마커 제거
    markers.forEach(marker => marker.setMap(null));
    markers = []; // 마커 배열 초기화

    // 지도 범위를 설정할 객체 생성
    const bounds = new kakao.maps.LatLngBounds();

    for (let i = 0; i < items.length; i++) {
        const statNm = items[i].getElementsByTagName("statNm")[0].textContent;  // 충전소명
        const busiNm = items[i].getElementsByTagName("busiNm")[0].textContent;  // 운영기관명
        const busiCall = items[i].getElementsByTagName("busiCall")[0].textContent;  //운영기관 연락처
        const addr = items[i].getElementsByTagName("addr")[0].textContent;      // 주소
        const addrDetail = items[i].getElementsByTagName("addrDetail")[0].textContent; // 상세주소
        const useTime = items[i].getElementsByTagName("useTime")[0].textContent; // 이용 가능 시간
        const output = items[i].getElementsByTagName("output")[0].textContent;   // 충전 용량
        const type = items[i].getElementsByTagName("chgerType")[0].textContent;  // 충전기 타입
        const stat = items[i].getElementsByTagName("stat")[0].textContent;       // 충전기 상태
        const statUpdDt = items[i].getElementsByTagName("statUpdDt")[0].textContent; // 상태갱신일시
        const lastTsdt = items[i].getElementsByTagName("lastTsdt")[0].textContent; // 마지막 충전시작일시
        const lastTedt = items[i].getElementsByTagName("lastTedt")[0].textContent; // 마지막 충전종료일시
        const nowTsdt = items[i].getElementsByTagName("nowTsdt")[0].textContent; // 충전중 시작일시
        const note = items[i].getElementsByTagName("note")[0].textContent;  // 충전소 안내
        const limitDetail = items[i].getElementsByTagName("limitDetail")[0]?.textContent || ""; // 제한 사항
        const lat = parseFloat(items[i].getElementsByTagName("lat")[0].textContent); // 위도
        const lng = parseFloat(items[i].getElementsByTagName("lng")[0].textContent); // 경도

        // 타입과 상태 텍스트 변환
        const typeText = chargerTypeMap[type] || "알 수 없는 타입";
        const statusInfo = chargerStatusMap[stat] || { text: "알 수 없는 상태", class: "status-unknown" };

        // 중복된 충전소명에 번호 붙이기
        if (stationNameCount[statNm]) {
            stationNameCount[statNm] += 1; // 중복 카운트 증가
        } else {
            stationNameCount[statNm] = 1; // 처음 등장하는 충전소명
        }

        const displayName = stationNameCount[statNm] > 1 ? `${statNm} (${stationNameCount[statNm]})` : statNm;

        const listItem = document.createElement("li");
        listItem.className = "search-item";
        listItem.dataset.lat = lat;
        listItem.dataset.lng = lng;

        listItem.innerHTML = `
            <div class="info">
                <h3>${displayName}</h3>
                <p>${addr}</p>
                <div class="status">
                    <span class="stat ${statusInfo.class}">${statusInfo.text}</span>
                    <span class="fast">⚡ ${output}kW</span>
                    <span class="type">타입: ${typeText}</span>
                </div>
                <p>이용시간: ${useTime}</p>
                <p>이용자 제한사항: ${limitDetail ? limitDetail : "제한 없음"}</p>
            </div>
        `;

        listItem.addEventListener("click", function () {
            const stationData = {
                name: displayName,             // 충전소명 (중복 구분 포함)
                operator: busiNm,              // 운영기관명
                contact: busiCall,             // 운영기관 연락처
                address: addr,                 // 주소
                addressDetail: addrDetail,     // 상세주소
                useTime: useTime,              // 이용 가능 시간
                output: output,                // 충전 용량
                type: type,                    // 충전기 타입 코드
                status: stat,                  // 충전기 상태 코드
                statusUpdateDate: statUpdDt,   // 상태갱신일시
                lastStart: lastTsdt,           // 마지막 충전 시작 일시
                lastEnd: lastTedt,             // 마지막 충전 종료 일시
                chargingStart: nowTsdt,        // 현재 충전 시작 일시
                note: note,                    // 충전소 안내
                limitDetail: limitDetail,      // 이용 제한 사항
                lat: lat,                      // 위도
                lng: lng                       // 경도
            };

            showStationInfoPopup(stationData);

            // 기존 마커가 있다면 지도에서 제거
            if (lastMarker) {
                lastMarker.setMap(null);
            }

            // 새로운 마커 추가 및 lastMarker에 저장
            const selectedLocation = new kakao.maps.LatLng(lat, lng);
            map.setCenter(selectedLocation);

            lastMarker = new kakao.maps.Marker({
                position: selectedLocation,
                map: map
            });
        });

        resultList.appendChild(listItem);

        // 지도에 마커 추가
        const markerPosition = new kakao.maps.LatLng(lat, lng);
        const marker = new kakao.maps.Marker({
            position: markerPosition,
            map: map
        });

        // 마커 클릭 시 팝업 표시 이벤트 추가
        kakao.maps.event.addListener(marker, 'click', function() {
            showStationInfoPopup({
                name: displayName,             
                operator: busiNm,              
                contact: busiCall,             
                address: addr,                 
                addressDetail: addrDetail,     
                useTime: useTime,              
                output: output,                
                type: type,                    
                status: stat,                  
                statusUpdateDate: statUpdDt,   
                lat: lat,                      
                lng: lng                       
            });
        });

        // 마커 배열에 저장
        markers.push(marker);

        // 지도 범위에 마커 위치 추가
        bounds.extend(markerPosition);
    }

    // 모든 마커가 보이도록 지도 범위 설정
    map.setBounds(bounds);
}

 

 

검색 시 결과

 

 

수정 내용 : 기존 let lastMarker = null;로 하나만 체크하던 마커에서

전체 마커 관리할 let markers = []; 배열 추가.

let lastMarker = null;
let markers = [];	// 추가

 

마커 초기화 추가

markers.forEach(marker => marker.setMap(null));
markers = []; // 마커 배열 초기화

 

지도 범위 설정하기

const bounds = new kakao.maps.LatLngBounds();

 

모든 마커 보이게 하게

map.setBounds(bounds);

 

전에 lastMarker로 관리하던 마커를 새 검색마다 기존 마커 제거 후 새 마커 표시하게 변경.

페이지네이션으로 다음 페이지 넘어갈때마다 마커가 찍히게 설정

(한번에 너무 많이 가져오니까 지저분해보였다는..)

const markerPosition = new kakao.maps.LatLng(lat, lng);
const marker = new kakao.maps.Marker({
    position: markerPosition,
    map: map
});

markers.push(marker);

 

 

페이지네이션도 잘 작동하는거 확인하고

 

눌렀을때 팝업창 확인도 다시 한번 해주고, 길 찾기 눌렀을때 마커 사라지면서 도착지만 나오는지도 체크하기

 

 

 

잘 된다! 이제 다른거 하러 갑니다..

내일은 진짜 길찾기 스타일링 하겠습니다...