[Java Script & CSS] 페이지네이션 스크롤 인터렉티브 구현! (Pagination, Scroll Animation / Interactive)
Language/Java Script

[Java Script & CSS] 페이지네이션 스크롤 인터렉티브 구현! (Pagination, Scroll Animation / Interactive)

반응형
js와 css로 페이지네이션, 스크롤 인터렉티브를 만들어보자!

 

목표 Goal💨

  • 버튼으로 페이지 이동
  • 스크롤로 페이지 이동
  • 네비게이션 요소로 페이지 이동
  • 현재 페이지 표시
  • 페이지 이동시 배경화면, 이미지, 프로그래스바(Progress Bar) 부드럽게 변경(트렌지션)

 

Preview

👍여기 클릭

 

HTML

html은 간단한 태그들로 구성됩니다. 목표에서 설명한 것들을 구현하기 위한 요소들을 생성해줍니다.

  • 이전, 다음 페이지로 이동하는 버튼과 Progress Bar를 작성하고, 그에 맞는 클래스 이름을 지정합니다.
  • section 태그는 각 페이지별로 보여줄 내용을 포함합니다. 페이지 번호(혹은 제목), 내용, 이미지로 구성했습니다.
  • ul태그는 네비게이션 역할을 하기 위해 page수(section수) 와 동일하게 만들어 줍니다.
<body>
    <ul class="pointer">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    
    <div class="navi">
        <button class="preBtn">PREV</button>
        <button class="nextBtn">NEXT</button>
        <div class="progressBar"></div>
        <h1><span>1</span> 페이지 입니다.</h1>
    </div>

    <section>
        <h2>page 1</h2>
        <p>~~설명~~</p>
        <img src="~원하는 사진~" alt="">
    </section>

    <section>
        <h2>page 2</h2>
        <p>~~설명~~</p>
        <img src="~원하는 사진~" alt="">
    </section>

    <section>
        <h2>page 3</h2>
        <p>~~설명~~</p>
        <img src="~원하는 사진~" alt="">
    </section>

    <section>
        <h2>page 4</h2>
        <p>~~설명~~</p>
        <img src="~원하는 사진~" alt="">
    </section>
</body>

 

CSS

아래 주석에 자세한 설명을 참고해주세요!

      • 부드럽게 변경할 요소들, 애니메이션을 주고 싶은 요소들에는transition을 작성하여, 애니메이션 효과를 줄 수 있습니다.
        • all : 해당 클래스(혹은 태그)에서 일어나는 모든 변화에 대해 적용한다는 뜻입니다.
        • 1s : 변화 효과가 1초 지속(소수점 단위도 설정 가능)
        • ease-in-out : 가감속 효과, 속도의 변화량 조절. 다양한 옵션을 여기서 확인 가능!
      • positionfixed 로 요소를 고정 위치에 둘 수 있습니다
<style>
  body {
    transition: all 1s ease-in-out;
    overflow-x: hidden; /* 넘치는거 안보이게 함 */
  }

  section img{
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%); /* 축이 좌상단이라 중앙으로 이동 */
    height: 300px;
    opacity: 0;
    transition: all 1s ease-in-out;
  }

  section.active img { /* section에 active라는 class가 있을때 img의 스타일 */
  	opacity: 1;
  }

  .navi {
    position: fixed;
    left: 50%;
    top: 25%;
    transform: translate(-50%, -50%);
    z-index: 100;
  }

  button {
    font-size: 20px;
    padding: 10px 30px;
    cursor: pointer;
  }

  section {
    position: relative;
    height: 100vh; /* 전체 화면 꽉 채우기 */
    width: 100vw; /* 전체 화면 꽉 채우기 */
    border-top: dashed 2px black
  }

  .pointer {
    position: fixed;
    right: 3vw;
    top: 40%;
    z-index: 100;
  }

  li {
    list-style: none;
    width: 12px;
    height: 12px;
    margin-top: 15px;
    cursor: pointer;
    background-color: #666;
    border-radius: 50%;
    transition: background 1s ease-out;
  }

  li.active {
  	background-color: rgb(15, 15, 15);
  }

  .progressBar {
    margin-top: 20px;
    background-color: black;
    height: 5px;
    border-radius: 5px;
    text-align: start;
    width: 10%;
    transition: all .1s ease-out;
  }
</style>

 

Java Script

    • pageChange() : 변경된 페이지 번호를 span 태그에 반영하고, 배경 색상 변경, pageNum에 해당하는 이미지만 보이게 하기, pageNum에 해당하는 네비게이션만 진한색으로 하기, 스크롤값에 맞게 프로그래스바 변경하기
    • pageChangeBtn() : 버튼으로 이동한 경우 한번에 여러 스크롤을 뛰어 넘어야 해서 필요. pageNum에 해당하는 section의 Top으로 스크롤 부드럽게 이동하기
  • 스크롤 이벤트 : 스크롤값을 감지하여 페이지의 중간이상을 넘어가면 pageNum을 바꾸고, pageChange() 실행하기
<script>
    window.onload = function(){
        const preBtn = document.querySelector(".preBtn")
        const nextBtn = document.querySelector(".nextBtn")
        const span = document.querySelector('span')
        const bgColor = ["#E99497", "#F3C583", "#E8E46E", "#CDF0EA"]
        const section = document.querySelectorAll('section')
        const body = document.querySelector('body')
        const img = document.querySelector('img')
        const li = document.querySelectorAll('li')
        const progressBar = document.querySelector('.progressBar')
        const scrollHeight = body.scrollHeight

        let pageNum = 0 // 페이지 인덱스 0~3, 페이지는 1~4
        const totalNum = section.length // 전체 길이

        preBtn.addEventListener('click', function() {
            if (pageNum > 0) {
                pageNum --
                pageChange()
                pageChangeBtn()
            }
        })

        nextBtn.addEventListener('click', function() {
            if (pageNum < totalNum-1) {
                pageNum ++
                pageChange()
                pageChangeBtn()
            }
        })
        
        li.forEach((ele, idx) => {
            ele.addEventListener('click', function(){
                pageNum = idx
                pageChange()
                pageChangeBtn()
            })
        })

        function pageChange(){
            span.innerText = pageNum + 1 // 페이지 번호 변경
            body.style.backgroundColor = bgColor[pageNum] // 배경색 변경
            for(var i=0; i<totalNum; i++){ // section태그에서 active 클래스 다 빼기
                section[i].classList.remove("active");
                li[i].classList.remove("active");
            }
            section[pageNum].classList.add("active"); // 현재 page의 section태그에 active 클래스 넣기
            li[pageNum].classList.add("active")

            const scroll = this.scrollY
            progressBar.style.width = `${(scroll+section[0].offsetHeight)/scrollHeight*100}%`
        }

        function pageChangeBtn(){
            window.scrollTo({ // ~로 스크롤하기
                top: section[pageNum].offsetTop, // 각 section 상단에 맞추기
                behavior: 'smooth'
            })
        }
        
        // 페이지 로드되면 바로 실행
        pageChange()

        window.addEventListener("scroll", function(event){ // 스크롤 이벤트 감지
            const scroll = this.scrollY // 스크롤값
            
            for (let i=0; i<totalNum; i++){
                // 페이지가 중간 이상 넘어가면 다음페이지로 간주
                if (scroll > section[i].offsetTop - window.outerHeight/2 &&
                scroll < section[i].offsetTop - window.outerHeight/2 + section[i].offsetHeight) {
                    pageNum = i
                    break
                }
            }
            pageChange()
        })

    }

</script>

 

참고

반응형