다중 마커 및 오버레이 닫기 관련 문제

안녕하세요 마커에 오버레이 띄우는 작업 중 오버레이 닫기 오류 관련하여 질문 드립니다.

                var markers = []; // 지도에 표시된 마커 객체를 가지고 있을 배열입니다
				var contents = [];
				var overlays = [];
				var mapContainer = document.getElementById('map'), // 지도를 표시할 div  
				mapOption = {
					center : new kakao.maps.LatLng(37.5397629769285, 126.996240829219), // 지도의 중심좌표
					level : 5
				// 지도의 확대 레벨
				};

				var map = new kakao.maps.Map(mapContainer, mapOption); // 지도를 생성합니다

				// 마커를 표시할 위치와 title 객체 배열입니다
				var positions = [
						<%
							ArrayList<ContentDTO> list = (ArrayList<ContentDTO>)request.getAttribute("list");
						
							for(int i = 0; i < list.size(); i++) {
							if(i == list.size()-1) {
						%>
							{
								title : '<%=list.get(i).getName()%>',
								address : '<%=list.get(i).getAddress()%>',
								category : '<%=list.get(i).getCategory()%>',
								latlng : new kakao.maps.LatLng<%=list.get(i).getCoordinate()%>
							}
							
						<%
							} else {
						%>
							{
								title : '<%=list.get(i).getName()%>',
								address : '<%=list.get(i).getAddress()%>',
								category : '<%=list.get(i).getCategory()%>',
								latlng : new kakao.maps.LatLng<%=list.get(i).getCoordinate()%>
							},
						<%
							}
							}
						%>
				];
				    
				for (var i = 0; i < positions.length; i ++) {
					// 마커 이미지의 이미지 주소입니다
					if(positions[i].category == '관광지') var imageSrc = "https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png";
					else if(positions[i].category == '숙박시설') var imageSrc = "https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png";
					else var imageSrc = "https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/markerStar.png";
					
				    // 마커 이미지의 이미지 크기 입니다
				    var imageSize = new kakao.maps.Size(24, 35); 
				    
				    // 마커 이미지를 생성합니다    
				    var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize); 
				    
				    // 마커를 생성합니다
				    var marker = new kakao.maps.Marker({
				        map: map, // 마커를 표시할 지도
				        position: positions[i].latlng, // 마커를 표시할 위치
				        title : positions[i].title, // 마커의 타이틀, 마커에 마우스를 올리면 타이틀이 표시됩니다
				        image : markerImage, // 마커 이미지 
				        clickable: true // 마커를 클릭했을 때 지도의 클릭 이벤트가 발생하지 않도록 설정합니다
				    });
				    markers.push(marker);
				}
				
				for(var i=0; i<positions.length; i++) {
		         	// 마커 위에 커스텀오버레이를 표시합니다
			        // 마커를 중심으로 커스텀 오버레이를 표시하기위해 CSS를 이용해 위치를 설정했습니다
					var overlay = new kakao.maps.CustomOverlay({
		            	map: map,
		            	position: markers[i].getPosition()
		         	});
					overlay.setMap(null);
					
					var content = '<div class="wrap">' + 
		            '    		   <div class="info">' + 
		            '        	   <div class="title">' + positions[i].title + 
		            '              <div class="close" onclick="closeOverlay()" title="닫기"></div>' + 
		            '        	   </div>' + 
		            '        	   <div class="body">' + 
		            '              <div class="img">' +
		            '              <img src="image/contents/hyattseoul1.PNG" width="73" height="70">' +
		            '              </div>' + 
		            '              <div class="desc">' + 
		            '              <div class="ellipsis">' + positions[i].address + '</div>' + 
		            '              </div>' + 
		            '              </div>' + 
		            '    		   </div>' +    
		            '			   </div>';
		            
		            overlay.setContent(content);
					
					// 마커를 클릭했을 때 커스텀 오버레이를 표시합니다
					kakao.maps.event.addListener(markers[i], 'click', function(o) {
						return function() {
							o.setMap(map);
						}
				    }(overlay));
				}
				
				function closeOverlay() {
			        overlay.setMap(null);
			    }
				
				// 배열에 추가된 마커들을 지도에 표시하거나 삭제하는 함수입니다
				function setMarkers(map) {
				    for (var i = 0; i < markers.length; i++) {
				        markers[i].setMap(map);
				    }
				}

				// "마커 보이기" 버튼을 클릭하면 호출되어 배열에 추가된 마커를 지도에 표시하는 함수입니다
				function showMarkers() {
				    setMarkers(map);
				}

				// "마커 감추기" 버튼을 클릭하면 호출되어 배열에 추가된 마커를 지도에서 삭제하는 함수입니다
				function hideMarkers() {
				    setMarkers(null);    
				}

