여러개의 오버레이를 생성 후 제거 문제

안녕하세요.

여러개의 오버레이를 생성 후 마커를 hover했을 시 오버레이가 보이게 코드를 작성해봤습니다.
하지만 오버레이를 hide or fadeOut으로 처리 했을 경우 다시 오버레이를 보게 하기가 힘드네요.

개발자님들께 질문드립니다.
이미 닫기 기능이 가능한 오버레이를 참조해보았지만 해결이 안되어 글을 작성하게 되었습니다.

아래는 저의 코드입니다
content에서 마우스 out했을 경우 오버레이가 없어지고 다시 marker에 마우스가 hover했을 경우
오버레이가 생기게 하고 싶습니다.

$(data).find(‘item’).each(function(){ // xml 문서 item 기준으로 분리후 반복
var latitude = $(this).find(“latitude”).text();
var longitude = $(this).find(“longitude”).text();
// 위도와 경도를 읽어온 후 위치 잡기
var latlng = new daum.maps.LatLng(latitude, longitude)

                    var name = $(this).find("name").text(); 
                    var newAddr = $(this).find("newAddr").text();
                    var tel = $(this).find("tel").text();


                    // 마커를 생성합니다
                    var marker = new daum.maps.Marker({
                        map: map, // 마커를 표시할 지도
                        position: latlng // 마커를 표시할 위치
                    });

        
                   

                    var content = 
                    '<div class="card text-white bg-dark mb-3" style="position:relative; bottom:95px; max-width:21rem; max-height:10rem; font-size:0.9rem;" >'+
                    '<div class="removeBox" onclick="removeBox()" style="position:absolute; right:10px; top: 10px; cursor:pointer; font-size:20px;">X</div>'+
                    '<div class="card-body">'+
                        '<h6 class="card-title" style="font-size:1rem;">'+
                        name+
                        '</h6>'+
                        '<p class="card-text" style="font-size: 0.7rem;">'+
                        newAddr +
                        '</p>'+
                        '<p class="card-text">'+
                        tel +
                        '</p>'+
                    '</div>'+
                    '</div>'




                    



                    // 마커 위에 커스텀오버레이를 표시합니다
                    // 마커를 중심으로 커스텀 오버레이를 표시하기위해 CSS를 이용해 위치를 설정했습니다
                    var overlay = new daum.maps.CustomOverlay({
                        content: content,
                        position: latlng       
                    });


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

http://apis.map.daum.net/web/sample/removableCustomOverlay/

이 예제를 기준으로,
이렇게 해보시면 되지 않나요?

daum.maps.event.addListener(marker, ‘mouseover’, function() {
overlay.setMap(map);
});

daum.maps.event.addListener(marker, ‘mouseout’, function() {
closeOverlay();
});

좋아요 1

먼저 답변해주셔서 감사드립니다.

알려 주신 코드로 작성했을 경우,
오버레이가 바로 없어지는 현상이 나타납니다.(이름,전화번호,위치)가 나오는 곳 // div class=“card” 이하 부분
지금은 marker를 기준으로 mouserover mouseout을 하고 있습니다. 저는 아래 2가지 기능을 구현하고 싶습니다.
오버레이에서 mouseout이 됬을 경우 closeOverlay();
마커에게 mouseover가 됬을 경우 overlay.setMap(map);

하지만 생각대로 잘 되지 않네요. 카카오 Maps님의 도움이 절실합니다…

마커 기준으로 오버레이를 열고 닫으니 마커를 벗어나면 닫히는 코드였어요.

일단 커스텀오버레이에서는 마커에 사용하는 이벤트리스너가 동작하지 않을거구요.
아래 링크 참고해주세요.

그런데 말씀하신 방식이 모순이 좀 있어요

“마커에게 mouseover가 됬을 경우 overlay.setMap(map);”

마커에 마우스오버가 되면 오버레이가 나타나는데 이때 마우스포인터는 오버레이 영역을 이미 벗어나 있는 상태입니다.

“오버레이에서 mouseout이 됬을 경우 closeOverlay();”

그런데 다시 오버레이를 닫으려면, 밖에 있던 마우스 포인터가 일부러 오버레이를 스쳐지나가야 하는데요
이렇게 하는 걸 원하시는 게 맞는지요?

좋아요 1

지속적인 답변 정말 감사드립니다.
말씀해주신 대로 저의 말에 모순이 있었네요.
다음 캡처 1
공유해 URL에 들어가서 참조해보았습니다.
그러면 오버레이마다 순번을 따로 만들어 각각에 이벤트를 걸어줘야 되는게 맞을까요?
추가적으로 이벤트를 줄 경우 overlay.setMap(null); 처럼 주면 되는게 맞을까요?
fadeOut()과 hide()함수는 적용해 보니 약간의 어색함이 있었습니다.

제가 첨부한 다음 지도 이미지처럼 X버튼을 누르면 오버레이가 삭제되고
마커를 클릭시 오버레이가 나오게 하고 싶습니다.
하나의 마커와 하나의 오버레이서는 잘 작동하지만 여러개의 오버레이와 마커가 생기니
잘 작동 되지 않습니다.
예제를 몇번 해보고 doji.doo님이 달아주신 글도 읽어 봤지만 잘 해결이 안되네요.

닫기 버튼으로 오버레이를 지우고, 마커클릭으로 오버레이를 보이게 하는 건 위의 예제와 동일한건데요.

두개로 (그냠 임의로 넣어본 겁니다. 전 개발자 아니에요) 해봐도 잘 동작해요.

var mapContainer = document.getElementById('map'), // 지도의 중심좌표
    mapOption = { 
        center: new daum.maps.LatLng(33.455475, 126.585528), // 지도의 중심좌표
        level: 6 // 지도의 확대 레벨 
    }; 

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

// 지도에 마커를 표시합니다 
var marker1 = new daum.maps.Marker({
    map: map, 
    position: new daum.maps.LatLng(33.450701, 126.570667)
});

var marker2 = new daum.maps.Marker({
    map: map, 
    position: new daum.maps.LatLng(33.450701, 126.600667)
});
// 커스텀 오버레이에 표시할 컨텐츠 입니다
// 커스텀 오버레이는 아래와 같이 사용자가 자유롭게 컨텐츠를 구성하고 이벤트를 제어할 수 있기 때문에
// 별도의 이벤트 메소드를 제공하지 않습니다 
var content1 = '<div class="wrap">' + 
            '    <div class="info">' + 
            '        <div class="title">' + 
            '            카카오 스페이스닷원' + 
            '            <div class="close" onclick="closeOverlay1()" title="닫기"></div>' + 
            '        </div>' + 
            '        <div class="body">' + 
            '            <div class="img">' +
            '                <img src="http://cfile181.uf.daum.net/image/250649365602043421936D" width="73" height="70">' +
            '           </div>' + 
            '            <div class="desc">' + 
            '                <div class="ellipsis">제주특별자치도 제주시 첨단로 242</div>' + 
            '                <div class="jibun ellipsis">(우) 63309 (지번) 영평동 2181</div>' + 
            '                <div><a href="http://www.kakaocorp.com/main" target="_blank" class="link">홈페이지</a></div>' + 
            '            </div>' + 
            '        </div>' + 
            '    </div>' +    
            '</div>';

var content2 = '<div class="wrap">' + 
            '    <div class="info">' + 
            '        <div class="title">' + 
            '            카카오 스페이스닷투' + 
            '            <div class="close" onclick="closeOverlay2()" title="닫기"></div>' + 
            '        </div>' + 
            '        <div class="body">' + 
            '            <div class="img">' +
            '                <img src="http://cfile181.uf.daum.net/image/250649365602043421936D" width="73" height="70">' +
            '           </div>' + 
            '            <div class="desc">' + 
            '                <div class="ellipsis">제주특별자치도 제주시 첨단로 242</div>' + 
            '                <div class="jibun ellipsis">(우) 63309 (지번) 영평동 2181</div>' + 
            '                <div><a href="http://www.kakaocorp.com/main" target="_blank" class="link">홈페이지</a></div>' + 
            '            </div>' + 
            '        </div>' + 
            '    </div>' +    
            '</div>';    
// 마커 위에 커스텀오버레이를 표시합니다
// 마커를 중심으로 커스텀 오버레이를 표시하기위해 CSS를 이용해 위치를 설정했습니다
var overlay1 = new daum.maps.CustomOverlay({
    content: content1,
    map: map,
    position: marker1.getPosition()       
});

    var overlay2 = new daum.maps.CustomOverlay({
    content: content2,
    map: map,
    position: marker2.getPosition()       
});
// 마커를 클릭했을 때 커스텀 오버레이를 표시합니다
daum.maps.event.addListener(marker1, 'click', function() {
    overlay1.setMap(map);
});

daum.maps.event.addListener(marker2, 'click', function() {
    overlay2.setMap(map);
});
    
// 커스텀 오버레이를 닫기 위해 호출되는 함수입니다 
function closeOverlay1() {
    overlay1.setMap(null);     
}
    
function closeOverlay2() {
    overlay2.setMap(null);     
}
좋아요 1

marker over/out 일 때 InfoWindow visible 처리:
http://apis.map.daum.net/web/sample/multipleMarkerEvent/

marker click 일 때:
http://apis.map.daum.net/web/sample/keywordBasic/

여러개의 커스텀 오버레이의 닫기 버튼 구현시 주의할 점:

좋아요 2

지속적인 답변 감사드립니다.

만약 데이터의 갯수가 많이 늘어날 경우의 문제입니다.
var overlays = [ ] // 빈 overlay배열을 선언 후
overlays.push(overlay)를 each문을 통해 오버레이의 갯수 만큼 넣어준 뒤 아래와 같은 코드를 구성하려고합니다.
Ex) overlay의 갯수가 50개이면 overlays.length = 50;

        function removeBox(){
            var overlay = overlays[37];
            overlay.setMap(null);
        }

함수를 하나하나 일일히 작성할 수 없기 떄문에 반복문으로 작성하려고 하는데 그 뒤로 방법을 잘 못찾겠습니다.

http://apis.map.daum.net/web/sample/keywordBasic/
이 예제의 변형입니다.

<div id="map" style="width:100%;height:350px;"></div>
<script>
// 마커를 클릭하면 장소명을 표출할 인포윈도우 입니다
var infowindow = new daum.maps.InfoWindow({zIndex:1});

var mapContainer = document.getElementById('map'), // 지도를 표시할 div 
    mapOption = {
        center: new daum.maps.LatLng(37.566826, 126.9786567), // 지도의 중심좌표
        level: 3 // 지도의 확대 레벨
    };  

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

// 장소 검색 객체를 생성합니다
var ps = new daum.maps.services.Places(); 

// 키워드로 장소를 검색합니다
ps.keywordSearch('이태원 맛집', placesSearchCB); 

// 키워드 검색 완료 시 호출되는 콜백함수 입니다
function placesSearchCB (data, status, pagination) {
    if (status === daum.maps.services.Status.OK) {

        // 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해
        // LatLngBounds 객체에 좌표를 추가합니다
        var bounds = new daum.maps.LatLngBounds();

        for (var i=0; i<data.length; i++) {
            displayMarker(data[i]);    
            bounds.extend(new daum.maps.LatLng(data[i].y, data[i].x));
        }       

        // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다
        map.setBounds(bounds);
    } 
}

// 지도에 마커를 표시하는 함수입니다
function displayMarker(place) {
    
    // 마커를 생성하고 지도에 표시합니다
    var marker = new daum.maps.Marker({
        map: map,
        position: new daum.maps.LatLng(place.y, place.x) 
    });
    var overlay = new daum.maps.CustomOverlay({
        yAnchor: 3,
        position: marker.getPosition()
    });
    
    var content = document.createElement('div');
    content.innerHTML =  place.place_name;
    content.style.cssText = 'background: white; border: 1px solid black';
    
    var closeBtn = document.createElement('button');
    closeBtn.innerHTML = '닫기';
    closeBtn.onclick = function () {
        overlay.setMap(null);
    };
    content.appendChild(closeBtn);
    overlay.setContent(content);

    daum.maps.event.addListener(marker, 'click', function() {
        overlay.setMap(map);
    });
}
</script>

반복문으로는 데이터를 순회하고 그 데이터로 뷰를 만드는 부분은 diaplayMarker()입니다.
displayMarker() 함수를 보시면 커스텀 오버레이의 content와 마커의 생성 및 이벤트 연결하는 방법이 나와 있습니다. 이 부분을 참고하세요.

좋아요 1

지속적인 답변 감사드립니다.
점점 기능이 구현되고 있습니다. 감사합니다.

추가적으로 질문 한 가지만 더 드리겠습니다. 죄송합니다

 1. 소스코드

  var content =      
 '<div class="card text-white bg-dark mb-3" style="position:relative; bottom:95px; max-width:21rem; max-height:10rem; font-size:0.9rem;" >'+
'<div class="card-body">'+
'<h6 class="card-title" style="font-size:1rem;">'+
 name+
'</h6>'+
'</div'>+
'</div>


2. 소스코드
var content = document.createElement('div');
content.innerHTML = name;

많은 양의 데이터를 처리한 후 오버레이에 스타일과 클래스를 추가하고 싶습니다.
지금 jQuery를 사용 하고 있습니다. 2. 소스코드를 ==> 1.소스코드 처럼 간편하게 입력할 수 없을까요?
1.소스코드 처럼 했을 때는 content.appendChild()함수에 오류가 생기고 있습니다.

마지막으로 정말 지속적인 답변 감사드립니다.

끄응;
DOM API와 jQuery간의 관계 및 jQuery 사용법에 대한 이해도가 부족해서 애를 먹으시는 것 같은데요.

이 이상의 질답은 저와 질문자분 모두에게 도움이 되지 않을 것 같습니다.

말씀하신 변환을 원하시면
jQuery로 DOM 노드를 만드는 방식을 찾아보세요.
클래스 부여나 엘리먼트 attach는 모두 jQuery로 가능하니까요.

좋아요 2

jQuery가 아닌 순수한 VanillaJS를 사용하여 해결했습니다.

.className과 .innerHtml를 사용하여 부모와 자식태그를 서로 연결하습니다
고민할 기회를 주셔서 감사합니다.

doji.doo님이 없으셨다면 해결하지 못 했을겁니다. 정말감사합니다. 고생하세요!

좋아요 2