Jeongmin Seo

Add map UI using Kakao map API

1 -# Favorite restaurant platform
...\ No newline at end of file ...\ No newline at end of file
File mode changed
1 +<!DOCTYPE html>
2 +<html lang="en">
3 + <head>
4 + <meta charset="UTF-8" />
5 + <meta http-equiv="X-UA-Compatible" content="IE=edge" />
6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 + <title>맛집지도</title>
8 + <meta name="author" content="양주미" />
9 + <meta name="description" content="맛집지도 서비스" />
10 + <meta
11 + name="keywords"
12 + content="맛집지도, 맛집추천, 실시간채팅"
13 + />
14 + <link rel="stylesheet" href="style.css" />
15 + </head>
16 +
17 + <body>
18 + <nav>
19 + <div class="inner">
20 + <div class="nav-container">
21 + <h1 class="nav-title">맛집지도</h1>
22 + <button class="nav-contact">Contact</button>
23 + </div>
24 + </div>
25 + </nav>
26 +
27 + <main>
28 + <section id="category">
29 + <div class="inner">
30 + <div class="category-container">
31 + <h2 class="category-title">💜맛집지도 카테고리를 선택해보세요💜</h2>
32 + <div class="category-list">
33 + <button class="category-item" id="korea">한식🍚</button
34 + ><button class="category-item" id="china">중식🍜</button
35 + ><button class="category-item" id="japan">일식🍙</button
36 + ><button class="category-item" id="america">양식🍝</button
37 + ><button class="category-item" id="wheat">분식🍭</button
38 + ><button class="category-item" id="meat">구이🍖</button
39 + ><button class="category-item" id="sushi">회/초밥🍣</button
40 + ><button class="category-item" id="etc">기타🍴</button>
41 + </div>
42 + </div>
43 + </div>
44 + </section>
45 + <!-- 카테고리 -->
46 + <div id="map" class="inner"></div>
47 +
48 + <!-- 카카오지도 -->
49 + </main>
50 +
51 + <script
52 + type="text/javascript"
53 + src="//dapi.kakao.com/v2/maps/sdk.js?appkey=2263ae9eb197ad864a94eb1ed7b912c9&libraries=services">
54 +</script>
55 +
56 + <script src="script.js"></script>
57 + </body>
58 +</html>
...\ No newline at end of file ...\ No newline at end of file
1 +/*인포윈도우 설정*/
2 +.infowindow {
3 + width : 25rem;
4 + border : 1px solid black;
5 + border-radius: 5px;
6 + background-color : white;
7 +}
8 +
9 +.infowindow-title {
10 + font-size: 3rem;
11 +}
12 +
13 +.infowindow-address {
14 + font-size: 1.6rem;
15 +}
16 +
17 +.infowindow-btn {
18 + font-size: 1.6rem;
19 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/******************************************************************************
2 + * 1. 지도 생성 및 확대 축소 컨트롤러
3 + */
4 +
5 +var container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
6 +var options = { //지도를 생성할 때 필요한 기본 옵션
7 + center: new kakao.maps.LatLng(37.54, 126.96), //지도의 중심좌표.
8 + level: 7 //지도의 레벨(확대, 축소 정도)
9 +};
10 +
11 +var map = new kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
12 +
13 +// 확대 축소 컨트롤러
14 +var zoomControl = new kakao.maps.ZoomControl();
15 +map.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT);
16 +
17 +/******************************************************************************
18 + * 2. 더미데이터 준비하기(제목, 주소, 카테고리)
19 + */
20 +
21 + const dataSet = [
22 + {
23 + title: "희락돈까스",
24 + address: "서울 영등포구 양산로 210",
25 + category: "양식",
26 + },
27 + {
28 + title: "즉석우동짜장",
29 + address: "서울 영등포구 대방천로 260",
30 + category: "한식",
31 + },
32 + {
33 + title: "아카사카",
34 + address: "서울 서초구 서초대로74길 23",
35 + category: "일식",
36 + },
37 + {
38 + title: "한우만",
39 + address: "서울 서초구 서초3동 효령로 216",
40 + category: "한식",
41 + },
42 +
43 + ];
44 +
45 +
46 +/******************************************************************************
47 + * 3. 여러개 마커찍기
48 + */
49 +
50 +// 주소-좌표 변환 객체를 생성합니다
51 +var geocoder = new kakao.maps.services.Geocoder();
52 +
53 +function getCoordsByAddress(address) {
54 + return new Promise((resolve, reject) => {
55 + // 주소로 좌표를 검색합니다
56 + geocoder.addressSearch(address, function (result, status) {
57 + // 정상적으로 검색이 완료됐으면
58 + if (status === kakao.maps.services.Status.OK) {
59 + var coords = new kakao.maps.LatLng(result[0].y, result[0].x);
60 + return resolve(coords);
61 + }
62 + reject(new Error("getCoordsByAddress Error: not valid Address"));
63 + });
64 + });
65 +}
66 +
67 +setMap(dataSet);
68 +
69 +/*
70 +*************************************************************
71 +4. 마커에 인포윈도우 붙이기
72 +*/
73 +
74 +function getContent(data) {
75 + // 인포윈도우 가공하기
76 + return `
77 + <div class="infowindow">
78 + <div class="infowindow-body">
79 + <h5 class="infowindow-title">${data.title}</h5>
80 + <p class="infowindow-address">${data.address}</p>
81 + <a href='/chat' class="infowindow-btn" target="_blank">채팅방이동</a>
82 + </div>
83 + </div>
84 + `;
85 +}
86 +
87 +async function setMap(dataSet) {
88 + for (var i = 0; i < dataSet.length; i++) {
89 + // 마커를 생성합니다
90 + let coords = await getCoordsByAddress(dataSet[i].address);
91 + var marker = new kakao.maps.Marker({
92 + map: map, // 마커를 표시할 지도
93 + position: coords,
94 + });
95 +
96 + markerArray.push(marker);
97 +
98 + // 마커에 표시할 인포윈도우를 생성합니다
99 + var infowindow = new kakao.maps.InfoWindow({
100 + content: getContent(dataSet[i]),// 인포윈도우에 표시할 내용
101 + });
102 +
103 + infowindowArray.push(infowindow);
104 +
105 + // 마커에 mouseover 이벤트와 mouseout 이벤트를 등록합니다
106 + // 이벤트 리스너로는 클로저를 만들어 등록합니다
107 + // for문에서 클로저를 만들어 주지 않으면 마지막 마커에만 이벤트가 등록됩니다
108 + kakao.maps.event.addListener(marker, 'click', makeOverListener(map, marker, infowindow, coords));
109 + kakao.maps.event.addListener(map, 'click', makeOutListener(infowindow));
110 + }
111 + }
112 +
113 + // 인포윈도우를 표시하는 클로저를 만드는 함수입니다
114 +function makeOverListener(map, marker, infowindow, coords) {
115 + return function() {
116 + // 1. 클릭시 다른 인포윈도우 닫기
117 + closeInfoWindow();
118 + infowindow.open(map, marker);
119 + // 2. 클릭한 곳으로 지도 중심 옮기기
120 + map.panTo(coords);
121 + };
122 +}
123 +
124 +let infowindowArray = [];
125 +function closeInfoWindow() {
126 + for (let infowindow of infowindowArray) {
127 + infowindow.close();
128 + }
129 +}
130 +
131 +// 인포윈도우를 닫는 클로저를 만드는 함수입니다
132 +function makeOutListener(infowindow) {
133 + return function() {
134 + infowindow.close();
135 + };
136 +}
137 +
138 +/*
139 +**********************************************
140 +5. 카테고리 분류
141 +*/
142 +
143 +// 카테고리
144 +const categoryMap = {
145 + korea: "한식",
146 + china: "중식",
147 + japan: "일식",
148 + america: "양식",
149 + wheat: "분식",
150 + meat: "구이",
151 + sushi: "회/초밥",
152 + etc: "기타",
153 + };
154 +
155 +const categoryList = document.querySelector(".category-list");
156 +categoryList.addEventListener("click", categoryHandler);
157 +
158 +function categoryHandler(event) {
159 + const categoryId = event.target.id;
160 + const category = categoryMap[categoryId];
161 +
162 + // 데이터 분류
163 + let categorizedDataSet = [];
164 + for (let data of dataSet) {
165 + if (data.category === category) {
166 + categorizedDataSet.push(data);
167 + }
168 + }
169 +
170 + // 기존 마커 삭제
171 + closeMarker();
172 +
173 + // 기존 인포윈도우 닫기
174 + closeInfoWindow();
175 +
176 + setMap(categorizedDataSet);
177 +}
178 +
179 +let markerArray = [];
180 +function closeMarker() {
181 + for (marker of markerArray) {
182 + marker.setMap(null);
183 + }
184 +}
...\ No newline at end of file ...\ No newline at end of file
1 +@font-face {
2 + font-family: 'Noto Sans KR', sans-serif;
3 + src: url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@700&display=swap');
4 + font-weight: normal;
5 + font-style: normal;
6 + }
7 +
8 + * {
9 + padding: 0;
10 + margin: 0;
11 + box-sizing: border-box;
12 + }
13 +
14 + html {
15 + font-size: 10px;
16 + font-family: 'Noto Sans KR', sans-serif;
17 + }
18 +
19 + nav {
20 + /* background-color: #e69a06; */
21 + }
22 +
23 + .nav-container {
24 + padding: 1rem 0;
25 + display: flex;
26 + flex-direction: row;
27 + justify-content: space-between;
28 + align-items: center;
29 + }
30 +
31 + .nav-title {
32 + font-size: 2.5rem;
33 + color :rebeccapurple;
34 + }
35 +
36 + .nav-contact {
37 + font-size: 1.5rem;
38 + border: 0;
39 + background: none;
40 + cursor: pointer;
41 + font-family: inherit;
42 + color :lightslategray;
43 + }
44 +
45 + .category-title {
46 + font-size: 2rem;
47 + }
48 +
49 + .category-item {
50 + width: 25%;
51 + height: 5rem;
52 + background: none;
53 + border: none;
54 + font-family: inherit;
55 + font-size: 1.6rem;
56 + }
57 +
58 + .category-item:hover {
59 + color: #e69a06;
60 + cursor: pointer;
61 + }
62 +
63 + .inner {
64 + padding: 0 1.5rem;
65 + }
66 +
67 + @media all and (min-width: 1024px) {
68 + .inner {
69 + max-width: 1024px;
70 + margin: 0 auto;
71 + }
72 + }
73 +
74 + /* 카카오맵 CSS */
75 +
76 + body {
77 + height: 100vh;
78 + }
79 +
80 + nav {
81 + height: 59px;
82 + }
83 +
84 + main {
85 + padding-top: 1.5rem;
86 + height: calc(100% - 59px);
87 + display: flex;
88 + flex-direction: column;
89 + }
90 +
91 + #map {
92 + flex-grow: 1;
93 + width: 100%;
94 + height: 100%;
95 + }
...\ No newline at end of file ...\ No newline at end of file