지오로케이션위치로부터 1km 3km 5km 전체 위치 표시하기

안녕하세요
지도에 받아온 데이터를 라디오버튼을 사용하여
1km, 3km, 5km, 전체 위치 표시하기 를 만들고 있는데

지오 로케이션의 거리로부터 마커들간의 거리를 구하여 1km, 3km, 5km 전체 위치 표시 하는
이벤트는 구현을 해냈습니다
사진과 같이 보시면
처음 지오로케이션으로 잡은곳에선 잘 작동을 하게 됩니다
그러나 현재 사용자의 위치가 아닌 다른곳에서 또는 지도를 축소해서 라디오버튼을 선택하게되면
마커가 거리와 관계없이 이상하게 찍힙니다.
무슨 문제일까요?..
현재 원은 3km 범위로 만들어놨습니다.
$(document).ready(function(){

var mapContainer = document.getElementById(‘map’), // 지도를 표시할 div
mapOption = {
center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
level: 7 // 지도의 확대 레벨
};

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

// 일반 지도와 스카이뷰로 지도 타입을 전환할 수 있는 지도타입 컨트롤을 생성합니다
var mapTypeControl = new kakao.maps.MapTypeControl();

// 지도에 컨트롤을 추가해야 지도위에 표시됩니다
// kakao.maps.ControlPosition은 컨트롤이 표시될 위치를 정의하는데 TOPRIGHT는 오른쪽 위를 의미합니다
map.addControl(mapTypeControl, kakao.maps.ControlPosition.TOPRIGHT);

// 지도 확대 축소를 제어할 수 있는 줌 컨트롤을 생성합니다
var zoomControl = new kakao.maps.ZoomControl();
map.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT);

// // 마커 클러스터러를 생성합니다
// var clusterer = new kakao.maps.MarkerClusterer({
// map: map, // 마커들을 클러스터로 관리하고 표시할 지도 객체
// averageCenter: true, // 클러스터에 포함된 마커들의 평균 위치를 클러스터 마커 위치로 설정
// minLevel: 10 // 클러스터 할 최소 지도 레벨
// });
// HTML5의 geolocation으로 사용할 수 있는지 확인합니다
if (navigator.geolocation) {

// GeoLocation을 이용해서 접속 위치를 얻어옵니다
navigator.geolocation.getCurrentPosition(function(position) {

  var lat = position.coords.latitude, // 위도
  lon = position.coords.longitude; // 경도

  var locPosition = new kakao.maps.LatLng(lat, lon), // 마커가 표시될 위치를 geolocation으로 얻어온 좌표로 생성합니다
  message = '<div class="locationmy">현재 사용자의 위치입니다?!</div>'; // 인포윈도우에 표시될 내용입니다

  // 마커와 인포윈도우를 표시합니다
  displayMarker(locPosition, message);
  // 지도에 표시할 원을 생성합니다
  var circle = new kakao.maps.Circle({
    center :locPosition,  // 원의 중심좌표 입니다
    radius: 3000, // 미터 단위의 원의 반지름입니다
    strokeWeight: 5, // 선의 두께입니다
    strokeColor: '#75B8FA', // 선의 색깔입니다
    strokeOpacity: 1, // 선의 불투명도 입니다 1에서 0 사이의 값이며 0에 가까울수록 투명합니다
    strokeStyle: 'dashed', // 선의 스타일 입니다
    // fillColor: '#CFE7FF', // 채우기 색깔입니다
    // fillOpacity: 0.7  // 채우기 불투명도 입니다
  });

  // 지도에 원을 표시합니다
  circle.setMap(map);
});

} else { // HTML5의 GeoLocation을 사용할 수 없을때 마커 표시 위치와 인포윈도우 내용을 설정합니다

var locPosition = new kakao.maps.LatLng(33.450701, 126.570667),
message = 'geolocation을 사용할수 없어요..'

displayMarker(locPosition, message);

}

// 지도에 마커와 인포윈도우를 표시하는 함수입니다
function displayMarker(locPosition, message) {

// 마커를 생성합니다
var markers = new kakao.maps.Marker({
  map: map,
  position: locPosition
});

var iwContent = message, // 인포윈도우에 표시할 내용
iwRemoveable = true;

// 인포윈도우를 생성합니다
var infowindow = new kakao.maps.InfoWindow({
  content : iwContent,
  removable : iwRemoveable
});

// 인포윈도우를 마커위에 표시합니다
infowindow.open(map, markers);

// 지도 중심좌표를 접속위치로 변경합니다
map.setCenter(locPosition);

}
// 주소-좌표 변환 객체를 생성합니다
var geocoder = new kakao.maps.services.Geocoder();

var mapname = $(’.mapname’);
var mapid = $(’.mapip’);
var positions = $(’.maparry’);
var mappicture = $(’.mappicture’);
var mapstartprice = $(’.mapstartprice’)
var mapproduct = $(’.mapproduct’);
var rodcount = {{count($road)}};
// console.log(id);
var add = [];
var id = [];
var name = [];
var picture = [];
var startprice = [];
var product = [];
var makers = [];

for (i = 0; i < mapproduct.length; i++) {
product.push(mapproduct[i].value);
}
for (i = 0; i < mapstartprice.length; i++) {
startprice.push(mapstartprice[i].value);
}
for (i = 0; i < mappicture.length; i++) {
picture.push(mappicture[i].value);
}
console.log(picture);
for (i = 0; i < mapname.length; i++) {
name.push(mapname[i].value);
}
for (i = 0; i < mapid.length; i++) {
id.push(mapid[i].value);
}
for(i=0; i<positions.length;i++){
add.push(positions[i].value);
}
for(let i=0; i <add.length; i++){
// console.log(add[i]);
geocoder.addressSearch(add[i], function(result, status) {

  // 정상적으로 검색이 완료됐으면
  if (status === kakao.maps.services.Status.OK) {

    var coords = new kakao.maps.LatLng(result[0].y, result[0].x);

    // 결과값으로 받은 위치를 마커로 표시합니다
    var marker = new kakao.maps.Marker({
      map: map,
      position: coords
    });
    // markers.push(marker);
    var link = mapproduct[i];
    var fuck = picture[i];
    console.log(fuck);
    // iwRemoveable = true; // removeable 속성을 ture 로 설정하면 인포윈도우를 닫을 수 있는 x버튼이 표시됩니다
    var iwContent =
    '<div class="wrap">' +
    '    <div class="info">' +
    '        <div class="title">' + name[i] +
    '          <div class="close" onclick="closeOverlay()" title="닫기"></div>' +
    '        </div>'+
    '        <div class="body">' +
    '            <div class="img">' +
    '                  <img src="/img/item/'+fuck+'" width="73" height="70">' +
    '            </div>' +
    '            <div class="desc">' +
    '                <div class="ellipsis">'+ add[i]+'</div>' +
    '                <div class="jibun ellipsis">판매자 :'+ id[i] +'</div>' +
    '                <div class="stapri">경매 시작가격 : ' + startprice[i] + '</div>'+
    '                <div><a href="/product-detail/'+product[i]+'" target="_self" class="link">상품 바로가기</a></div>' +
    '            </div>' +
    '        </div>' +
    '    </div>' +
    '</div>', // 인포윈도우에 표출될 내용으로 HTML 문자열이나 document element가 가능합니다
    iwRemoveable = true;

    // 인포윈도우를 생성합니다
    var infowindow = new kakao.maps.InfoWindow({
      content : iwContent,
      removable : iwRemoveable
    });

    // 마커에 클릭이벤트를 등록합니다
    kakao.maps.event.addListener(marker, 'click', function() {
      // 마커 위에 인포윈도우를 표시합니다
      infowindow.open(map, marker);
    });
    // var radius = 1000;

    $("input:radio[name=chk_km]").change(function(){
      if ($('input:radio[name=chk_km]:checked').val() == "1km") {
        var radius = 1000;
      }
      if($('input:radio[name=chk_km]:checked').val() == "3km") {
        var radius = 3000;
      }
      if($('input:radio[name=chk_km]:checked').val() == "5km") {
        var radius = 5000;
      }
      if($('input:radio[name=chk_km]:checked').val() == "all_maker") {
        var radius = 100000;
      }
      console.log(radius);
      // 상품을 표시할 원의 반경 미터
        var c1 = map.getCenter(locPosition);
        var c2 = marker.getPosition();
        console.log(radius);
        console.log(c2);
        var poly = new kakao.maps.Polyline({
          path: [c1, c2]
        });
        // console.log(path);
        var dist = poly.getLength(); // m 단위로 리턴
        if (dist < radius) {
          marker.setMap(map);
        } else {
          marker.setMap(null);
        }
      });
    // // 지도의 중심을 결과값으로 받은 위치로 이동시킵니다
     map.setCenter(locPosition);
  }
});

}
});

