스크롤을하여 고개를 돌려보아요

김삿갓의싱잉랩·2023년 8월 2일

✨ 스크롤을 했을 때 사진이 슥 나오기

0. 구현하고자 하는 효과

1. html 코드 작성

: 이번엔 매우 간단하다. main tag를 만들고 그 안에 section tag와 원하는 이미지를 삽입했다.

<main>
        <section id="panel1-img">
            <img id="chungju-lake-img" src="./assets/image/image2.jpg">
        </section>
</main>

2. CSS 간단하게 구성

: main tag에는 사진이 overflow:hidden이 될 수 있도록 (창을 넘어가지 않도록) 해당 속성값을 부여한다. 이미지가 보여질 section 에는 position:relative를 활용해서 img tag를 활용할 때 position:absolute를 사용할 수 있도록 하였다. 이미지 태그에는 위치와 크기를 간단하게 지정하고 transform 속성을 활용해서 위치와 기울기의 변화를 주려고 한다.

/* 스크롤에 따라 반응하는 이미지 만들기 */

main {
    width: 100%;
    overflow: hidden;
}

#panel1-img {
    position: relative;
    height: 520px;
    }

#chungju-lake-img {
    position: absolute;
    right: -80px;
    top: 20%;

    height: 285px;
    border-radius: 50px;

    transform: translate(80px, -13px) rotate(23deg);
}

3. JS 구현

: 해당 효과에 들어가는 JS이다.

✅ 변수 선언

  • panel1image : section의 위치값을 활용해야 하기 때문에 dom 요소를 불러온다.
  • chungjuImg : 사진에다가 Element.style.transform을 주어야 움직이기 때문에 요소를 불러온다.
const panel1image = document.getElementById('panel1-img');
const chungjuImg = document.getElementById('chungju-lake-img')

✅ 문서 위치판단 요소 제작

  • scrollYBottom : 2개의 요소를 더한 값은 현재 내가 바라보는 화면의 가장 하단의 y값이다.
  • if문 : 해당 효과가 유지되어야 하는 시간은 그 효과가 차지하고 있는 스크롤y 값이라고 할 수 있다. 따라서 section 안에 있어야 효과가 유지될 수 있도록 조건을 만든다. && 뒤에 붙는 조건식은 section의 가장 높은 값에서 길이를 더한 값이므로 section 의 높이라고 볼 수 있다.
  • translateX, translateY : 각각 CSS에서 정했던 transform의 값에 역을 할당해준다. 즉 해당 요소의 element.trnasform 값을 주기 전의 원래의 상태로 돌아오도록 하는 것이다. 여기에 1.1 같은 배수를 곱하면 변화하는 크기가 더 커진다.
  • rotationDegree : 회전 요소도 위와 동일하다. 모든 변경 요소에서 수 뒤에 붙는 수식은 section에 단위를 부여하여 점진적으로 효과가 나올 수 있도록 하는 수식이다.
  • style.transform : literal 방식을 통해 변화 효과를 추가한다.
window.addEventListener('scroll', () => {
    //문서 위치에 따라 판단
    //document.documentElement.clientHeight는 브라우저 창의 높이
    const scrollYBottom = window.scrollY + document.documentElement.clientHeight;
    
    // panel1image.offsetTop은 panel1image의 문서 위치 좌상단 기준 가장 높은 위치
    console.log(document.documentElement.clientHeight)


    
    // 스크롤의 위치가 panel1image의 상단 위치보다 아래에 있고,
    // panel1image의 상단 위치와 panel1image의 높이를 합친 값보다 위에 있을 때,
    // 이는 스크롤이 panel1image 내부로 들어왔음을 의미합니다.
    if (scrollYBottom > panel1image.offsetTop && scrollYBottom < panel1image.offsetTop + panel1image.offsetHeight + 200) {
        
            // 이 경우에, 이미지의 translateX 값을 계산합니다.
            // 80 - 80 * 스크롤 위치와 이미지 상단의 차이를 이미지의 높이 + 200으로 나눈 값
            // 이 결과값은 스크롤이 이미지를 지나감에 따라 80에서 0으로 변경됩니다.
            const translateX = 80 - 80 * 1.1 * (scrollYBottom - panel1image.offsetTop) / (panel1image.offsetHeight + 200);
            const translateY = -13 + 13 * (scrollYBottom - panel1image.offsetTop) / (panel1image.offsetHeight + 200);

            const rotationDegree = 23 - 23 * 1.3 * (scrollYBottom - panel1image.offsetTop) / (panel1image.offsetHeight + 200);

            // 위에서 계산된 translateX 값으로 이미지의 위치를 변경합니다.
            // 이미지는 스크롤이 지나감에 따라 오른쪽으로 움직입니다.
            chungjuImg.style.transform = `translate(${translateX}%, ${translateY}%) rotate(${rotationDegree}deg)`
    }

})



profile
시스템 개발에 시간을 아끼지 말자

0개의 댓글