개발이야기/자바스크립트

[자바스크립트] 카카오맵 API 이용해 카테고리 장소 마커로 보여주기

후린개발자 2023. 7. 25.
반응형

카카오맵 API를 이용해서 지도 영역 내에 숙박과 음식점을 마커로 표시하고, 마커를 클릭하면 장소에 대한 정보를 노출하고 있습니다. 내 위치로 지도를 이동하는 버튼과, 카테고리를 선택하는 버튼도 생성하였습니다.

 

  • 소스코드 설명
    • panTo()
      • 내 위치로 지도를 이동시키는 기능입니다. get_latitude, get_longitude 변수를 사용하여 사용자의 위도와 경도 정보를 얻습니다. map.panTo() 함수를 호출하여 지도의 중심을 해당 위치로 이동시킵니다.
    • kakaomap()
      • 지도를 초기화하고, 필터 옵션을 사용하여 장소를 검색하고 마커를 표시합니다. kakao.maps.event.addListener() 함수를 사용하여 지도의 idle(정지) 상태일 때 searchPlaces() 함수를 호출합니다. searchPlaces() 함수를 호출하여 지도의 초기 장소를 검색하고 마커를 표시합니다.
    • searchPlaces()
      • 카테고리 옵션에 따라 장소를 검색하고 마커를 표시합니다.
    • placesSearchCB()
      • 카테고리 검색 결과를 처리하여 마커를 표시합니다.
    • displayMarker()
      • 장소 정보를 받아와서 해당 장소의 마커를 생성하고 지도에 표시하는 역할을 합니다. 각 장소에 대한 마커를 생성하고, 마커를 클릭했을 때 나타낼 장소 정보를 설정합니다.

 

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Expires" content="-1">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<link rel="stylesheet" type="text/css" href="../front/css/front.css">
<script type="text/javascript" src="https://code.jquery.com/jquery-1.10.2.min.js"/></script>
<script type="text/javascript" src="../front/js/front.js"></script>
<script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=카카오맵키&libraries=services"></script>
</head>
<body>
	<div class="map-wrap" style="position: absolute; left: 0; top: 0; right: 0; bottom: 60px;">
		<div id="map" style="width:100%; height:100%"></div>
		<div class="quick" style="z-index:100;">
			<a href="javascript:;" onclick="panTo()"><img src="../front/img/ico_map1.png"></a>
			<a href="javascript:;" id="filter"><img src="../front/img/ico_map2.png"></a>
		</div>
	</div>
	<script>
		var get_latitude = "";
		var get_longitude = "";
		navigator.geolocation.getCurrentPosition(function(pos) {
			get_latitude = pos.coords.latitude;
			get_longitude = pos.coords.longitude
		});

		var mylocationCheck = false;
		var foodCheck = true;
		var hotelCheck = true;
		let map;
		let ps;
		let markers = [];
		let markerPosition = [];

		kakaomap(hotelCheck,foodCheck);

		$(function() {
			$("#filter").click(function() {
				$('#modal3').modal();
			});
			$('#foodCheck').change(function() {
				if($(this).is(":checked")) {
					foodCheck=true;
				}else{
					foodCheck=false;
				}
				searchPlaces(hotelCheck,foodCheck);
			});
			$('#hotelCheck').change(function() {
				if($(this).is(":checked")) {
					hotelCheck=true;
				}else{
					hotelCheck=false;
				}
				searchPlaces(hotelCheck,foodCheck);
			});
		});
		function panTo() {
			if (navigator.geolocation) {
				mylocationCheck = true;
				if(get_latitude == ""){
					alert("GPS정보를 수신 중입니다.\r\n잠시 후 다시 시도해주세요");
					return;
				}else{
					var moveLatLon = new kakao.maps.LatLng(get_latitude, get_longitude);
					map.panTo(moveLatLon);
				}
			}
		}
		function kakaomap(hotelCheck,foodCheck){
			/*
			AD5 숙박
			FD6 음식점
			*/
			var mapContainer = document.getElementById('map'), // 지도 표기 DIV
			mapOption = {
				center: new kakao.maps.LatLng(37.566826, 126.9786567), //중심좌표
				level: "5" // 지도의 확대 영역
			};
			map = new kakao.maps.Map(mapContainer, mapOption);
			ps = new kakao.maps.services.Places(map);
			kakao.maps.event.addListener(map, 'idle', searchPlaces);

			searchPlaces();
		}
		function searchPlaces() {
			removeMarker();

			if(mylocationCheck == true){
				if (navigator.geolocation) {
					var imageSize = new kakao.maps.Size(43, 43);
					var imageSrc = 'img/marker5.png';
					var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize);
					var marker = new kakao.maps.Marker({	//지도에 뿌려주는 이미지마커
						map: map, // 마커를 표시할 지도
						position: new kakao.maps.LatLng(get_latitude, get_longitude) ,
						zIndex: 5,
						image : markerImage // 마커 이미지
					});
					markers.push(marker);
				}
			}
			if(foodCheck == true){
				ps.categorySearch('FD6', placesSearchCB, {useMapBounds:true});	
			}
			if(hotelCheck == true){
				ps.categorySearch('AD5', placesSearchCB, {useMapBounds:true});
			}

		}
		function placesSearchCB (data, status, pagination) {
			if (status === kakao.maps.services.Status.OK) {
				for (var i=0; i<data.length; i++) {
					displayMarker(data[i]);
				}
			}
		}
		// 지도에 마커를 표시하는 함수입니다
		function displayMarker(place) {
			// 마커를 생성하고 지도에 표시합니다
			if(place.category_group_code == "FD6"){
				imageSrc = '../front/img/marker4.png';
			}else if(place.category_group_code == "AD5"){
				imageSrc = '../front/img/marker1.png';
			}
			var imageSize = new kakao.maps.Size(36, 49);
			var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize);
			var marker = new kakao.maps.Marker({
				map: map,
				position: new kakao.maps.LatLng(place.y, place.x) ,
				zIndex: 3,
				image : markerImage
			});
			markers.push(marker);
			// 마커에 클릭이벤트를 등록합니다
			kakao.maps.event.addListener(marker, 'click', function() {
				//음식점
				if(place.category_group_code == "FD6"){
					$('#category_name').text("음식점 : ");
				}else{
					$('#category_name').text("숙박 : ");
				}

				$('#place_name').text(place.place_name);
				$('#place_phone').text(place.phone);
				$('#place_addr').text(place.address_name);
				$('#modal5').modal();
			});
		}
		function removeMarker() {
			for ( var i = 0; i < markers.length; i++ ) {
				markers[i].setMap(null);
			}
			markers = [];
		}
	</script>
	<div class="modal" id="modal3" style="z-index:999999;">
		<div class="modal-dialog" style="max-width:350px">
			<div class="modal-content">
				<div class="modal-header">
					<h7><strong>카테고리</strong></h7>
					<button class="close-modal" data-dismiss="modal">닫기</button>
				</div>
				<div class="modal-body">
					<div class="info" style="display:inline-flex;">
						<input type="checkbox" id="hotelCheck" checked>
						<label for="hotelCheck"></label>

						<input type="checkbox" id="foodCheck" checked>
						<label for="foodCheck"></label>
					</div>
					<div class="btns">
						<a href="javascript:;" class="b1" data-dismiss="modal">닫기</a>
					</div>

				</div>
			</div>
		</div>
	</div>
	<div class="modal" id="modal5">
		<div class="modal-dialog" style="max-width:800px">
			<div class="modal-content">
				<div class="modal-header">
					<h7><strong>업체정보</strong></h7>
					<button class="close-modal" data-dismiss="modal">닫기</button>
				</div>
				<div class="modal-body">
					<div class="info">
						<dl>
							<dt id="category_name"></dt>
							<dd><strong id="place_name"></strong></dd>
						</dl>
						<dl>
							<dt>연락처 : </dt>
							<dd id="place_phone"></dd>
						</dl>
						<dl>
							<dt>주소 : </dt>
							<dd id="place_addr"></dd>
						</dl>
						<div class="btns">
							<a href="javascript:;" class="b1" data-dismiss="modal">닫기</a>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</body>
