본문 바로가기
Develop/JSP

핫플 페이지 마무리 겸 정리하기 (2)

by ys2ys2 2024. 10. 6.

페이지 구성

(1)에 이어서 (2)도 시작!

 

5. 이미지 부분

이미지 부분은 공공데이터 API를 사용해서 저장한 firstimage 값들을 가져와서 나오게 했다.

근데 이미지를 세로로 나열하면 깔끔하지도 않고 보기도 불편해서 슬라이드 형식으로 꾸몄다.

 

간단하게 https://swiperjs.com 에서 괜찮은 demo 찾아서 사용했다.

Thumbs gallery loop

 

사용법은 엄청 간단하다! 메인 페이지 만들때도 썼는데 편하다. 리액트의 npm install slick slider 같은 느낌?

상단의 Core 눌러서 들어가면 소스코드를 다 준다! 근데 이름 바꾸면 안되고 정해진 대로 써야지 되는거 같다.

상단에 script도 추가해야지 사용할 수 있다.

<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
<!-- 사진 보기 섹션 (메인 슬라이드) -->
<div id="section-photos" class="h_content">
    <div class="swiper mySwiper2">
      <div class="swiper-wrapper">
        <c:forEach var="item" items="${itemList}">
          <c:set var="imageArray" value="${fn:split(item.firstimage, ',')}" />
          <c:forEach var="imgUrl" items="${imageArray}">
            <div class="swiper-slide">
              <img src="${fn:trim(imgUrl)}" alt="핫플 이미지" />
            </div>
          </c:forEach>
        </c:forEach>
      </div>
     <!-- 슬라이드 좌,우 이미지 버튼 -->
     <button class="custom-next-button">
       <img src="../images/right_arrow.png" alt="다음">
     </button>
     <button class="custom-prev-button">
       <img src="../images/left_arrow.png" alt="이전">
     </button>
     </div>

    <!-- Swiper 썸네일 추가 -->
    <div thumbsSlider="" class="swiper mySwiper">
      <div class="swiper-wrapper">
        <c:forEach var="item" items="${itemList}">
          <c:set var="imageArray" value="${fn:split(item.firstimage, ',')}" />
          <c:forEach var="imgUrl" items="${imageArray}">
            <div class="swiper-slide">
              <img src="${fn:trim(imgUrl)}" alt="핫플 썸네일 이미지" />
            </div>
          </c:forEach>
        </c:forEach>
      </div>
    </div>
</div>

 

원래 기본으로 주는 화살표 버튼은 커스텀해서 동그라미 화살표 이미지로 바꿨다.

누를때마다 다음 이미지로 변경되고 밑에 썸네일에 해당하는 이미지에 색이 진해진다!

지금 이미지들이 DB에 http://~, http://~, http://~, 식으로 저장이 되어있다.

http://tong.visitkorea.or.kr/cms/resource/09/3008609_image2_1.jpg,
http://tong.visitkorea.or.kr/cms/resource/04/3008604_image2_1.jpg,
http://tong.visitkorea.or.kr/cms/resource/05/3008605_image2_1.jpg,
http://tong.visitkorea.or.kr/cms/resource/06/3008606_image2_1.jpg,
http://tong.visitkorea.or.kr/cms/resource/07/3008607_image2_1.jpg,
http://tong.visitkorea.or.kr/cms/resource/12/3008612_image2_1.jpg

 

쉼표로 나눠서 배열 형태로 imageArray를 만들고

<c:set var="imageArray" value="${fn:split(item.firstimage, ',')}" />

 

<c:forEach> 를 통해서 이미지들에 대한 반복문을 돌리고 imgUrl에 저장시켰다.

<c:forEach var="imgUrl" items="${imageArray}">

 

 

fn:trim(imgUrl)을 쓰면서 fn:trim(imgUrl)을 배웠는데 imgUrl 앞 뒤에 공백을 제거한다고 했다. (불필요한 공백 삭제)