처음페이지가 로드되고 지도를 움직이지 않은채 라디오버튼만 작동시

마커를 배열로 관리하고 라디오 버튼이 눌렸을 때
지도의 중심 좌표와 마커들 간의 거리를 비교해서 범위 안에 있는 마커를 표시해주세요.

아래 링크와 코드 함께 참고해주세요.

<body>
    <div id="map" style="width:100%;height:350px;"></div>

    <button onclick="showMarker(1000)">1km</button>
    <button onclick="showMarker(3000)">3km</button>
    <button onclick="showMarker(5000)">5km</button>
    <button onclick="showMarker(100000)">모두보기</button>

    <script>
        var mapContainer = document.getElementById('map'), // 지도를 표시할 div
        mapOption = {
            center: new kakao.maps.LatLng(33.450701, 126.570667), // 지도의 중심좌표
            level: 7 // 지도의 확대 레벨
        };

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

        var current = new kakao.maps.Marker({
            map: map,
            position: new kakao.maps.LatLng(33.450701, 126.570667)
        });

        // 주소-좌표 변환 객체를 생성합니다
        var geocoder = new kakao.maps.services.Geocoder();
        var add = ['제주특별자치도 제주시 첨단로 242', '제주특별자치도 제주시 명림로 575-107', '제주특별자치도 제주시 516로 2870', '제주특별자치도 제주시 한북로 313'];
        var markers = [];
        for(let i=0; i <add.length; i++){
        geocoder.addressSearch(add[i], function(result, status) {
            // 정상적으로 검색이 완료됐으면
            if (status === kakao.maps.services.Status.OK) {
                var coords = new kakao.maps.LatLng(result[0].y, result[0].x);
                // 결과값으로 받은 위치를 마커로 표시합니다
                var marker = new kakao.maps.Marker({
                    map: map,
                    position: coords
                });

                markers.push(marker);
            }
        });
    }

    var circle = new kakao.maps.Circle({});

    function showMarker(radius) {
        var center = map.getCenter();
        var line = new kakao.maps.Polyline();

        if(radius < 100000) {
            circle.setMap(map);
            circle.setPosition(center);
            circle.setRadius(radius);
        } else {
            // 전체보기
            circle.setMap(null);
        }

        markers.forEach(marker => {
            var path = [marker.getPosition(), center];
            line.setPath(path);

            // 마커와 원의 중심 사이의 거리
            var dist = line.getLength();

            // 이 거리가 원의 반지름보다 작거나 같다면
            if (dist <= radius) {
                // 해당 marker는 원 안에 있는 것
                marker.setMap(map);
            } else {
                marker.setMap(null);
            }
        });
    }
    </script>
