토이프로젝트(4)- 주변 맛집
728x90

하루에 두번 나눠서 올린다.

 

이번에는 검색을 했을 때 지도 안에 마커들의 리스트를 표현 해줬다. 다시 한번 말하지만 공식 가이드문서에 나와있는데로 만들어봤다.

 

나머지 기능들은 고민하면서 만들어 봐야겠다... css나 이런게 부족해서 화면을 잘 못띄울거 같다...

 

keyWordSearch () {
      this.isOk = true
      // 마커를 담을 배열
      var markers = []

      const container = document.getElementById('map')// 지도를 표시할 div
      const options = {
        center: new kakao.maps.LatLng(33.664, 6.890),
        level: 10
      }

      const map = new kakao.maps.Map(container, options)

      const ps = new kakao.maps.services.Places()

      const infowindow = new kakao.maps.InfoWindow({ zIndex: 1 })

      searchPlaces(this.keyWord)

      function searchPlaces (keyWord) {
        const keyword = keyWord

        if (!keyword.replace(/^\s+|\s+$/g, '')) {
          alert('키워드를 입력해주세요!')
          return false
        }
        ps.keywordSearch(keyword + '맛집', placesSearchCB)
      }
      // 장소 검색이 완료되었을때 호출되는 콜백함수
      function placesSearchCB (data, status, pagination) {
        if (status === kakao.maps.services.Status.OK) {
          // 정상적으로 검색이 완료됐으면 검색 목록과 마커를 표출합니다.
          displayPlaces(data)
          // 페이지 번호를 표출한다
          displayPagination(pagination)
        } else if (status === kakao.maps.services.Status.ERROR) {
          alert('검색 결과 중 오류가 발생했습니다.')
        }
      }
      function displayPlaces (places) {
        const listEl = document.getElementById('placesList')
        const menuEl = document.getElementById('menu_wrap')
        const fragment = document.createDocumentFragment()
        const bounds = new kakao.maps.LatLngBounds()

        // 검색 결과 목록에 추가된 항목들을 제거한다.
        removeAllChildNods(listEl)
        // 지도에 표시되고 있는 마커를 제거
        removeMarker()

        for (let i = 0; i < places.length; i++) {
          // 마커를 생성하고 지도에 표시한다.
          const placePosition = new kakao.maps.LatLng(places[i].y, places[i].x)
          const marker = addMarker(placePosition, i)
          const itemEl = getListItem(i, places[i]) // 검색결과 항목 Element를 생성

          // 검색된 장소 위치를 기준으로 지도 범위를 재설정 하기 위해 LatLngBounds 객체에 좌표를 추가
          bounds.extend(placePosition);

          // 마커와 검색결과 항목에 mouseover 했을때 해당 장소에 인포윈도우에 장소명을 표시, mouseout했을때 인포윈도우 닫음
          (function (marker, title) {
            kakao.maps.event.addListener(marker, 'mouseover', function () {
              displayInfowindow(marker, title)
            })
            kakao.maps.event.addListener(marker, 'mouseout', function () {
              infowindow.close()
            })
            itemEl.onmouseover = function () {
              displayInfowindow(marker, title)
            }
            itemEl.onmouseout = function () {
              infowindow.close()
            }
          })(marker, places[i].place_name)

          fragment.appendChild(itemEl)
        }
        // 검색결과 항목들을 검색결과 목록 Elemnet에 추가합니다
        listEl.appendChild(fragment)
        menuEl.scrollTop = 0

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

      // 검색결과 항목을 Element로 반환하는 함수입니다
      function getListItem (index, places) {
        var el = document.createElement('li')
        var itemStr = '<span class="markerbg marker_' + (index + 1) + '"></span>' +
                '<div class="info" style="background-color:white;">' +
                '   <h5>' + places.place_name + '</h5>'

        if (places.road_address_name) {
          itemStr += '    <span>' + places.road_address_name + '</span>' +
                    '   <span class="jibun gray">' + places.address_name + '</span>'
        } else {
          itemStr += '    <span>' + places.address_name + '</span>'
        }

        itemStr += '  <span class="tel">' + places.phone + '</span>' +
                '</div>'

        el.innerHTML = itemStr
        el.className = 'item'

        return el
      }

      // 마커를 생성하고 지도 위에 마커를 표시하는 함수입니다
      function addMarker (position, idx, title) {
        var imageSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png' // 마커 이미지 url, 스프라이트 이미지를 씁니다
        var imageSize = new kakao.maps.Size(36, 37) // 마커 이미지의 크기
        var imgOptions = {
          spriteSize: new kakao.maps.Size(36, 691), // 스프라이트 이미지의 크기
          spriteOrigin: new kakao.maps.Point(0, (idx * 46) + 10), // 스프라이트 이미지 중 사용할 영역의 좌상단 좌표
          offset: new kakao.maps.Point(13, 37) // 마커 좌표에 일치시킬 이미지 내에서의 좌표
        }
        var markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imgOptions)
        var marker = new kakao.maps.Marker({
          position: position, // 마커의 위치
          image: markerImage
        })

        marker.setMap(map) // 지도 위에 마커를 표출합니다
        markers.push(marker) // 배열에 생성된 마커를 추가합니다

        return marker
      }

      // 지도 위에 표시되고 있는 마커를 모두 제거합니다
      function removeMarker () {
        for (var i = 0; i < markers.length; i++) {
          markers[i].setMap(null)
        }
        markers = []
      }

      // 검색결과 목록 하단에 페이지번호를 표시는 함수입니다
      function displayPagination (pagination) {
        var paginationEl = document.getElementById('pagination')
        var fragment = document.createDocumentFragment()
        var i

        // 기존에 추가된 페이지번호를 삭제합니다
        while (paginationEl.hasChildNodes()) {
          paginationEl.removeChild(paginationEl.lastChild)
        }

        for (i = 1; i <= pagination.last; i++) {
          var el = document.createElement('a')

          if (i === pagination.current) {
            el.className = 'on'
          } else {
            el.onclick = (function (i) {
              return function () {
                pagination.gotoPage(i)
              }
            })(i)
          }

          fragment.appendChild(el)
        }
        paginationEl.appendChild(fragment)
      }

      // 검색결과 목록 또는 마커를 클릭했을 때 호출되는 함수입니다
      // 인포윈도우에 장소명을 표시합니다
      function displayInfowindow (marker, title) {
        var content = '<div style="padding:5px;z-index:1;">' + title + '</div>'

        infowindow.setContent(content)
        infowindow.open(map, marker)
      }

      // 검색결과 목록의 자식 Element를 제거하는 함수입니다
      function removeAllChildNods (el) {
        while (el.hasChildNodes()) {
          el.removeChild(el.lastChild)
        }
      }
    }
728x90