사이트명 : 엔터프라이즈 블록체인
사용언어 : HTML, CSS, Jquery(GSAP)
<div class="sticky">
<div class="area1">
이미지, ALWAYS 영역
</div>
<div class="area2">
갤러리 영역
</div>
</div>
ALWAYS의 영역의 애니메이션을 위해 두 개의 영역으로 잡았으며, 마지막의 이미지와 텍스트 리스트 부분은 Y 값을 위로 올려서 스크롤이 되게 만들었다.
const groupSlide = gsap
.timeline({
scrollTrigger: {
trigger: ".sc-intro .group-slide",
start: "0% 0%",
end: "100% 100%",
scrub: 0,
// markers: true,
invalidateOnRefresh: true,
},
})
.to(
".sc-intro .content-wrap",
{
x: function () {
return -$(".sc-intro .area1").outerWidth() + window.innerWidth;
},
},
"bg"
)
이전처럼 xPercent : -100% 안한 이유는 ALWAYS 영역의 애니메이션을 처리하기 위해 area1의 넓이 값 만큼 X값을 움직인 뒤 페이지의 넓이 만큼 동시에 움직여서 정확하게 가운데로 올 수 있게 만들었다.
gsap.to(".wander-img figure", {
xPercent: -250,
scrollTrigger: {
trigger: ".sc-intro .group-slide .wander-img",
containerAnimation: groupSlide,
start: "left 100%",
end: "left 0%",
scrub: 0,
},
});
중간의 이미지가 움직이는 애니메이션을 넣기 위해 containerAnimation 속성을 사용해서 애니메이션을 넣어줬다. 사용법은 간단하게 애니메이션을 같이 진행시킬 영역의 타임라인 변수를 지정해주면 된다.
트리거의 위치를 left, right를 줘서 트리거를 가로로 줄 수 있으며 그때 동안 실행시킬 애니메이션을 Gsap의 to로 지정하였다
텍스트가 위로 올라오는 애니메이션은 여러군데 사용해서 html의 data-effect="y-move"
를 지정하여 Gsap set으로 설정해주었다.
gsap.set(`[data-effect="fade"]`, { opacity: 0 });
gsap.set(`[data-effect="x-move"]`, { xPercent: 100 });
gsap.set(`[data-effect="y-move"]`, { yPercent: 100 });
gsap.to('.sc-order .group-call [data-effect="y-move"]', {
scrollTrigger: {
trigger: ".sc-order .title-area",
start: "0% 80%",
end: "100% 80%",
scrub: 0,
// markers: true,
},
yPercent: 0,
stagger: 0.01,
});
반복문으로 타임라인을 써서 애니메이션을 줄 수도 있지만 stagger란 속성을 사용해서 간단하게 애니메이션을 설정하였다.
html에서 텍스트를 분리하는게 아닌 JS에서 텍스트를 분리할 수 있게 하는 split 사용하여 텍스트를 분리했다.
const visualText1 = new SplitType(".sc-intro .sub-title-area", {
types: "words, chars",
});
문장, 단어로 텍스트를 분리할 수 있다.
인테리어 영역을 클릭하면 사이드바가 열리도록 만들었다.
$(".sc-interior .group-interior .interior-item").click(function () {
const room = $(this).data("room");
if (room == "bed-room") {
$(`[data-room="bed-room"]`).css("display", "block");
} else if (room == "scand-room") {
$(`[data-room="scand-room"]`).css("display", "block");
} else {
$(`[data-room="eco-room"]`).css("display", "block");
}
$(".interior-side").toggleClass("active");
$("body").toggleClass("active");
setTimeout(() => {
$(".interior-side .group-side").toggleClass("active");
}, 300);
});
인테리어 영역의 data를 가지고 와서 각 data에 맞는 영역을 보이게 했다
사이드바 영역이 아닌 곳을 클릭하면 닫히게 끔 만들었다
$(document).click(function (e) {
if (
!$(
".interior-side .group-side, .sc-interior .group-interior .interior-box .interior-item").has(e.target).length) {
$(".interior-side .group-side").removeClass("active");
setTimeout(() => {
$(".interior-side").removeClass("active");
$("body").removeClass("active");
$(`.interior-side [data-room*="room"]`).css("display", "none");
}, 1200);
}
});
배경 이미지의 영역, 고정되어 움직이는 텍스트, 이미지 영역으로 2개의 영역으로 나누었다
<div class="sticky">
텍스트, 이미지
</div>
<div>
배경 이미지
</div>
배경 이미지의 부분은 margin-top 조절해서 sticky 영역과 같이 보여지게 하였다
영역이 사라지는 부분을 처음엔 height 값을 조절했지만 텍스트 부분이 겹쳐보여 height값으로는 안되서 클립패스를 사용했다.
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
//보이는 코드
첫 번째 영역 빼고 전부 안보이게 한 다음 Gsap으로 애니메이션을 만들었다
clip-path: polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%);
//안보이는 코드
interiorList = gsap.timeline({
scrollTrigger: {
trigger: '.bg-area',
start: "0% 0%",
end: "100% 100%",
scrub: 0,
},
})
interiorList.to('.sc-order-interior .group-interior .area1', {
"clip-path": "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)"
}, 'a');
interiorList.to('.sc-order-interior .group-interior .area2', {
"clip-path": "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)"
}, 'a');
interiorList.to('.sc-order-interior .group-interior .area2', {
"clip-path": "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)"
}, 'b');
interiorList.to('.sc-order-interior .group-interior .area3', {
"clip-path": "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)"
}, 'b');
area1, area2 의 클립패스를 조절해서 1번은 안보이게 만들고 2번은 보여지게 만드는걸 동시에 진행되도록 했다 area2, area3 똑같이 만들었다.
$(".sc-visual, #footer").mousemove(function (e) {
const x = (20 * e.clientX) / $(".sc-visual").width();
const y = (10 * e.clientY) / $(".sc-visual").height();
gsap.to(".sc-visaul .img-box",{x:x,y:y})
});
뷰포트 내 좌표를 가지고 온 뒤, 너무 많이 움직일 필요는 없어 영역의 크기로 나누어 x값을 조절했다
반응형 처리를 위해 Gsap의 matchMedia 사용했다. 사용법은 Css의 미디어 쿼리 처럼 사용할 수 있어 간단하게 사용하였다.
let mm = gsap.matchMedia();
mm.add("(min-width: 1000px)", () => {}
이런식으로 사용해서 특정 크기에서만 사용할 수 있는 애니메이션을 넣어서 반응형 처리를 쉽게 할 수 있다.
부드러운 스크롤을 위해 lenis 사용하였다.
lenis.on("scroll", ScrollTrigger.update);
gsap.ticker.add((time) => {
lenis.raf(time * 800);
});
gsap.ticker.lagSmoothing(0);
Gsap용으로도 사용할 수 있게 되어 있어 간단하게 가능하며,
스크롤의 부드러움 값을 정하는 부분은 time 값을 조절해가면서 사용 할 수 있다
각 버튼을 누르면 각각의 영역으로 이동하는 애니메이션을 만들었다
$("#header .gnb-item").each(function (index) {
const targetIndex = index;
$(this).click(function () {
gsap.to(window, {
duration: 0.7,
scrollTo: { y: `#sc${targetIndex + 1}` },
});
$("#header .gnb").removeClass("active");
$("#header .menu-btn span.close").removeClass("active");
$("#header .menu-btn span.open").removeClass("remove");
});
});
각각의 세션마다 id값을 sc1, sc2... 정하고 반복문을 돌려서 각 영역의 y값으로 움직일수 있도록 만들었다