1개의 좋아요

감사합니다… 원을 변경하는것까진 했는데
원이 지도 중앙에서부터 계산하여 만들어지는것 같네요… 그이유는 알 수 있을가요?
<-- 코드입니다!! -->
var circle = new kakao.maps.Circle({
center :locPosition, // 원의 중심좌표 입니다
radius: 3000, // 미터 단위의 원의 반지름입니다
strokeWeight: 5, // 선의 두께입니다
strokeColor: ‘#75B8FA’, // 선의 색깔입니다
strokeOpacity: 1, // 선의 불투명도 입니다 1에서 0 사이의 값이며 0에 가까울수록 투명합니다
strokeStyle: ‘dashed’, // 선의 스타일 입니다
fillColor: ‘#CFE7FF’, // 채우기 색깔입니다
fillOpacity: 0.05 // 채우기 불투명도 입니다
});
$(“input:radio[name=chk_km]”).change(function(){
var locPosition = map.getCenter(locPosition);
var line = new kakao.maps.Polyline();
if ($(‘input:radio[name=chk_km]:checked’).val() == “1km”) {
var radius = 1000;
circle.setMap(map);
circle.setPosition(locPosition);
circle.setRadius(radius);
}
if($(‘input:radio[name=chk_km]:checked’).val() == “3km”) {
var radius = 3000;
circle.setMap(map);
circle.setPosition(locPosition);
circle.setRadius(radius);
}
if($(‘input:radio[name=chk_km]:checked’).val() == “5km”) {
var radius = 5000;
circle.setMap(map);
circle.setPosition(locPosition);
circle.setRadius(radius);
}
if($(‘input:radio[name=chk_km]:checked’).val() == “all_maker”) {
var radius = 100000;
circle.setMap(null);
}
console.log(radius);
// 상품을 표시할 원의 반경 미터
var c1 = map.getCenter(locPosition);
var c2 = marker.getPosition();
// 지도에 표시할 원을 생성합니다
// 지도에 원을 표시합니다
// circle.setMap(map);
console.log(radius);
console.log(c2);
var poly = new kakao.maps.Polyline({
path: [c1, c2]
});
// console.log(path);
var dist = poly.getLength(); // m 단위로 리턴
if (dist < radius) {
marker.setMap(map);
} else {
marker.setMap(null);
}
});
<-- 코드입니다!! -->

