캠핑장 찾기 사이트

박경준·2021년 6월 6일
0

Toy Project

목록 보기
1/1

api 데이터를 이용해 만든 첫 사이트...!

공개 api의 데이터를 mongoDB를 이용해 저장

  • db_save.py
response = requests.get(url_items) # requests 를 사용해 get요청(Request)하기

dict = json.loads(response.text) # 파이썬 형식에 맞게 디코딩을 해줘야함 (json이라는 내장 라이브러리를 사용하여 디코딩)


for camp_item in camp_info:
    address = camp_item['addr1']
    ...
    # 사용하고자 하는 Value를 변수화 함.

	doc = {
	    'address': address,
	    ...
   	}
   	# DB에 넣기 위해 딕셔너리 형태로 다시 저장
   
   	db.camping_site.insert_one(doc)
   	# DB에 저장

서버를 생성하고, 클라이언트에 응답을 보내줄 POST 코드 작성

  • app.py
@app.route('/list', methods=['POST'])
def camping_info():
    sido_receive = request.form['sido_give']
    # 클라이언트에서 전달받은 지역을 의미하는 sido_give를 서버에서 저장.

    if sido_receive == '서울':
        regex = '^' + sido_receive
    elif sido_receive == '충청':
        regex = '^충청|충남|충북'
    ...
    # 파이썬 정규표현식을 사용하여, regex라는 변수에 '지역명'을 넣는다.

    real_address = list(db.camping_site.find({'address': {'$regex': regex, '$options': 'i'}}, {'_id': 0}))
    # db에서 address가 regex인 데이터들을 가져옴.

    return jsonify({'result': 'success', 'list': real_address})
    #  성공 여부 & 캠핑장 목록 반환하기

카카오 지도 불러오기

  • index.html
<script src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=2278501db03cc9b91e0a5d5345025fa2&libraries=clusterer"></script>
<!-- appkey= 부분에 받은 javascript인증키를 넣어준다. (내 key는 왜 에러가 나지...) -->
<script>
  var container = document.getElementById('map');
  var options = {
    center: new kakao.maps.LatLng(37.59029757506694, 127.10029414904892), // 지도의 중심좌표
    level: 12 // 지도의 zoom 정도
  };

  // 지도를 생성한다
  var map = new kakao.maps.Map(container, options);
</script>

클러스터러로 좌표 찍기 (클러스터러를 사용하기 위해서는 마커 객체를 생성해줘야함)

  • index.html
// 클러스터러 객체 생성
var clusterer = new kakao.maps.MarkerClusterer({
                    map: map, // 마커들을 클러스터로 관리하고 표시할 지도 객체
                    averageCenter: true, // 클러스터에 포함된 마커들의 평균 위치를 클러스터 마커 위치로 설정
                    minLevel: 10 // 클러스터 할 최소 지도 레벨
                });
function onclickSearch() {

  let sido_val = $('#sido').val()

  $.ajax({
    type: "POST",
    url: "/list",
    data: {sido_give: sido_val},
    success: function (response) {
      if (response["result"] == "success") {
        clusterer.clear(); // 직전 검색값을 누적해서 보여주지 않기 위해 응답을 받아오면서 clusterer 초기화

        let list = response.list;
        let markers = [];

        for (let i = 0; i < list.length; i++) {
          let camp_address = list[i].address;
          ...
          // 클라이언트에서 DB의 값들을 재사용하기 위해 변수화

          let markerPosition = new kakao.maps.LatLng(camp_X, camp_Y);
          // 마커가 표시될 위치.(데이터 베이스에서 위도,경도 camp_X :위도 , camp_Y :경도)
          let marker = new kakao.maps.Marker({
            position: markerPosition,
            clickable: true
          });

          markers.push(marker);

        }
        
        clusterer.addMarkers(markers);
      }
    }
  })
}

마커를 클릭했을때, 인포윈도우 생성하기

  • index.html
let infoWindows = [];

