엔터프라이즈 블록체인 클론코딩
2025. 8. 24.ㆍ공부/HTML,CSS
728x90

URL : https://developedbyssony.github.io/enterpriseBlockchain/

컨텐츠 영역에 섹션이 16개 들어갔으며, 중간에 div로 묶어준 section에 data-theme="dark"를 적용하였다. 또, .sc_service 섹션 같은 경우 인터랙션에 용이하기 위해 내부에 수직 컨텐츠와 수평 컨텐츠를 따로 묶어주었다. 클론을 하면서 GSAP을 활용한 스크롤 인터랙션을 구사하는 것에 중점을 두었다. 본 포스팅에서 스크롤 인터랙션 시나리오를 간단하게 정리하고자 한다.
일단 GSAP 활용하기 위해 CDN을 넣어야한다. 스크롤 인터랙션을 구현하기 위하여 스크롤 트리거용 CDN도 넣어준다.
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
a. 인트로 구간
const motionIntro = gsap.timeline({
scrollTrigger:{
trigger: ".sc_intro",
start: "top top",
end: "+=7000",
scrub: true,
pin:true
}
});
const introText = $(".sc_intro .intro_description .intro_description_text");
motionIntro.addLabel('a')
.to('.sc_intro .dimmed', {opacity:1 },'a')
.to(introText[0], { opacity: 1 },'a')
.to(introText[0], { opacity: 0 ,
onStart:function(){
$('.header').addClass('show');
},
onReverseComplete:function(){
$('.header').removeClass('show');
}
})
.to(introText[1], { opacity: 1 })
.to(introText[1], { opacity: 0 })
.to(introText[2], { opacity: 1 })
.to(introText[2], { opacity: 0 })
.to(introText[3], { opacity: 1 });
const showTitleArr = $(".showcase_intro_text");
const showImgArr = $(".showcase_img img");
const motionShowcase = gsap.timeline({
scrollTrigger:{
trigger: ".sc_showcase",
start: "0% 0%",
end: "100% 100%",
scrub: 0
}
});
motionShowcase
.to('.sc_showcase .dimmed',{ autoAlpha:1 },'a') // 화면 dimmed
.to('.showcase_intro', { autoAlpha:1 },'a') // 해당 섹션 인트로 화면 투명도 100%
.to(showTitleArr[0], {xPercent:100 },'b') // 첫번째 텍스트 오른쪽으로 100% 이동
.to(showTitleArr[2], { xPercent:-100},'b') // 마지막 텍스트 왼쪽으로 100% 이동
.to('.sc_showcase .dimmed',{ autoAlpha:0 },'b') // dimmed된 화면 다시 밝게
.to('.showcase_intro', { autoAlpha:0},'c') // 해당 섹션 인트로 화면 투명도 0%
.to(showImgArr[2], { height:0},'c') // 해당 이미지 height 스크롤 내리며 0으로 줄어듬
.to(showImgArr[1], { height:0,'c'}) // 해당 이미지 height 스크롤 내리며 0으로 줄어듬
.to('.sc_showcase .dimmed',{ autoAlpha:1 },'d') // 화면 dimmed
.to('.showcase_description',{ autoAlpha:1 },'d') // 글자 투명도 100%
b. 흑백 전환 구간
data-theme="dark"라는 속성의 div 구간에 진입하면 body에 dark클래스가 자동 적용되어 전역적으로 다크 테마를 적용하게 하였다. 트리거 구간의 0%가 뷰포트의 55%에 도달하면 시작하고, 트리거의 100%가 뷰포트의 100%에 도달하면 끝난다.
ScrollTrigger.create({
trigger: `[data-theme="dark"]`,
start: "0% 55%",
end: "100% 100%",
toggleClass:{
targets:"body",
className:"dark",
}
});
const possibility = gsap.timeline({
scrollTrigger: {
trigger: ".sc_possibility",
start: "0% 0%",
end: "100% 100%",
scrub: 0,
invalidateOnRefresh:true,
},
});
possibility.to(".sc_possibility .slide_sub_wrap", {
xPercent:-100,
x:function(){
return window.innerWidth-100;
}
});
const feature = gsap.timeline({
scrollTrigger: {
trigger: ".sc_feature",
start: "0% 95%",
end: "100% 80%",
scrub: 0
},
});
feature.from('.sc_feature .col-left',{xPercent:-50},'a')
feature.from('.sc_feature .green',{xPercent:50},'a')
const feature2 = gsap.timeline({
scrollTrigger: {
trigger: ".sc_feature",
start: "0% 45%",
end: "100% 35%",
scrub: 0,
onEnter:function(){
$('.sc_feature').addClass('blur')
},
onLeaveBack:function(){
$('.sc_feature').removeClass('blur')
}
},
});
feature2.from('.sc_feature .feature_title',{autoAlpha:0})
c. .sc_service 구간
- .group_hr에서 카드들의 좌-> 우 순차적 이동
const service1 = gsap.timeline();
service1
.addLabel("a")
.to(".sc_service .group_hr .slide",{x:-515,duration:3},"a")
.addLabel("b")
.to('.sc_service .group_hr .slide',{
x:function(){
return $('.sc_service .slide_head .headline').outerWidth()*-1
}})
.to(".sc_service .group_hr .card_item:nth-child(2)",{xPercent:-100,x:-40,duration:3},"b")
.to(".sc_service .group_hr .card_item:nth-child(3)",{xPercent:-200,x:-80,duration:3},"b")
.to(".sc_service .group_hr .card_item:nth-child(4)",{xPercent:-300,x:-120,duration:3},"b")
- .group_vt가 하단에서 위로 밀려오며 등장 + 카드 이동
.addLabel("c")
.from(".sc_service .group_vt",{autoAlpha:0},"c")
.from(".sc_service .group_vt",{yPercent:100,y:"-200",duration:8,ease:"none"},"c")
.from(".sc_service .group_vt .card_lock",{autoAlpha:0})
.addLabel("d")
.to(".sc_service .group_vt .card_item:nth-child(2)",{x:-445,duration:3},"d")
.to(".sc_service .group_vt .card_item:nth-child(3)",{x:-885,duration:3},"d")
.to(".sc_service .group_vt .card_item:nth-child(4)",{x:-1325,duration:3},"d")
- "누구든 무엇이든"(엔딩 텍스트) 등장
.addLabel("e")
.from(".sc_service .group_vt .end_txt_box",{autoAlpha:0,duration:3},"e")
d. 끊임없이 흐르는 띠배너 구간
@keyframes banner {
from { transform: translateX(0); }
to { transform: translateX(300%); }
}
.sc_banner .content_list {
display: flex;
margin-left:-705px ;
}
.sc_banner .content_list .content_item:nth-child(3n-1) {
background: #0049ff;
}
.sc_banner .content_list .content_item:nth-child(3n-2) {
background: #00bf41;
}
.sc_banner .content_list .content_item:nth-child(3n) {
background: #e657af;
}
.sc_banner .content_list .content_item {
position: relative;
color: #fff;
display: flex;
font-size: 24px;
width: 235px;
height: 60px;
justify-content: center;
align-items: center;
animation: banner 8s linear infinite running;
}
'공부 > HTML,CSS' 카테고리의 다른 글
| 셀세이프 클론 코딩 (0) | 2025.08.23 |
|---|---|
| 웹 구축을 위한 최소한의 조건, 웹 접근성 (1) | 2024.10.04 |
| [Component] 간단한 헤더 만들기 (0) | 2024.01.20 |
| [HTML/CSS] 뷰포트 중앙정렬하기 (0) | 2024.01.03 |
| [HTML/CSS] em과 rem (0) | 2023.12.02 |