<img src="${fn:trim(imgUrl)}" alt="핫플 이미지" />

 

같은 방식으로 밑에 썸네일 부분도 했다!

결과는??!

이미지 부분

 

요렇게 완성!

 

6. 설명 부분

설명 부분은 DB에 저장된 overview값을 가져왔다.

<div class="h_details">
    <c:forEach var="item" items="${itemList}">
        <p id="description-text">${item.overview}</p>
    </c:forEach>
</div>

 

그냥 위에서 저장해둔 overview값 가져오기

String sql = "SELECT title, addr1, overview, firstimage, mapx, mapy FROM hotplace LIMIT 1 OFFSET 2";

 

근데 문제는 overview 글자들이 그냥 그대로 쭉 써진다. 

본문이 그냥 출력

 

뭔가 보기 불편하고 그래서 점 두개마다 <br>을 하나씩 넣어줬다. javascript 사용!

  document.addEventListener("DOMContentLoaded", function() {
      // description-text 요소 가져오기
      var descriptionElement = document.getElementById("description-text");

      // 텍스트 가져오기
      var descriptionText = descriptionElement.innerText;

      // 점('.')을 기준으로 텍스트를 분할하고, 각 문장을 트림하여 배열로 변환
      var sentences = descriptionText.split('.').map(function(sentence) {
          return sentence.trim();
      });

      // 배열을 돌면서 두 번째 문장마다 줄바꿈을 추가
      var formattedText = "";
      sentences.forEach(function(sentence, index) {
          if (sentence !== "") { // 빈 문장은 무시
              formattedText += sentence;
              if ((index + 1) % 2 === 0) {
                  formattedText += ".<br>"; // 두 번째 문장마다 줄바꿈 추가
              } else if (index < sentences.length - 1) {
                  formattedText += ". "; // 그 외에는 그냥 점 추가
              }
          }
      });

 

결과는?

그럭저럭 괜찮은듯..?

 

이렇게 패스!

 

7. 지도API

지도API

 

지도 API는 구글을 사용했다. 지금 보여지는건 완성된 상태!

 

구글 맵을 추가하는건 쉬웠다.

<script src="https://maps.googleapis.com/maps/api/js?key="내 구글맵 키"&callback=initMap" async defer></script>

<!-- 구글 맵 -->
<div id="map" class="h_map">
  <div class="google_map"></div>
</div>

 

스크립트 추가하고 구글 맵 넣고 js 만들기

window.initMap = function() {

}

 

처음에는 공공데이터 api에서 주소값을 주니까 그 주소값을 가지고 마커를 찍으려고 했다.

그렇게 하다가 알게 된 지오코딩! 구글에서 지원해주고 주소값 → 위도,경도로 바꿔주는 기능이다.

반대로 역지오코딩은 위도,경도 → 주소값 이라고 한다.

 

근데 공공데이터에 위도,경도를 다 주니까 js에 위도,경도 부분을 변수로 두고

jsp → js 넘길때 db에 저장된 위도,경도 값을 넘기게 하려고 했다.

 

window.initMap = function() {
    // mapx와 mapy 변수가 정의되어 있는지 확인
	    if (typeof mapx !== 'undefined' && typeof mapy !== 'undefined' && mapx && mapy) {
	        // 위도와 경도 설정
	        var latitude = parseFloat(mapy);
	        var longitude = parseFloat(mapx);

	        // 쉼표로 구분된 첫 번째 이미지 URL 가져오기
	        var firstImageUrl = firstimage.trim();

	        // 지도 초기화
	        var mapOptions = {
	            center: { lat: latitude, lng: longitude },
	            zoom: 16
	        };

	        var map = new google.maps.Map(document.getElementById('map'), mapOptions);

	        // 기본 빨간 마커 추가
	        var basicMarker = new google.maps.Marker({
	            position: { lat: latitude, lng: longitude },
	            map: map,
	            title: '선택된 장소'
	        });

	        // 커스텀 마커 추가
	        addCustomMarker(map, latitude, longitude, firstImageUrl);
	    } else {
	        console.error('위도와 경도 값이 없습니다. mapx, mapy값을 확인해주세요.');
	    }
	};
    
    //위도,경도로 지도 표시 + imageUrl
function displayMap(latitude, longitude, imageUrl) {
    var mapOptions = {
        center: { lat: latitude, lng: longitude }, // 위도와 경도 값을 중심으로 설정
        zoom: 16 // 지도 확대 레벨 설정
    };

    // 'map' ID를 가진 요소에 지도를 삽입
    var map = new google.maps.Map(document.getElementById('map'), mapOptions);
	
	};

 

이런식으로 위도, 경도를 받아서 지도에 넣어서 위치를 잡고, 마커도 찍어줬다.

그리고 firstImageUrl 값도 1개 받아서 마커 위에 썸네일 처럼 쓰려고 했다.

이렇게 item값으로 저장해둔 mapx, mapy값과 공백 제거한 firstimage중 첫번째[0] 배열만 가져가게 했다.

<script>
    <c:forEach var="item" items="${itemList}" varStatus="status">
        if (${status.first}) {
            mapx = parseFloat("${item.mapx}");
            mapy = parseFloat("${item.mapy}");
            firstimage = '${fn:split(item.firstimage, ",")[0]}'; // DB의 쉼표중 첫번째[0] 이미지만 가져오기
        }
    </c:forEach>
</script>

 

그러고 커스텀 마커로 js를 추가했다.

// 커스텀 마커를 추가하는 함수
function addCustomMarker(map, latitude, longitude, imageUrl) {
    // 커스텀 마커를 위한 HTML 엘리먼트 생성
    var markerDiv = document.createElement('div');
    markerDiv.className = 'custom-marker';

    // 마커 안에 들어갈 이미지 엘리먼트 생성
    var imgElement = document.createElement('img');
    imgElement.src = imageUrl;
    imgElement.className = 'marker-image';

    // 마커 이미지와 스타일링된 배경을 포함한 div에 추가
    markerDiv.appendChild(imgElement);

    // 지도에 커스텀 마커 오버레이 추가
    var customMarker = new google.maps.OverlayView();
    customMarker.onAdd = function() {
        var panes = this.getPanes();
        panes.overlayMouseTarget.appendChild(markerDiv);
    };
    customMarker.draw = function() {
        var position = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(latitude, longitude));
        markerDiv.style.left = position.x + 'px';
        markerDiv.style.top = position.y + 'px';
    };
    customMarker.onRemove = function() {
        markerDiv.parentNode.removeChild(markerDiv);
    };
    customMarker.setMap(map);
}

 

지도API

 

어찌저찌 완성.. 근데 새로고침할때 가끔 안나올때가 있다.. 왜그러지?

 

8. 여행톡

은 여기를 참고하세요! 여기서 다 정리해놨습니다?

 

https://ys2ys2.tistory.com/17

 

페이지 댓글 구현하기

DB 부분은 어느정도 끝나서 (최종이라고 올렸지만 수정할게 아직 더 남았다..)'여행톡' 이라는 부분을 구현해 보려고 한다. - 현재까지 진행 상황 -  inputApi를 통해 테이블에 저장된 값으로제목 :

ys2ys2.tistory.com

 

이렇게 어느정도 맡은 페이지를 완성시켰다.. 이제 5%정도는 중간중간 생각날때 추가하고 하는 정도만 하면 될 것 같다!!

(+ 카카오 로그인, 네이버 로그인, 구글 로그인 값 받아서 게시글 쓸 수 있게 하기! 이건 이메일 로그인으로 해봤으니까 금방 하겠지!)

 

다음은 메인 페이지 마무리 작업을 해야한다! 2차 끝나기 전까지 헛둘헛둘🏃‍♂️ 하면 금방 하겠지!!