사이트명 : 엔터프라이즈 블록체인
사용언어 : HTML, CSS, Jquery(GSAP)
화면에 요소를 고정시킬 때, GSAP의 Pin 기능을 사용할 수도 있지만, Pin 기능을 사용하면 레이아웃이 이상해질 수 있고, position : fixed의 기능은 position: sticky로도 대체가 가능해 sticky를 사용하였다.
<section>
<div class="content-wrap">
화면에 고정시켜서 보여줄 내용
</div>
</section>
position: sticky 속성을 사용하여 .content-wrap 요소가 스크롤 시 화면에 고정되도록 설정 하였다. 충분히 스크롤이 가능하도록 부모 요소에 높이 값을 지정
section {
height: 600vh
}
.content-wrap {
width: 100%;
height: 100vh;
position: sticky;
top: 0;
}
GSAP과 ScrollTrigger를 활용하여 인트로 글자가 변경될 때 헤더 부분의 클래스를 제어하기 위해 이벤트 핸들러를 사용
const intro = gsap
.timeline({
scrollTrigger: {
trigger: ".sc-intro",
start: "0% 0%",
end: "100% 100%",
scrub: 0,
},
})
.to(".sc-intro .intro-description", { background: "rgba(0,0,0,.7)" }, "bg")
.to(".sc-intro .desc-text1", { opacity: 1 }, "bg")
.to(".sc-intro .desc-text1", {
opacity: 0,
onStart: function () {
$("#header").addClass("active");
},
onReverseComplete: function () {
$("#header").removeClass("active");
},
})
(.to("",{},"bg") : 라벨 이름이 같으면 같이 실행, bg+=5 or bg-=5 : X초뒤 시작 X초 먼저 시작)
슬로건의 배경이미지, 텍스트 부분들은 따로 따로 만들어 position: absolute;로 위치값을 조정
<section>
<div>
슬로건 배경 이미지
</div>
<div>
슬로건 텍스트
</div>
<div>
슬로건 텍스트
</div>
</section>
이렇게 구조를 잡았으며, absolute을 사용해서 각 요소의 z-index를 조절 할 수도 있지만 이미지를 역순으로 배치 하였다.
const slogan = gsap
.timeline({
scrollTrigger: {
trigger: ".sc-slogan",
start: "0% 0%",
end: "100% 100%",
scrub: 0,
// markers: true,
},
})
.to(".slogan-text-box", { background: "rgba(0,0,0,.7)" }, "bg")
.to(".slogan-title", { opacity: 1 }, "bg")
.to(".slogan-text1", { xPercent: 100 }, "text")
.to(".slogan-text2", { xPercent: -100 }, "text")
.to(".slogan-text-box", { background: "rgba(0,0,0,0)" }, "text")
.to(".slogan-title", { opacity: 0 })
.to(".bg-img1", { height: 0 })
.to(".bg-img2", { height: 0 })
.to(".slogan-description-text", { opacity: 1 }, "bg-end")
.to(".slogan-text-box", { background: "rgba(0,0,0,.4)" }, "bg-end");
이미지들의 높이값을 0으로 줄 때 img의 높이 값을 없애는게 아닌 이미지의 높이는 100vh로 고정시키고 부모의 높이값을 조절했다
const business = ScrollTrigger.create({
trigger: ".sc-business",
start: "0% 10%",
end: "100% 100%",
scrub: 0,
onEnter: function () {
$("#header").addClass("dark");
$(".lang-list").addClass("white");
},
onLeaveBack: function () {
$("#header").removeClass("dark");
$(".lang-list").removeClass("white");
},
});
const dark = ScrollTrigger.create({
trigger: '[data-theme="dark"]',
start: "0% 50%",
end: "100% 20%",
scrub: 0,
toggleClass: {
targets: "body",
className: "dark",
},
onEnter: function () {
$("#header").removeClass("dark");
$(".lang-list").removeClass("white");
},
onLeaveBack: function () {
$("#header").addClass("dark");
$(".lang-list").addClass("white");
},
});
중간의 header와 body의 색상을 변경하기 위해 GSAP으로 조절 하였다
스크롤 될때마다 요소의 x값을 계속 밀어주기 위해 두개의 요소를 감싸는 div를 만들었다.
<div class="sticky">
<div class="group">
<div>
첫번째 요소
</div>
<div>
두번째 요소
</div>
</div>
</div>
group의 정확한 width값을 알기 위해 max-content란 속성을 사용하였다. 부모가 display:flex면 사용할 필요는 없지만, 사용을 안한 경우엔 max-content란 속성을 활용하여 width값을 정확히 알 수 있다.
.group {
width: max-content;
height: 100%;
display: flex;
align-items: center;
}
요소의 x값을 미는건 생각보다 간단하게 밀 수 있다
const dataInfo = gsap
.timeline({
scrollTrigger: {
trigger: ".sc-data-info",
start: "0% 0%",
end: "100% 100%",
scrub: 0,
// markers: true,
invalidateOnRefresh: true,
},
})
.to(".group", {
xPercent: -100,
x: function () {
return window.innerWidth;
},
});
지금의 레이아웃 경우는 두 번째의 요소가 width:100vw 값으로 화면에 꽉차게 보여지고 있으며, 감싸고 있는 부모의 요소를 xPercent:100을 사용해 x축을 -100% 만큼 이동 시킨 뒤 window.innerWidth 값 만큼 x축으로 동시에 이동 시킨다.
그리고 x축의 값을 이동 시킬 때 브라우저 크기에 맞게 보여지게 하기 위해 invalidateOnRefresh: true 사용 (윈도우 리사이징 할 때 새로고침 할수 있도록)
return 함수를 써서 윈도우 리사이징 할 때도 새로고침 할 수 있게 만들었다.
DATA 영역
총 세개의 영억으로 잡아주었다.
<div class="content1">
<div class="sticky-wrap">
<div class="sticky">
카드 영역
</div>
</div>
</div>
<div class="content2">
<div>
위로 올라오는 텍스트 영역
</div>
</div>
<div class="content3">
<div class="sticky">
카드 영역
</div>
</div>
마크업은 이런식으로 잡은 뒤 하나의 영역으로 보여지게 하기 위해서 content의 높이 값 보다 sticky-wrap 높이 값을 더 많이 줘서 실제 영역보다 더 많이 스크롤을 고정 시키고 두 번째의 요소는 margin-top 값을 조정하여 하나의 영역으로 이어지게 해주었다.
제일 중요한 카드 부분은 content 영역 마다 미리 만들어서 content 영역이 스크롤 될 때 바꿀 수 있게 하였다.
onEnter: function () {
gsap.set(".sc-service .area2 .card-area .card", { opacity: 0 });
gsap.set(".sc-service .area3 .card-list-item.card-lock", {
opacity: 1,
});
},
onLeaveBack: function () {
gsap.set(".sc-service .area2 .card-area .card", { opacity: 1 });
gsap.set(".sc-service .area3 .card-list-item.card-lock", {
opacity: 0,
});
},
onEnter와 onLeaveBack 으로 실행 시켜 set으로 속성 상태를 변경한다
스크롤을 내렸을 땐 버튼이 안보이다가 다시 올릴땐 보이게 만들었다.
ScrollTrigger.create({
trigger: ".sc-slogan",
start: "0% 0%",
end: "100% 100%",
endTrigger: "#footer",
onUpdate: function (self) {
direction = self.direction;
if (direction == 1) {
$(".top-btn").removeClass("active");
} else {
$(".top-btn").addClass("active");
}
},
onLeaveBack: function () {
$(".top-btn").removeClass("active");
},
});
endTrigger를 사용하여 슬로건의 영역부터 푸터의 영역까지 스크롤 트리거를 잡아주었다. onUpdate란 메소드를 사용하여 direction란 속성은 스크롤이 내려가면 1 올라가면 -1의 값을 출력하는데 if문을 통해서 Top 버튼의 숨김 처리를 하였다.
버튼을 눌렀을때 스크롤 이동은 Gsap의 ScrollToPlugin 사용하여 간단하게 만들었다.
$(".top-btn").click(function () {
gsap.to(window, { duration: 1, scrollTo: 0 });
});