seungmi

카카오 map api추가

카카오 map api를 이용한 검색기능 구현
...@@ -18,9 +18,9 @@ app.get(['/food', '/food/:id'], function(req, res) { ...@@ -18,9 +18,9 @@ app.get(['/food', '/food/:id'], function(req, res) {
18 var id = req.params.id; 18 var id = req.params.id;
19 if (id) { 19 if (id) {
20 if (id == 'search') { 20 if (id == 'search') {
21 - res.render('search.ejs', { 21 + res.render('map.ejs', {
22 title: 'Searching', 22 title: 'Searching',
23 - description: 'You can search for food here.' 23 + searching: '경희대학교 국제캠퍼스'
24 }); 24 });
25 } else if (id == 'recommendation') { 25 } else if (id == 'recommendation') {
26 res.render('recommendation.ejs', { 26 res.render('recommendation.ejs', {
...@@ -39,7 +39,11 @@ app.get(['/food', '/food/:id'], function(req, res) { ...@@ -39,7 +39,11 @@ app.get(['/food', '/food/:id'], function(req, res) {
39 //사용자가 호출한 search page 39 //사용자가 호출한 search page
40 app.post('/food/search', function(req, res) { 40 app.post('/food/search', function(req, res) {
41 var title = req.body.title; 41 var title = req.body.title;
42 - res.redirect("https://www.google.com/search?q=" + title + "&oq=" + title + "&aqs=chrome..69i57j0l3j69i60j69i61.3149j0j9&sourceid=chrome&ie=UTF-8") 42 + res.render('map.ejs',{
43 + title: 'Search',
44 + searching: title
45 + });
46 + // res.redirect("https://www.google.com/search?q=" + title + "&oq=" + title + "&aqs=chrome..69i57j0l3j69i60j69i61.3149j0j9&sourceid=chrome&ie=UTF-8")
43 }) 47 })
44 48
45 //사용자가 호출한 recommendation page 49 //사용자가 호출한 recommendation page
...@@ -79,7 +83,6 @@ app.post('/food/recommendation', function(req, res) { ...@@ -79,7 +83,6 @@ app.post('/food/recommendation', function(req, res) {
79 var rand = Math.floor(Math.random() * length); //(Math.random() * (max - min)) + min 83 var rand = Math.floor(Math.random() * length); //(Math.random() * (max - min)) + min
80 var food_value = food[rand]; 84 var food_value = food[rand];
81 console.log(rand); 85 console.log(rand);
82 -
83 res.render('print.ejs', { 86 res.render('print.ejs', {
84 title: 'Recommendation', 87 title: 'Recommendation',
85 description: 'We recommend this...', 88 description: 'We recommend this...',
......
1 +.map_wrap, .map_wrap * {
2 + margin: 0;
3 + padding: 0;
4 + font-family: 'Malgun Gothic', dotum, '돋움', sans-serif;
5 + font-size: 12px;
6 +}
7 +
8 +.map_wrap a, .map_wrap a:hover, .map_wrap a:active {
9 + color: #000;
10 + text-decoration: none;
11 +}
12 +
13 +.map_wrap {
14 + position: relative;
15 + width: 100%;
16 + height: 500px;
17 +}
18 +
19 +#map {
20 + top: 0;
21 + left: 0;
22 + width: 100%;
23 + height: 100%;
24 + position: relative;
25 + overflow: hidden;
26 +}
27 +
28 +#menu_wrap {
29 + position: absolute;
30 + top: 0;
31 + left:0;
32 + bottom: 0;
33 + width: 250px;
34 + margin: 10px 0 30px 10px;
35 + padding: 5px;
36 + overflow-y: auto;
37 + background: rgba(255, 255, 255, 0.7);
38 + z-index: 1;
39 + font-size: 12px;
40 + border-radius: 10px;
41 +}
42 +
43 +.bg_white {
44 + background: #fff;
45 +}
46 +
47 +#menu_wrap hr {
48 + display: block;
49 + height: 1px;
50 + border: 0;
51 + border-top: 2px solid #5F5F5F;
52 + margin: 3px 0;
53 +}
54 +
55 +#menu_wrap .option {
56 + text-align: center;
57 +}
58 +
59 +#menu_wrap .option p {
60 + margin: 10px 0;
61 +}
62 +
63 +#menu_wrap .option button {
64 + margin-left: 5px;
65 +}
66 +
67 +#placesList li {
68 + list-style: none;
69 +}
70 +
71 +#placesList .item {
72 + position: relative;
73 + border-bottom: 1px solid #888;
74 + overflow: hidden;
75 + cursor: pointer;
76 + min-height: 65px;
77 +}
78 +
79 +#placesList .item span {
80 + display: block;
81 + margin-top: 4px;
82 +}
83 +
84 +#placesList .item h5, #placesList .item .info {
85 + text-overflow: ellipsis;
86 + overflow: hidden;
87 + white-space: nowrap;
88 +}
89 +
90 +#placesList .item .info {
91 + padding: 10px 0 10px 55px;
92 +}
93 +
94 +#placesList .info .gray {
95 + color: #8a8a8a;
96 +}
97 +
98 +#placesList .info .jibun {
99 + padding-left: 26px;
100 + background: url(http://t1.daumcdn.net/localimg/localimages/07/mapapidoc/places_jibun.png) no-repeat;
101 +}
102 +
103 +#placesList .info .tel {
104 + color: #009900;
105 +}
106 +
107 +#placesList .item .markerbg {
108 + float: left;
109 + position: absolute;
110 + width: 36px;
111 + height: 37px;
112 + margin: 10px 0 0 10px;
113 + background: url(http://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png) no-repeat;
114 +}
115 +
116 +#placesList .item .marker_1 {
117 + background-position: 0 -10px;
118 +}
119 +
120 +#placesList .item .marker_2 {
121 + background-position: 0 -56px;
122 +}
123 +
124 +#placesList .item .marker_3 {
125 + background-position: 0 -102px
126 +}
127 +
128 +#placesList .item .marker_4 {
129 + background-position: 0 -148px;
130 +}
131 +
132 +#placesList .item .marker_5 {
133 + background-position: 0 -194px;
134 +}
135 +
136 +#placesList .item .marker_6 {
137 + background-position: 0 -240px;
138 +}
139 +
140 +#placesList .item .marker_7 {
141 + background-position: 0 -286px;
142 +}
143 +
144 +#placesList .item .marker_8 {
145 + background-position: 0 -332px;
146 +}
147 +
148 +#placesList .item .marker_9 {
149 + background-position: 0 -378px;
150 +}
151 +
152 +#placesList .item .marker_10 {
153 + background-position: 0 -423px;
154 +}
155 +
156 +#placesList .item .marker_11 {
157 + background-position: 0 -470px;
158 +}
159 +
160 +#placesList .item .marker_12 {
161 + background-position: 0 -516px;
162 +}
163 +
164 +#placesList .item .marker_13 {
165 + background-position: 0 -562px;
166 +}
167 +
168 +#placesList .item .marker_14 {
169 + background-position: 0 -608px;
170 +}
171 +
172 +#placesList .item .marker_15 {
173 + background-position: 0 -654px;
174 +}
175 +
176 +#pagination {
177 + margin: 10px auto;
178 + text-align: center;
179 +}
180 +
181 +#pagination a {
182 + display: inline-block;
183 + margin-right: 10px;
184 +}
185 +
186 +#pagination .on {
187 + font-weight: bold;
188 + cursor: default;
189 + color: #777;
190 +}
1 +<!DOCTYPE html>
2 +<html>
3 +
4 +<head>
5 + <meta charset="utf-8">
6 + <link rel="stylesheet" href="/../map.css">
7 + <!-- <link rel="stylesheet" href="/../style.css"> -->
8 + <title>키워드로 장소검색하고 목록으로 표출하기</title>
9 +
10 +</head>
11 +
12 +<body>
13 + <h1><a href="/food">점심 메뉴 정하기</a></h1>
14 + <div class="grid">
15 + <ul>
16 + <il><a href="/food/search">검색</a></il><br>
17 + <il><a href="/food/recommendation">추천</a></il>
18 + </ul>
19 +
20 + <article>
21 + <h2>
22 + <%= title %>
23 + </h2>
24 + <form action='/food/search' method='post'>
25 + <p>
26 + 검색 :
27 + <input type="text" name="title" placeholder="검색">
28 + <input type="submit">
29 + </p>
30 + </form>
31 + </article>
32 + </div class="grid">
33 + <div class="map_wrap">
34 + <div id="map" ></div>
35 +
36 + <div id="menu_wrap" class="bg_white">
37 + <div class="option">
38 + <div>
39 + <form onsubmit="searchPlaces(); return false;">
40 + 키워드 : <input type="text" value='<%=searching%>' id="keyword" size="15">
41 + <button type="submit">검색하기</button>
42 + </form>
43 + </div>
44 + </div>
45 + <hr>
46 + <ul id="placesList"></ul>
47 + <div id="pagination"></div>
48 + </div>
49 + </div>
50 +
51 + <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=a8a43eda451b054ac46a281a3db5d536&libraries=services"></script>
52 + <script>
53 + // 마커를 담을 배열입니다
54 + var markers = [];
55 +
56 + var mapContainer = document.getElementById('map'), // 지도를 표시할 div
57 + mapOption = {
58 + center: new kakao.maps.LatLng(37.566826, 126.9786567), // 지도의 중심좌표
59 + level: 3 // 지도의 확대 레벨
60 + };
61 +
62 + // 지도를 생성합니다
63 + var map = new kakao.maps.Map(mapContainer, mapOption);
64 +
65 + // 장소 검색 객체를 생성합니다
66 + var ps = new kakao.maps.services.Places();
67 +
68 + // 검색 결과 목록이나 마커를 클릭했을 때 장소명을 표출할 인포윈도우를 생성합니다
69 + var infowindow = new kakao.maps.InfoWindow({
70 + zIndex: 1
71 + });
72 +
73 + // 키워드로 장소를 검색합니다
74 + searchPlaces();
75 +
76 + // 키워드 검색을 요청하는 함수입니다
77 + function searchPlaces() {
78 +
79 + var keyword = document.getElementById('keyword').value;
80 +
81 + if (!keyword.replace(/^\s+|\s+$/g, '')) {
82 + alert('키워드를 입력해주세요!');
83 + return false;
84 + }
85 +
86 + // 장소검색 객체를 통해 키워드로 장소검색을 요청합니다
87 + ps.keywordSearch(keyword, placesSearchCB);
88 + }
89 +
90 + // 장소검색이 완료됐을 때 호출되는 콜백함수 입니다
91 + function placesSearchCB(data, status, pagination) {
92 + if (status === kakao.maps.services.Status.OK) {
93 +
94 + // 정상적으로 검색이 완료됐으면
95 + // 검색 목록과 마커를 표출합니다
96 + displayPlaces(data);
97 +
98 + // 페이지 번호를 표출합니다
99 + displayPagination(pagination);
100 +
101 + } else if (status === kakao.maps.services.Status.ZERO_RESULT) {
102 +
103 + alert('검색 결과가 존재하지 않습니다.');
104 + return;
105 +
106 + } else if (status === kakao.maps.services.Status.ERROR) {
107 +
108 + alert('검색 결과 중 오류가 발생했습니다.');
109 + return;
110 +
111 + }
112 + }
113 +
114 + // 검색 결과 목록과 마커를 표출하는 함수입니다
115 + function displayPlaces(places) {
116 +
117 + var listEl = document.getElementById('placesList'),
118 + menuEl = document.getElementById('menu_wrap'),
119 + fragment = document.createDocumentFragment(),
120 + bounds = new kakao.maps.LatLngBounds(),
121 + listStr = '';
122 +
123 + // 검색 결과 목록에 추가된 항목들을 제거합니다
124 + removeAllChildNods(listEl);
125 +
126 + // 지도에 표시되고 있는 마커를 제거합니다
127 + removeMarker();
128 +
129 + for (var i = 0; i < places.length; i++) {
130 +
131 + // 마커를 생성하고 지도에 표시합니다
132 + var placePosition = new kakao.maps.LatLng(places[i].y, places[i].x),
133 + marker = addMarker(placePosition, i),
134 + itemEl = getListItem(i, places[i]); // 검색 결과 항목 Element를 생성합니다
135 +
136 + // 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해
137 + // LatLngBounds 객체에 좌표를 추가합니다
138 + bounds.extend(placePosition);
139 +
140 + // 마커와 검색결과 항목에 mouseover 했을때
141 + // 해당 장소에 인포윈도우에 장소명을 표시합니다
142 + // mouseout 했을 때는 인포윈도우를 닫습니다
143 + (function(marker, title) {
144 + kakao.maps.event.addListener(marker, 'mouseover', function() {
145 + displayInfowindow(marker, title);
146 + });
147 +
148 + kakao.maps.event.addListener(marker, 'mouseout', function() {
149 + infowindow.close();
150 + });
151 +
152 + itemEl.onmouseover = function() {
153 + displayInfowindow(marker, title);
154 + };
155 +
156 + itemEl.onmouseout = function() {
157 + infowindow.close();
158 + };
159 + })(marker, places[i].place_name);
160 +
161 + fragment.appendChild(itemEl);
162 + }
163 +
164 + // 검색결과 항목들을 검색결과 목록 Elemnet에 추가합니다
165 + listEl.appendChild(fragment);
166 + menuEl.scrollTop = 0;
167 +
168 + // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다
169 + map.setBounds(bounds);
170 + }
171 +
172 + // 검색결과 항목을 Element로 반환하는 함수입니다
173 + function getListItem(index, places) {
174 +
175 + var el = document.createElement('li'),
176 + itemStr = '<span class="markerbg marker_' + (index + 1) + '"></span>' +
177 + '<div class="info">' +
178 + ' <h5>' + places.place_name + '</h5>';
179 +
180 + if (places.road_address_name) {
181 + itemStr += ' <span>' + places.road_address_name + '</span>' +
182 + ' <span class="jibun gray">' + places.address_name + '</span>';
183 + } else {
184 + itemStr += ' <span>' + places.address_name + '</span>';
185 + }
186 +
187 + itemStr += ' <span class="tel">' + places.phone + '</span>' +
188 + '</div>';
189 +
190 + el.innerHTML = itemStr;
191 + el.className = 'item';
192 +
193 + return el;
194 + }
195 +
196 + // 마커를 생성하고 지도 위에 마커를 표시하는 함수입니다
197 + function addMarker(position, idx, title) {
198 + var imageSrc = 'http://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png', // 마커 이미지 url, 스프라이트 이미지를 씁니다
199 + imageSize = new kakao.maps.Size(36, 37), // 마커 이미지의 크기
200 + imgOptions = {
201 + spriteSize: new kakao.maps.Size(36, 691), // 스프라이트 이미지의 크기
202 + spriteOrigin: new kakao.maps.Point(0, (idx * 46) + 10), // 스프라이트 이미지 중 사용할 영역의 좌상단 좌표
203 + offset: new kakao.maps.Point(13, 37) // 마커 좌표에 일치시킬 이미지 내에서의 좌표
204 + },
205 + markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imgOptions),
206 + marker = new kakao.maps.Marker({
207 + position: position, // 마커의 위치
208 + image: markerImage
209 + });
210 +
211 + marker.setMap(map); // 지도 위에 마커를 표출합니다
212 + markers.push(marker); // 배열에 생성된 마커를 추가합니다
213 +
214 + return marker;
215 + }
216 +
217 + // 지도 위에 표시되고 있는 마커를 모두 제거합니다
218 + function removeMarker() {
219 + for (var i = 0; i < markers.length; i++) {
220 + markers[i].setMap(null);
221 + }
222 + markers = [];
223 + }
224 +
225 + // 검색결과 목록 하단에 페이지번호를 표시는 함수입니다
226 + function displayPagination(pagination) {
227 + var paginationEl = document.getElementById('pagination'),
228 + fragment = document.createDocumentFragment(),
229 + i;
230 +
231 + // 기존에 추가된 페이지번호를 삭제합니다
232 + while (paginationEl.hasChildNodes()) {
233 + paginationEl.removeChild(paginationEl.lastChild);
234 + }
235 +
236 + for (i = 1; i <= pagination.last; i++) {
237 + var el = document.createElement('a');
238 + el.href = "#";
239 + el.innerHTML = i;
240 +
241 + if (i === pagination.current) {
242 + el.className = 'on';
243 + } else {
244 + el.onclick = (function(i) {
245 + return function() {
246 + pagination.gotoPage(i);
247 + }
248 + })(i);
249 + }
250 +
251 + fragment.appendChild(el);
252 + }
253 + paginationEl.appendChild(fragment);
254 + }
255 +
256 + // 검색결과 목록 또는 마커를 클릭했을 때 호출되는 함수입니다
257 + // 인포윈도우에 장소명을 표시합니다
258 + function displayInfowindow(marker, title) {
259 + var content = '<div style="padding:5px;z-index:1;">' + title + '</div>';
260 +
261 + infowindow.setContent(content);
262 + infowindow.open(map, marker);
263 + }
264 +
265 + // 검색결과 목록의 자식 Element를 제거하는 함수입니다
266 + function removeAllChildNods(el) {
267 + while (el.hasChildNodes()) {
268 + el.removeChild(el.lastChild);
269 + }
270 + }
271 + </script>
272 +</body>
273 +
274 +</html>