๐ https://github.com/eveneul/lush
๐ https://eveneul.github.io/lush
awwwards์ ์ฌ๋ผ์จ ์์์ฅ์ ๋ ํผ๋ฐ์ค๋ก ์ฐธ๊ณ ํด์ ๋ง๋ ๋ฌ์ฌ ์ฌ์ดํธ ๋ฆฌ๋ด์ผ์ ๋๋ค (์ ์ํ)
gsap, mouseover ์ด๋ฒคํธ ํ์ฉ๊ณผ ํนํ css ์์ฑ ์ค mask์ ๋ํด์ ์กฐ๊ธ ๋ ๊น๊ฒ ์ดํดํ ์ ์์๋ ์๊ฐ์ด์์ต๋๋ค
CSS์ ์ธ ์คํฌ๋ณด๋ค๋ gsap scrollTrigger, JQuery ๊ธฐ๋ฅ ์์ฃผ๋ก ์ต๋ํ ๊ฒ ๋ง์์ Jquery ๊ธฐ๋ฅ ์์ฃผ๋ก ์์ฑํ๋ ค๊ณ ํฉ๋๋ค
๊ณ ํ์ง ์ด๋ฏธ์ง๋ฅผ ์ป๋ ๊ฒ ์ด๋ ค์์ ํฐ ์ด๋ฏธ์ง์ ๊ฐ์ ๊ฒฝ์ฐ ํ์ง์ด ๋งค๋๋ฝ์ง ๋ชปํฉ๋๋ค.. ใ ใ
position: fixed
๋ฅผ ์ฃผ์ด์ ์คํฌ๋กค์ ๋ด๋ฆฌ๋ ์ฌ๋ฆฌ๋ ํญ์ ์๋จ์ ์์นํ๊ฒ ๊ณ ์ ํด ๋์์ต๋๋ค
๋์ , ํ์ด์ง ๋งจ ์์ ์์ ๋๋ background-color: transparent
์ ์ฃผ์ด์ ๋ฐํ์ ๊น๋ฆฐ ๋ณ ์ํฐํด์ด ๋ณด์ด๊ฒ๋ ์ค์ ํ๊ณ ,
์คํฌ๋กค์ ๋ด๋ฆฌ๋ฉด ํค๋๊ฐ ์๋ก ์ฌ๋ผ๊ฐ ์จ๊ฒจ์ง๊ณ , ์คํฌ๋กค์ ์ฌ๋ฆฌ๋ฉด background-color
๊ฐ ์ ์ฉ, ๋ค์ ํค๋๊ฐ ๋ฐ์ผ๋ก ๋ด๋ ค์ ๋์ผ๋ก ๋ณด์ด๊ฒ๋ ์ค์ ํ์ต๋๋ค.
const headerAni = gsap
.from('.header', {
yPercent: -100,
paused: true,
duration: 0.4,
})
.progress(1);
ScrollTrigger.create({
start: 'top top',
end: 99999,
onUpdate: (self) => {
self.direction === -1 ? headerAni.play() : headerAni.reverse();
},
});
๋จผ์ gsap.from์ ์ด์ฉํด header ๊ธฐ๋ณธ๊ฐ์ด y๋ก -100%๋งํผ ์ด๋ํด ํ๋ฉด์ด ๋
ธ์ถ๋์ง ์๊ฒ ์ค์ ํ์ต๋๋ค
๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ์ headerAni๋ผ๋ ๋ณ์์ ๋ด์์ ์คํฌ๋กค์ ์ฌ๋ฆฌ๋ฉด headerAni.reverse()๋ก ํ๋ฉด์ ๋
ธ์ถ๋๊ฒ,
์คํฌ๋กค์ ๋ด๋ฆฌ๋ฉด headerAni.play()๋ก yPercent: -100๊ฐ ์คํ๋๊ฒ ๋ง๋ค์์ต๋๋ค
$(window).scroll(function (e) {
let scrollVal = $(this).scrollTop();
if (scrollVal <= 10) {
gsap.to('.header', {
'background-color': 'rgba(24,24,24, 0)',
});
} else {
gsap.to('.header', {
'background-color': 'rgba(24,24,24, 1)',
});
}
});
๋ window
์ ์คํฌ๋กค ์์ง ์์น๊ฐ์ scrollVal
์ด๋ผ๋ ๋ณ์์ ๋ด์
scrollTop
์ด 10๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ผ๋ฉด (ํค๋๊ฐ ํ์ด์ง ๋งจ ์๋จ์ ์์นํ๊ณ ์์ผ๋ฉด) background-color
์์์ ํฌ๋ช
์ผ๋ก,
๊ทธ๊ฒ ์๋๋ผ๋ฉด background-color
์์ alpha
๊ฐ์ 1๋ก ์ฃผ์ด #181818 ์์์ด ์ ์ฉ๋๋๋ก ํ์ต๋๋ค
์คํฌ๋กค์ ์ฌ๋ฆฌ๊ณ ๋ด๋ฆฌ๋ฉด ๋ณ์ ์์์ด ๋ค์ ๋น์ณ์ง๊ณ , ๋ง์ฐ์ค๋ฅผ ์์ง์์ ๋๋ mousemove ์ด๋ฒคํธ๋ก ๋ณ๋ ์์ง์ผ ์ ์๊ฒ ๊ตฌํํ์ต๋๋ค
์ผ๋จ ์ฌ์ด์ฆ๊ฐ ๋ค ๊ฐ์ ๊ฒ์ด ์๋ partice์ particle1, particle2๋ก ๋๋ ์ ๋ ๊ฐ์ ํฌ๊ธฐ๋ฅผ ๋ค๋ฅด๊ฒ ํด ์ฃผ์์ต๋๋ค
let particle1 = '';
let particle2 = '';
for (let i = 0; i < 15; i++) {
particle1 += `<span class="particle particle1" data-speed="${
i + 1
}"><i class="front"></i><i class="back"></i></span>`;
}
for (let i = 0; i < 15; i++) {
particle2 += `<span class="particle particle2" data-speed="${
i + 1
}"><i class="front"></i><i class="back"></i></span>`;
}
$('.bg-particle').prepend(particle1);
$('.bg-particle').prepend(particle2);
๋ for ๋ฐ๋ณต๋ฌธ์ ํตํด ๊ฐ๊ฐ ์ต๋ 15๊ฐ์ ์ํฐํด์ ์ค์ ํ๊ณ , mousemove
ํ์ ์ ์๋๋ฅผ ๋ค๋ฅด๊ฒ ์ค์ ํ๊ธฐ ์ํด data-speed
๊ฐ๋ ๋ฃ์์ต๋๋ค
๋ ์ด ๋ ๊ฐ์ particle์ ๋ฏธ๋ฆฌ html์ผ๋ก ์์ฑํด ๋ .ba-particle
์์ ๋ฃ์์ต๋๋ค
const sizeArrS = [[3, 3],[5, 5],[4, 4],[2, 2]];
const sizeArrM = [[10, 10], [7, 7], [9, 9]];
const small = Math.floor(Math.random() * sizeArrS.length);
const sizeSmaollSelec = sizeArrS[small];
const mid = Math.floor(Math.random() * sizeArrM.length);
const sizeMidSelec = sizeArrM[mid];
ํ์ด์ง ๋ก๋ ์๋ง๋ค particle์ ํฌ๊ธฐ๋ฅผ ๋ค๋ฅด๊ฒ ํ๊ธฐ ์ํด์ ์์์ ๋ฐฐ์ด์ ๋ง๋ค์๊ณ ,
Math.floor()
, Math.random()
์ ํตํด ๋ฐฐ์ด ์์ ์๋ ์ฌ์ด์ฆ ๋ฐฐ์ด๋ค์ด particle์ ์ฌ์ด์ฆ๊ฐ ๋๋๋ก ์ค์ ํ์ต๋๋ค
const winH = $(window).innerHeight();
const winW = $(window).innerWidth();
gsap.set('.particle1', {
width: `${sizeSmaollSelec[0]}`,
height: `${sizeSmaollSelec[1]}`,
top: `random(0, ${winH})px`,
left: `random(0, ${winW})px`,
});
gsap.set('.particle2', {
width: `${sizeMidSelec[0]}`,
height: `${sizeMidSelec[1]}`,
top: `random(0, ${winH})px`,
left: `random(0, ${winW})px`,
});
window
์ innerWidth()
, innerHegiht()
๊ฐ์ ๊ตฌํด gsap์ random์ผ๋ก particle ์์น๋ฅผ ๊ฐ๊ฐ ๋ค๋ฅด๊ฒ ์ค์ ํด ๋์์ต๋๋ค
ํ์ด์ง ๋ก๋ ์๋ง๋ค ๋ฌ๋ผ์ง๋ ๊ฐ์ผ๋ก ๊ฐ๋ ๊ฒน์น particle์ด ์์ ์ ์์ต๋๋ค!
$(window).mousemove(function (e) {
$('.particle').each(function (idx, el) {
const speed = $(this).data('speed');
const x = ($(window).outerWidth() - e.offsetX * speed) / 350;
const y = ($(window).outerHeight() - e.offsetY * speed) / 350;
gsap.to(el, {
x: x,
y: y,
});
});
});
๋จผ์ mousemove
๋ฅผ ํ๋ฉด particle ๊ฐ๊ฐ data-speed
๊ฐ์ ์ด์ฉํด์ ์์ง์ด๊ฒ ๋ ์ค์ ํ์ต๋๋ค
๋ฆด๋ฆฌ๋ฐ์ด๋ ๋ ๋ฆฌ๋ด์ผ ๋ ๋ฐฐ์ด ๊ธฐ๋ฅ์ด๋ผ์ ์ด๋ฒ ๋ฌ์ฌ ๋ฆฌ๋ด์ผ์๋ ์ ์ฉํ๊ธฐ๊ฐ ์์ํ์ต๋๋ค
$('body').on('mousewheel', function (e) {
let y = e.originalEvent.wheelDelta;
number = Math.abs(y);
result = number > 10 ? 12 : 5;
gsap.to('.particle .back', {
scaleY: result,
});
if (y > 0) {
gsap.set('.particle .back', {
'transform-origin': 'center top',
'background': 'rgb(255,255,255)',
'background':
'linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(159,159,159,1) 93%)',
'border-top-left-radius': '3px',
'border-top-right-radius': '3px',
});
} else {
gsap.set('.particle .back', {
'transform-origin': 'center bottom',
'background': 'rgb(255,255,255)',
'background':
'linear-gradient(180deg, rgba(255,255,255,0) 0%, rgba(159,159,159,1) 93%)',
'border-bottom-left-radius': '3px',
'border-bottom-right-radius': '3px',
});
}
gsap.to('.particle .back', {
scaleY: 0,
});
});
๊ทธ๋ฆฌ๊ณ body
์์ mousewheel
์ด๋ฒคํธ๋ฅผ ๋ฐ์ํ์ ๋, e.originalEvent.wheelDelta
๋ก ๋ง์ฐ์ค ํ ์ด ์๋ก ํฅํ๋์ง, ์๋๋ก ํฅํ๋์ง ํ๋จํ๋ y๋ผ๋ ๋ณ์๋ฅผ ๋ง๋ค์์ต๋๋ค
์ด y๊ฐ 0๋ณด๋ค ํฌ๊ฑฐ๋ ์์ผ๋ฉด transform-origin
์ ์์ฑ๊ฐ์ ๋ณ๊ฒฝํด์ ๋ง์น ๋ณ์ ์์์ฒ๋ผ ๋ณด์ด๊ฒ ์ค์ ํ์ต๋๋ค
๋ y๊ฐ ์์๋ฉด ์์๋ก ๋ณํํด ์ฃผ๋ Math.abs() ํจ์์ ๋ด๊ณ , ์ด ๊ฒฐ๊ณผ๊ฐ์ ์ด์ฉํด ๋ง์ฐ์คํ ๋ฐฉํฅ์ ๋ฐ๋ผ์ ์์ ์์น๊ฐ ๋ฐ๋๊ฒ๋ ์ค์ ํ์ต๋๋ค
๋จผ์ ํ
์คํธ๋ฅผ CSS transform-origin
์ผ๋ก ์์น๊ฐ์ ์ค์ ํด ์ค ์ํ์
๋๋ค
gsap.from('.sc-visual', {
duration: 1,
opacity: 0,
});
const visualAni = gsap.timeline({
defaults: {
duration: 1,
ease: 'power2.out',
},
});
๋จผ์ ํ์๋ผ์ธ์ ์ค์ ํด์ ํ ์คํธ -> ๋ฒํผ -> ๋๊ทธ๋ผ๋ฏธ ์์ผ๋ก ๋ํ๋๊ฒ๋ ์ค์ ํ์ต๋๋ค
๊ทธ๋ฆฌ๊ณ ์ด ๋ชจ๋ ๊ฒ๋ค์ด ํฌ๋ช
์ธ ์ํ์ด๊ณ ์๋์์ ์ฌ๋ผ์ค๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ gsap.from()
์ผ๋ก opacity: 0
์ ์ค์ ํ์ต๋๋ค
visualAni
.from('.sc-visual .sc-title', {
scaleY: 5,
})
.from('.sc-visual .link-more', {
duration: 0.5,
opacity: 0,
bottom: '200px',
})
.from('.rotate-article', {
duration: 0.5,
opacity: 0,
})
.to('.sc-visual .group-right .img-box', {
opacity: 1,
})
.to('.sc-visual .group-right .img-box', {
y: '15px',
repeat: -1,
yoyo: true,
ease: Power1.easeInOut,
});
gsap.timeline
์ visualAni
๋ผ๋ ๋ณ์์ ๋ด์ ํ์๋ผ์ธ์ ์ค์ ํ์ต๋๋ค
์ฒซ ๋ฒ์งธ๋ก ํ
์คํธ -> ๋งํฌ ๋ฒํผ -> ๋๊ทธ๋ผ๋ฏธ ์ํฐํด -> ์ค๋ฅธ์ชฝ ์ด๋ฏธ์ง ๋ฐ์ค๋ก ์ค์ ํ๊ณ ,
๊ฐ๊ฐ ๊ณ ์ ํ CSS ์์ฑ๊ฐ์ ์ ์ด ์ฃผ์์ต๋๋ค