let iwContent = `<div class="info_window" style="max-width: 70vw; max-height: 75vh; overflow: scroll; padding: 11px; border : 1px solid black; background-color: gainsboro;">
  <div class="image_box" style="display: flex; justify-content: center; align-items: center;">
  <img src="${url_image}" style="width : 65vw;" alt=""></div>

  <h1 style="font-size : 16px;">${camp_name}</h1>
  <p style="font-size : 12px; color : dimgrey" >${camp_address}</p>
  <p style="font-size : 12px; color : dimgrey" >${phone}</p>
  <p style="font-size : 12px; color : dimgrey" >${feature}</p>
  <p style="font-size : 12px; color : dimgrey" >${intro}</p>
  <a href="${homepage}" target="blank" style="font-size : 12px; color : dodgerblue" >${homepage}</a>
  </div>`

let iwPosition = new kakao.maps.LatLng(camp_X, camp_Y); // 인포윈도우 표시 위치.

let infowindow = new kakao.maps.InfoWindow({ // 인포윈도우 객체 생성
  position : iwPosition,
  content : iwContent,
  removable : true
});

for (let i = 0; i < list.length; i++) {
  ...
  infowindow.setZIndex(1); // 인포윈도우를 띄운 후 마커가 생성되었을때, 마커가 인포윈도우 위로 보이는 현상 방지.
  infoWindows.push(infowindow)
}

for (let i = 0; i < markers.length; i++) {
  kakao.maps.event.addListener(markers[i], 'click', function () {
    // 이미 띄워져있는 인포윈도우를 지워야하는데 해당 인포윈도우를 특정하는게 어려우니, 모든 인포윈도우(이미 닫혀져있는 인포윈도우 포함)를 닫아줌.
    infoWindows.forEach(function (infowindow, index) {
      infowindow.close();
    });

    // 마커 위에 인포윈도우를 표시. markers[i]를 이용해 어느 마커 위에 인포윈도우를 띄울지를 특정지음.
    infoWindows[i].open(map, markers[i]);
  });
}

찾기 버튼을 눌렀을때 지도의 중심을 클러스터러로 aim 하도록 설정

  • index.html
let total_X = 0;
let total_Y = 0;

for (let i = 0; i < list.length; i++) {
  ...
  total_X += parseFloat(camp_X);
  total_Y += parseFloat(camp_Y);
  // 클러스터러의 좌표를 알려주는 메서드가 없었음.
  // 때문에 list의 모든 X, Y좌표의 평균 직접 구해서 지도 중심 aim으로 설정해줘야 함.
  // 여기서 api의 mapX, mapY 데이터가 string 형인 것이 있음;;
  // 때문에 parseFloat으로 연산이 가능하도록 변경해줘야함 (공개 api의 데이터는 깨끗하지 않으므로 항상 검수를 해봐야함...)
}

let average_X = total_X / markers.length
let average_Y = total_Y / markers.length

// 이동할 위도 경도 위치를 생성
var moveLatLon = new kakao.maps.LatLng(average_X, average_Y);

// 지도 중심을 이동!
map.setCenter(moveLatLon);

fullpage.js를 이용해 모바일 화면에서의 사용성 증대

  • index.html

    fullpage.js 공식사이트에서 파일 다운받은 후 static 폴더!!!에 저장

<link rel="stylesheet" href="./static/fullpage.min.css" />
<script src="./static/fullpage.min.js"></script>

<div id="fullpage">
  <div class="section active">
    지역 검색
  </div>
  <div class="section">
    지도
  </div>
</div>
  
<script>
  $(document).ready(function() {
    new fullpage('#fullpage', {
      licenseKey: '', // key가 따로 없어도 되는듯..?
      navigation: true, // 화면 우측 버튼
      anchors: ['sec1', 'sec2'], // 각 네비 버튼의 앵커 설정
      normalScrollElements: '.map_search > #map' // 지도 위에서 zoom을 위한 드래그 동작 시 fullpage 스크롤 이동이 안되도록 하는 설정
    });
  });
</script>

참고 페이지

profile
빠굥

0개의 댓글