</html>

 

 

소스코드 화면

 

 

카테고리 버튼

 

 

장소 정보 화면

 

 


CSS 부분 입니다.

 

.map-wrap { position: absolute; left: 0; top:50px; right:0; bottom:60px; }
.map-wrap .marker { position: absolute; }
.map-wrap .marker img { width:36px; }
.map-wrap .btns { position: absolute; left: 20px; bottom:20px; right:20px; }
.map-wrap .btns .b1 { display: block; height: 50px; line-height: 49px; text-align: center; font-size:21px; color: #fff; background: #f18c2c; border-radius:5px; margin-bottom: 7px;  }
.map-wrap .btns .b1:before { content: ''; display: inline-block; vertical-align: middle; background: url(../img/ico_chk.png) no-repeat 50% 50%; width:25px; height: 21px; background-size:25px auto;margin:-5px 10px 0 0; }
.map-wrap .btns .desc { border-radius:4px; line-height: 30px; font-size:13px; color: #fff; text-align: center; background: rgba(0,0,0,0.6);}
.map-wrap .btns .desc:before { content: ''; display: inline-block; vertical-align: middle; background: url(../img/ico_photo.png) no-repeat 50% 50%; width:17px; height: 15px; background-size:17px auto; margin:-3px 5px 0 0; }
.map-wrap .quick { position: absolute; right:20px; top:20px; }
.map-wrap .quick a { display: block; width:34px; margin-bottom: 5px; }
.map-wrap .quick a img { width:100%; }

/***********************************************************************************************
MODAL
***********************************************************************************************/
.hidden { overflow:hidden; }
.modal-backdrop {position: fixed; top:0; right:0; bottom:0; left:0; background:#000; z-index:7500; opacity:.7; filter:alpha(opacity=70);}
.modal {display:none; position:fixed; top:0; right:0; bottom:0; left:0; z-index:8000; overflow:auto; -webkit-overflow-scrolling:touch; outline:0; }
.modal-dialog {position:relative; width:auto;margin:0 auto 15px;  padding:0 20px; }
.modal-content {position:relative; background-color:#fff; outline:none;  /*overflow:hidden; */ border-radius:15px;  }
.modal-header { padding:25px 0;  }
.modal-header h4 img { height: 52px; }
.modal-header h4 { text-align: center; }
.modal-header h5 { text-align: center; font-size:24px; padding:30px 0 10px; font-family: 'S-CoreDream-6Bold';}
.modal-header h6 { display: flex; align-items: baseline;  padding:20px 20px 15px; }
.modal-header h6 strong { font-size:24px; color: #333; font-family: 'S-CoreDream-6Bold';}
.modal-header h6 span { padding-left: 8px; margin-left: 10px; position: relative; font-size:18px; color: #49a9de; font-weight: 400; letter-spacing: -1px; position: relative;}
.modal-header h6 span:before {content: ''; position: absolute; left: 0; top:50%; width:2px; height: 14px; margin-top:-7px; background: #f18c2c; }
.modal-header h7 { padding:20px 0 20px 20px;}
.modal-header h7 strong { display: inline-block;vertical-align: middle; padding-bottom: 4px; border-bottom: 2px solid #f18c2c; font-size:24px;font-family: 'S-CoreDream-6Bold'; }
.modal-header .close-modal { position: absolute; right:0; top:0; width:55px; height:55px; background: url(../img/ico_modal_close.png) no-repeat 50% 50%; text-indent: -9999px; background-size:22px auto;  }
.modal-body { padding:0 20px 20px; }

반응형

댓글

💲 추천 글