혹시 지도의 시점을 이동하였을때 가운데에 마커가 따라다니며 보이게 할 순 없나요?
사진을 첨부합니다!

로직을 보면 원의 중심 좌표를 지도의 중심 좌표로 설정하고 있습니다.
이 부분을 원하는 구현 방향으로 수정하면 됩니다.

var locPosition = map.getCenter(locPosition);
/* .... */
circle.setPosition(locPosition);
/*....*/

그리고 지도의 중심 좌표를 가져오는 API는 map.getCenter(); 로 호출해주세요.
파라미터를 넣지 않아도 됩니다.

idle, dragend 이벤트를 등록해서 지도 패닝이 끝났을 때 마커의 위치를 변경하면
지도 중심에 표출할 수 있습니다.

http://apis.map.kakao.com/web/documentation/#Map_idle
http://apis.map.kakao.com/web/documentation/#Map_dragend

1개의 좋아요

빠른 답변 감사합니다ㅠ!

dragend 이벤트를 등록해서 지도 패닝이 끝났을 때 마커의 위치를 변경하면
지도 중심에 표출하는 이벤트도 성공하였는데 문제가
지도를 드래그하여 이동할때마다 마커가 계속 중심점에 생겨서 이전에 중심점에 마커가 남습니다 ㅠ

지도 중심에 표출할 마커를 전역 변수로 선언하고 이벤트에서 marker.setPosition(/*..*/); 으로 위치를 변경하거나
이벤트 로직에서 마커를 매번 새로 생성한다면 이전 마커를 지우고 마커를 생성해주세요.

1개의 좋아요

감사합니다…아직 답은못찾았지만 한번 해결해 볼께요