position: sticky를 사용하여 해당 위치에 페이지를 고정하고
우측 하단의 카드가 슬라이드 되고, 해당 위치에 도달했을 때
사이즈와 색상이 변경되는 효과를 구현하였다.
<!--css-->
.sc-appeal{ // ✅ 부모
position: sticky;
top: 0;left: 0;
width: 100%;
z-index: 2;
}
.sc-appeal .wrapper{ // ✅ 자식
position: relative;
height: 1000vh; // 👈 자식의 높이
}
.sc-appeal .content{ // ✅ 부모
position: sticky;
top: 0;
display: flex;
align-items: flex-end;
background: #fff;
width: 100%;
height: 100vh; // 👈 부모의 높이
}
.sc-appeal .content .text-area{ // ✅ 자식
flex: 1;
position: relative;
height: 100vh; // 👈 자식의 높이
}
position을 sticky로 설정해준 태그의 자식의 height는 원하는 이벤트를 나타날 시간만큼
높이를 길게 해주면 부모는 해당위치에 고정된 채로 길이가 길어진 자식 태그가 길이가 끝날 시간동안 웹에 페이지가 고정된 형태로 남고, 스크롤 되며 자식은 그대로 스크롤이 되며
인터렉션 효과가 구현된다.
여기서 가장 중요한 부분 ⭐️
position: sticky 엘리먼트의 부모 엘리먼트의 overflow 속성이 hidden일 경우 fixed좌표가 아닌 계속 static 좌표에 위치한다.
정확히 말하면 스크롤박스와 sticky 엘리먼트 사이에 overflow: hidden인 엘리먼트가 존재할 경우 sticky 속성값이 무시된다.
전에 설명했던 이미지 시퀀스 ( 📎 이미지 시퀀스 방법) 방법 외에
비디오로도 시퀀스가 가능하단 방법을 알게되어 사용해보았다.
<!--js-->
const vid1 = $('.sc-setup .img-wrap').find('video')[0];
ScrollTrigger.create({
trigger: '.sc-setup',
start: '0% 0%',
end: '100% 100%',
scrub: 1,
// markers: true,
onEnter: function (e) {
setInterval(function () {
vid1.currentTime = e.progress.toFixed(3) * 5.5;
}, ✅ 270);
},
});
vid1 변수에 비디오 요소를 선언해주고, ScrollTrigger 객체를 생성해줍니다. 그리고
Gsap의 ScrollTrigger을 사용하여 스크롤에 반응하여 애니메이션 및 동작을 트리거합니다.
trigger로는 .sc-setup 클래스를 트리거로 사용하고 scrub을 사용하여 스크롤마다 반응하도록 설정하였습니다. 그리고
onEnter속성을 사용하여 ScrollTrigger가 요소 진입시에 실행될 콜백 함수를 지정합니다.
setInterval 함수는 ScrollTrigger가 요소에 진입할 때 실행되는 콜백 함수를 정의하며,일정한 간격으로 비디오의 현재 시간(currentTime)을 업데이트하여 비디오를 제어합니다.
vid1.currentTime = e.progress.toFixed(3) * 5.5;은
ScrollTrigger의 e.progress 속성을 기반으로 비디오의 재생 위치를 업데이트합니다.
toFixed(3)은 e.progress 값을 소수점 이하 3자리로 반올림하고,
이 값을 5.5와 곱하여 비디오의 현재 재생 시간을 설정합니다.
✅ 표시된 숫자인 270은 setInterval 함수의 실행 간격을 나타냅니다.
setInterval 함수는 주어진 시간 간격마다 함수를 실행하며,
여기서 270은 각 실행 간격을 밀리초(1/1000 초) 단위로 나타냅니다.
각 비디오를 사용할 때 이 숫자를 조금씩 수정해가며 사용하면 된다!
스와이프 시에 이미지의 위치와 이미지의 크기가 변동되도록 표현하였으며,
스와이프 슬라이드 버튼의 클래스명 변환으로 간단하게 조절이 가능하다.
<!--css-->
.sc-review .swiper-slide-prev{ // 이전 슬라이드 기본 클래스명
transform: translateX(-50%) scale(.6) rotate(10deg) !important;
}
.sc-review .swiper-slide-active{ // 현재 슬라이드 기본 클래스명
transform: translateY(20%) rotate(-7deg) !important;
}
.sc-review .swiper-slide-next{ // 다음 슬라이드 기본 클래스명
transform: translateX(50%) scale(.6) rotate(-10deg) !important;
}
!important는 모든 조건을 무조건적으로 우선순위로 만드는 속성!