๐ป HYBE coding
์ฌ์ดํธ๋ช
: HYBE
์ฌ์ฉ์ธ์ด : html / scss / js
๋ถ๋ฅ : ์ ์ํ PC / ๋ฐ์ํ
๐ HYBE HOMEPAGE
https://hybecorp.com/kor/company/artist
๐ ๊ธฐ๋ณธ์๋ฆฌ
: gsapํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ์ฌ, ์์ฐจ์ ์ธ ์ ๋๋ฉ์ด์
์ ๊ตฌํํจ
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.2/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.2/ScrollTrigger.min.js"></script>
โ๐ป ์ฝ๋์์ฑ
<div id="loading">
<div class="loading-txt">
<div class="wrap">
<span class="first">H</span>
<span class="sec">Y</span>
<span class="sec">B</span>
<span class="sec">E</span>
</div>
</div>
</div>
.wrap{
overflow: hidden;
padding: 0 10px;
transform: translateX(20%);
}
span{
font-size: 15vw;
font-weight: 900;
color: $color-main;
display: inline-block;
transform: translateY(100%);
}
โ๐ป ์ฝ๋์์ฑ
const intro = gsap.timeline({
defaults:{
},
onComplete:function(){ ๐๐ป ์๋ฃ๋ํ์
scaleIntro.play();
}
})
intro
.addLabel('a')
.to('#loading .first',1,{yPercent: -95},'a')
.to('#loading .sec',1,{yPercent: -95, stagger:0.1},'a+=0.2')
.to('#loading .wrap',0.5,{xPercent:-20},'a+=0.5')
.to('#loading',1,{height:0})
const scaleIntro = gsap.from('.sc-visual .visual-bg img',0.5,{
scale:1.2,
paused:true,
})
โ gsap.timeline : gsap๋ฅผ ํ๊บผ๋ฒ์ ๋ฌถ์ด ์์ฐจ์ ์ผ๋ก ์คํํ๋ ๋ฉ์๋
โ addLabel : gsap๋ฅผ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด, ๋์์ ์ ๋๋ฉ์ด์
์ ์ฉํ๋ ๋ฉ์๋
๐ ๊ธฐ๋ณธ์๋ฆฌ
: ์๋๋์์์ ์ฐธ๊ณ ํ์ฌ ์ฝ๋์ ์ฉ
๐๐ป ๊ตฌํํด์ผ๋๋ ๋ชจ์ต
: text-in๊ณผ text-out์ผ๋ก ์ปจํธ๋กคํ์ฌ ๊ณ์ ๋กค๋ง๋๊ฒ ํ์ฌ์ผํจ
โ๐ป ์ฝ๋์์ฑ
<div class="visual-content">
<h2 class="title">
<div class="title-list">
<span class="title-item">BTS</span>
<span class="title-item">LEE HYUN</span>
<span class="title-item">LE SSERAFIM</span>
<span class="title-item">NewJeans</span>
<span class="title-item">SEVENTEEN</span>
<span class="title-item">ENHYPEN</span>
<span class="title-item">TXT</span>
</div>
HYBE ARTIST
</h2>
</div>
const txts = document.querySelector('.title-list').children;
txtsLen = txts.length;
let index = 0;
function aniMate1() {
for (let i = 0; i < txtsLen; i++) {
txts[i].classList.remove('text-in', 'text-out');
}
txts[index].classList.add('text-in');
}
function aniMate2() {
txts[index-1].classList.add('text-out');
}
setInterval(function () {
aniMate2()
}, 3500);
setInterval(function () {
if (index == txtsLen - 1) {
index = 0;
}
else {
index++;
}
aniMate1()
}, 3000);
๐ ๊ธฐ๋ณธ๋ฌธ๋ฒ
: ์ด๋ค ์ง์ ์ ๋๋ฌํ๋ฉด ์คํฌ๋กค ํ๋๋ผ๋ ๋ฐฐ๊ฒฝ์ ์ ์ง๋ ์ฑ, ์ํ ๋ฐฉํฅ์์ ์์๊ฐ ๋ฑ์ฅํ๋ ํจ๊ณผ๊ฐ ๋ชฉ์
scrollTrigger:{
trigger:"๊ธฐ์ค์ด๋ ํ๊ทธ",
start:"top top", ๐๐ป ๊ธฐ์คํ๊ทธ์ ์์์ง์ , ์๋์ฐ๊ธฐ์ค ์์์ง์
end:"bottom top" ๐๐ป ๊ธฐ์คํ๊ทธ์ ๋์ง์ , ์๋์ฐ๊ธฐ์ค ๋์ง์
markers:true, ๐๐ป ์ธ๋์ผ์ดํฐ๋ฅผ ํ์
scrub:1 ๐๐ป ๋๊ฐ๊ธฐ(์คํฌ๋กค์ด ์์ ์ด์ ์ผ๋ก ๋์๊ฐ๋ฉด ์ ๋๋ฉ์ด์
์ญ์ ๋๋์๊ฐ๋ ๊ธฐ๋ฅ)
}
๐๐ป ๊ตฌํํด์ผ๋๋ ๋ชจ์ต
const viewSlide = gsap.timeline({
defaults:{
ease:'none',
},
scrollTrigger:{
trigger:'.sc-view',
start:'top top',
end:'+=800%', ๐๐ป ๊ฐ์ด ํด์๋ก ์คํฌ๋กค์ด ์ฒ์ฒํ๋
scrub:1,
markers:true, ๐๐ป ์์๊ณผ ๋์์น ํ์ธ
pin:true, ๐๐ป ๊ณ ์
},
})
gsap.set('.sc-view .img-item .item01',{ scale:1.3 })
gsap.set('.sc-view .img-item .item02',{ rotate:30, })
gsap.set('.sc-view .img-item .item03',{ rotate:-10,scale:0.8 })
gsap.set('.sc-view .img-item .item05',{ rotate:-50,scale:1.5 })
gsap.set('.sc-view .img-item .item05',{ scale:1.1 })
gsap.set('.sc-view .img-item .item07',{ rotate:-120})
gsap.set('.sc-view .img-item .item08',{ rotate:20,scale:1.2 })
gsap.set('.sc-view .img-item .item09',{ rotate:45})
gsap.set('.sc-view .img-item .img',{ yPercent:-50})
.addLabel('a')
.to('.sc-view .title',{ xPercent:-20 },'a')
.to('.sc-view .img-item',{ xPercent:-110 },'a')
.to('.sc-view .img-item .img',{ yPercent:100, stagger:0.02 },'a')
.to('.sc-view .img-item .item01',{ rotate:-90 },'a')
.to('.sc-view .img-item .item02',{ rotate:0 },'a')
.to('.sc-view .img-item .item03',{ rotate:0 },'a')
.to('.sc-view .img-item .item04',{ rotate:60 },'a')
.to('.sc-view .img-item .item05',{ rotate:0 },'a')
.to('.sc-view .img-item .item06',{ rotate:30 },'a')
.to('.sc-view .img-item .item07',{ rotate:0 },'a')
.to('.sc-view .img-item .item08',{ rotate:0 },'a')
.to('.sc-view .img-item .item09',{ rotate:0, left:'100px', bottom:'-150px' },'a+=.1')
๊ฐ์ฒด์ ์์น๋ฅผ ์ก๋๊ฒ point์๋ค.
๐ ๊ธฐ๋ณธ์๋ฆฌ
[์ฐธ๊ณ ์ฌ์ดํธ]
https://zzzmh.tistory.com/13
๐๐ป ๊ตฌํํด์ผ๋๋ ๋ชจ์ต
โ๐ป ์ฝ๋์์ฑ
function menuOpen() {
var target = document.querySelector('.menu');
var motion = document.querySelector('.open-btn');
target.addEventListener('mousemove', (event) => {
let x = (event.layerX * 0.1);
let y = (event.layerY * 0.1);
motion.style.transform = `translate(${x}px,${y}px)`
})
target.addEventListener('mouseout', (event) => {
motion.style.transform = '';
})
}
โ MouseEvent.layerX์ฝ๊ธฐ ์ ์ฉ ์์ฑ: ํ์ฌ ๋ ์ด์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ์ด๋ฒคํธ์ ์ํ ์ขํ๋ฅผ ๋ฐํ
โ MouseEvent.layerY์ฝ๊ธฐ ์ ์ฉ ์์ฑ: ํ์ฌ ๋ ์ด์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ์ด๋ฒคํธ์ ์์ง ์ขํ๋ฅผ ๋ฐํ
๐๐ป ๋ง์ฐ์ค ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ๋ ๋ง์ฐ์ค ํฌ์ธํฐ์ x ์ขํ์ ๋ํ ์ ์ ๊ฐ์ด ๋์ด
๐ ๊ธฐ๋ณธ์๋ฆฌ
[์ฐธ๊ณ ์ฌ์ดํธ]
https://codepen.io/jonathan/pen/XXdNjR
๐๐ป ๊ตฌํ๋ ๋ชจ์ต
1. transform-origin์์ฑ์ ์ฉ
<h2 class="title">
<span class="effect"><span class="em-txt">HYBE</span> is committed to satisfying</span>
<span class="effect">customers with the 'content' leading the</span>
<span class="effect"><span class="em-txt">global trend and our 'fans'</span></span>
</h2>
.title{
transform-origin: top left;
}
<span class="effect"> ๐๐ป ํจ๊ณผ๋ฅผ ์ฃผ๊ธฐ์ํด class๋ช
์ ๋ฃ์ด์ค
[์ฐธ๊ณ ์ฌ์ดํธ]
https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin
gsap.set(".sc-intro .effect", { ๐๐ป ๊ธฐ์ด์
ํ
rotationX: -45,
transformStyle: "preserve-3d",
transformOrigin: "0% 50% -100%",
opacity: 0,
yPercent: 110,
});
const introEffect = gsap.to('.sc-intro .effect', {
scrollTrigger:{
trigger:'.sc-intro',
start:'top 50%',
end:'bottom top',
},
transformStyle: "preserve-3d",
rotationX: 0,
duration:1,
opacity: 1,
yPercent: 0,
transformOrigin: "50% 50%",
stagger:0.1,
});
perspective: 400px;
โ ๋ถ๋ชจ์๊ฒ perspective ์์ฑ์ ์ฃผ๊ณ , ์ด๋ฒคํธ ๋์์๋ transform์ ์ํจ ๋ชจ์ต
โ ์ฌ๊ธฐ์์์ 400px์ '๋ด๊ฐ ์ผ๋ง๋ ๋จ์ด์ ธ์ ๋ณด๊ณ ์๋๊ฐ'๋ฅผ ๋ํ๋ธ๋ค๊ณ ํ ์ ์์
โ ๊ฐ์ด ์์ผ๋ฉด ์์ ์๋ก ๋ ๊ฐ๊น์ด์์ ๋ณด๋ ๊ฒ์ผ๋ก ์ฒ๋ฆฌ
[์ฐธ๊ณ ์ฌ์ดํธ]
https://nykim.work/26