오버레이를 생성하고 content를 추가하는 식으로 코딩을 했는데요
마커 클릭시 해당하는 오버레이가 정상적으로 출력되긴합니다.
다만, 닫기 버튼 클릭시 마지막 오버레이만 닫힙니다.
닫기 버튼에서 closeOverlay() 함수가 있는데 각 마커 클릭시 열리는 오버레이를 closeOverlay() 함수의 파라미터로 넘겨줘야 할거같은데 도무지 방법을 모르겠습니다.
자바스크립트 부분이 약해서 그런지 감이 오질 않네요
고수님들의 답변 부탁드리겠습니다.
(positions 배열에 요소 추가하는 부분에 스크립트릿이 들어가는 부분은 제가 스크립트에서 jstl 사용 방식이 조금 서툴러서 급한대로 스크립트릿을 사용한 점 양해 부탁드립니다ㅜㅜ)

1개의 좋아요

아래 링크와 같이 컨텐츠는 HTMLElement로 생성하여 이벤트를 등록해주시고
스코프 유지를 위해 forEach 또는 함수 스코프로 만들어주세요.
https://devtalk.kakao.com/t/topic/41602/5
https://devtalk.kakao.com/t/topic/54337/2

마커를 생성하는 반복문 안에서 모두 처리가 가능합니다.
첫 번째 반복문에 마커 생성, 커스텀 오버레이 생성 및 닫기 이벤트 추가, 마커 이벤트를 등록해주세요.
그리고 커스텀 오버레이 생성 시 map 파라미터를 부여하지 않으면 지도에 올라가지 않기 때문에
위 로직처럼 map 파라미터를 적용하고 setMap(null);을 호출하지 않아도 됩니다.

정리하면 아래와 같은 로직으로 구현이 됩니다.
참고해주세요.

positions.forEach(function (pos) {
    // 마커를 생성합니다
    var marker = new kakao.maps.Marker({/* do something */});

    // content HTMLElement 생성
    var content = document.createElement('div');

    var info = document.createElement('span');
    info.appendChild(document.createTextNode(pos.title));
    content.appendChild(info);

    var closeBtn = document.createElement('button');
    closeBtn.appendChild(document.createTextNode('닫기'));
    // 닫기 이벤트 추가
    closeBtn.onclick = function() {
        overlay.setMap(null);
    };

    content.appendChild(closeBtn);

    // customoverlay 생성, 이때 map을 선언하지 않으면 지도위에 올라가지 않습니다.
    var overlay = new daum.maps.CustomOverlay({
        position: pos.latlng,
        content: content
    });

    // 마커를 클릭했을 때 커스텀 오버레이를 표시합니다
    kakao.maps.event.addListener(marker, 'click', function() {
        overlay.setMap(map);
    });
});
2개의 좋아요

정말 감사합니다.
덕분에 createElement 배워갑니다.
해결했습니다. 오전에 글을 보고 지금 해결 후 바로 답글 다네요ㅜㅜ
감사합니다.

3개의 좋아요