EQL

seung weon, seoΒ·2024λ…„ 6μ›” 7일
0

project

λͺ©λ‘ 보기
7/8
post-thumbnail

🌿 EQL

  • ν”„λ‘œμ νŠΈ 이름: EQL
  • μ‚¬μš©ν•œ μ–Έμ–΄: HTML, SCSS, JavaScript, jQuery
  • μ‚¬μš©ν•œ JavaScript 라이브러리: GSAP (ScrollTrigger)

Image Roll λ§Œλ“€κΈ°

HTML

<div class="img-roll">
	<img src="./assets/images/roll1.jpg" alt="">
	<img src="./assets/images/roll2.jpg" alt="">
	...
</div>

SCSS

img{
	position: absolute;
	top: 0;left: 0;
	 width: 100%;
	height: 100%;
	object-fit: cover;
	visibility: hidden;
	}

GSAP

gsap.to('.sc-header .group-images .img-roll img',{
    visibility:'visible',
    stagger:{
        each: 0.1,
    }
});
  1. 각 μ΄λ―Έμ§€μ˜ CSS에 visiblity: hidden 처리 ν•˜κΈ°

  2. gsap.toλ₯Ό μ‚¬μš©ν•˜μ—¬ img의 경둜λ₯Ό 뢈러온 ν›„ 이미지듀이 보일수 있게 visiblity:'visible' μž‘μ„±ν•˜κΈ°

  3. gsap의 stagger / eachλ₯Ό ν™œμš©ν•˜μ—¬ 각 이미지듀이 0.1초 뒀에 순차적으둜 보일수 있게 ν•˜κΈ°

stagger / each

staggerλŠ” 일련의 μš”μ†Œλ“€μ„ μ§€μ •λœ μ‹œκ°„ κ°„κ²©μœΌλ‘œ 순차적으둜 μ• λ‹ˆλ©”μ΄μ…˜ν™”ν•˜λŠ” 데 μ‚¬μš©λ˜λ©° eachλŠ” 각 μš”μ†Œλ“€μ˜ μ‹œμž‘ μ‹œκ°„ 간격을 λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

Clamp() ν•¨μˆ˜

clamp(min, val, max);

clamp() ν•¨μˆ˜λŠ” CSS의 κ°’ λ²”μœ„λ₯Ό μ •μ˜ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” ν•¨μˆ˜λ‘œ μ΅œμ†Œ, μ΅œλŒ€, 및 ν˜„μž¬ κ°’μœΌλ‘œ 이루어진 μ„Έ 가지 λ§€κ°œλ³€μˆ˜λ₯Ό κ°€μ§‘λ‹ˆλ‹€.

width: clamp(36px,4.5vw,64px);

width의 μ΅œμ†Œ κ°’=36px, ν˜„μž¬ κ°’=4.5vw, μ΅œλŒ€ κ°’=64px

μ—¬κΈ°μ„œwidthλŠ” ν˜„μž¬ κ°’ 4.5vwλŠ” 36px보닀 μž‘μ•„μ§ˆ 수 μ—†μœΌλ©° 64px보닀 컀질 수 μ—†μŠ΅λ‹ˆλ‹€.
*λ°˜μ‘ν˜• μ›Ήμ‚¬μ΄νŠΈμ—μ„œ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

둜고 μ• λ‹ˆλ©”μ΄μ…˜ (stroke-dashoffset ν™œμš©)

둜고 μ• λ‹ˆλ©”μ΄μ…˜μ—μ„œ μ‚¬μš©ν•œ stroke-dashoffset 속성은 SVGμ—μ„œ μ„ μ˜ νŒ¨ν„΄μ„ μ œμ–΄ν• λ•Œ ν™œμš©λ˜λŠ” 속성 쀑 ν•˜λ‚˜λ‘œ 주둜 μ„ μ΄λ‚˜ κ²½λ‘œκ°€ κ·Έλ €μ§€λŠ” μ• λ‹ˆλ©”μ΄μ…˜μ„ λ§Œλ“€ λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.

  1. 둜고 μ•ˆμ— ν¬ν•¨λœ μ„ μ˜ 길이 μ°ΎκΈ° (보톡 μ—¬λŸ¬ 값을 μž…λ ₯해보며 μ°Ύμ•„μ•Ό 함)
    *μœ„ μ˜ˆμ‹œμ˜ κ²½μš°μ—λŠ” 20μ΄μ—ˆμŠ΅λ‹ˆλ‹€.

  2. stroke-dashoffsetκ³Ό stroke-dasharray의 값을 κ°™κ²Œ μ£Όμ–΄ ν™”λ©΄ μƒμ—μ„œ 보이지 μ•Šκ²Œ ν•˜κΈ°

  3. μ• λ‹ˆλ©”μ΄μ…˜μ΄ μ‹œμž‘ν•  λ°©ν–₯을 stroke-dashoffset의 값을 λ°”κΏ”λ³΄λ©΄μ„œ μ •ν•˜κΈ°
    *μœ„ μ˜ˆμ‹œμ˜ κ²½μš°μ—λŠ” 20μ—μ„œ 0으둜 κ°€λ©΄ 였λ₯Έμͺ½ λ°©ν–₯, 20μ—μ„œ 40으둜 κ°€λ©΄ μ™Όμͺ½ λ°©ν–₯으둜 μ• λ‹ˆλ©”μ΄μ…˜μ΄ μ μš©λ©λ‹ˆλ‹€.

  4. μœ„μ—μ„œ 찾은 값듀을 λ°”νƒ•μœΌλ‘œstroke-dashoffset에 @keyframes μ •μ˜ν•˜κΈ°
    *μœ„ μ˜ˆμ‹œμ—μ„œλŠ” μœ„μ˜ μ„ κ³Ό μ•„λž˜ 선이 λ°˜λŒ€λ‘œ κ·Έλ €μ§€λŠ” λŠλ‚Œμ„ μ£ΌκΈ° μœ„ν•΄ 각각 λ‹€λ₯Έ 값을 μ£Όμ—ˆμŠ΅λ‹ˆλ‹€.

  5. 각 선에 animation μΆ”κ°€ν•˜κΈ°

Grid 1/-1 λ ˆμ΄μ•„μ›ƒ

grid-column: 1/-1; grid-row: 1/-1;은 κ·Έλ¦¬λ“œ μ•„μ΄ν…œμ΄ κ·Έλ¦¬λ“œ μ»¨ν…Œμ΄λ„ˆμ—μ„œ 첫 번째 μ—΄(1)λΆ€ν„° λ§ˆμ§€λ§‰ μ—΄(-1)κΉŒμ§€, κ·Έλ¦¬λ“œ μ»¨ν…Œμ΄λ„ˆμ˜ 첫 번째 ν–‰λΆ€ν„° λ§ˆμ§€λ§‰ ν–‰κΉŒμ§€ ν™•μž₯λ˜λ„λ‘ λ§Œλ“€μ–΄ μ€λ‹ˆλ‹€. μœ„μ˜ μ˜ˆμ‹œλ₯Ό 보면 λΆ€λͺ¨ ν΄λž˜μŠ€μ— λ„ˆλΉ„μ™€ 높이λ₯Ό 100%μ”© μ£Όκ³  κ·Έλ¦¬λ“œλ₯Ό λ§Œλ“€λ©΄ 마치 absolute ν¬μ§€μ…˜μ„ μ“΄ κ²ƒμ²˜λŸΌ κ·Έλ¦¬λ“œ μ•„μ΄ν…œλ“€μ΄ ν¬κ°œμ§„ 것을 λ³Ό 수 있으며 μ΄λŠ” μ΄λ―Έμ§€λ‚˜ μ—¬λŸ¬ μš”μ†Œλ₯Ό ν•œ 곡간에 겹쳐놓을 λ•Œ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

동적 뷰포트 λ‹¨μœ„(dvh / dvw)

dvh(Dynamic Viewport Height)λŠ” μ£Όμ†Œ ν‘œμ‹œμ€„μ˜ μœ λ¬΄μ™€ 관계 없이 ν˜„μž¬ λ³΄μ—¬μ§€λŠ” 뷰포트 높이λ₯Ό λ™μ μœΌλ‘œ κ°€μ Έμ˜΅λ‹ˆλ‹€. 슀크둀 μ‹œ μ£Όμ†Œμ°½μ΄ μ‚¬λΌμ§€λŠ” λͺ¨λ°”일 λΈŒλΌμš°μ €μ—μ„œλ„ (주둜 Safariμ—μ„œ) 문제 없이 νŠΉμ • μš”μ†Œμ˜ 높이λ₯Ό λΈŒλΌμš°μ €μ˜ ν™”λ©΄ 높이와 맞좜 수 μžˆμŠ΅λ‹ˆλ‹€.

Variable 폰트

Variable fontsλŠ” μ—¬λŸ¬ 가지 μŠ€νƒ€μΌκ³Ό λ‘κ»˜μ˜ 좕을 가진 단일 폰트 파일둜 폰트의 μŠ€νƒ€μΌ, κ΅΅κΈ°, κΈ°μšΈμž„, λ„ˆλΉ„ 등을 μœ μ—°ν•˜κ²Œ μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

@font-face {
    font-family: Indivisible;
    src: url('../fonts/IndivisibleVariable.f64f7f53.woff2') format('woff2');
    font-weight: 100 1000; // 100λΆ€ν„° 1000κΉŒμ§€ 폰트 κ΅΅κΈ°λ₯Ό 자유둭게 쑰절 κ°€λŠ₯
}

랜덀 κΈ€μž μ• λ‹ˆλ©”μ΄μ…˜

HTML

<h2 class="title">
	<span>160λ…„</span> <span>역사λ₯Ό</span> <span>μ§€λ‹Œ</span> <span>HUNTERλŠ”</span>
	<span>ν΄λž˜μ‹ν•œ</span> <span>νŒ¨μ…˜</span> <span>μ•„μ΄ν…œμœΌλ‘œ</span>
	<span>μ „ μ„Έκ³„μ˜</span> <span>λ§Žμ€</span> <span>μ΄λ“€μ˜</span> <span>μ‚¬λž‘μ„</span>
	<span>λ°›μ•„</span><span>였고</span> <span>μžˆμŠ΅λ‹ˆλ‹€.</span>
    <br><br>
	<span>헀리티지에</span> <span>좩싀함과</span> <span>λ™μ‹œμ—</span> <span>λŠμž„μ—†λŠ”</span>
	<span>λ””μžμΈ</span> <span>ν˜μ‹ μ„</span> <span>톡해</span> <span>μ§„ν™”ν•˜κ³ </span>
	<span>μžˆλŠ”</span> <span>λΈŒλžœλ“œ</span> <span>ν—Œν„°λ₯Ό</span> <span>EQLμ—μ„œ</span> <span>λ§Œλ‚˜λ³΄μ„Έμš”.</span>
</h2>

JavaScript / jQuery

titleArr = $('.sc-hunter .group-hunter h2 span').toArray();
function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
    };
};
shuffleArray(titleArr);
ScrollTrigger.create({
    trigger:'.sc-hunter',
    start: "0% 50%",
    onEnter:function(){
		titleArr.forEach(function(el,i){
            gsap.to(el,{
                opacity: 1,
                duration: 1,
                delay: i * 0.12, 
            });
        });
    },
});
  1. 랜덀 μ• λ‹ˆλ©”μ΄μ…˜μ„ μ μš©ν•  κΈ€μžλ“€μ„ λ°°μ—΄λ‘œ λ§Œλ“€μ–΄ λ³€μˆ˜ titleArr에 μ €μž₯ν•˜κΈ°

  2. Fisher-Yates μ•Œκ³ λ¦¬μ¦˜μ— κ·Όκ±°ν•˜μ—¬ 배열을 λ¬΄μž‘μœ„λ‘œ λ§Œλ“œλŠ” ν•¨μˆ˜ shuffleArray λ§Œλ“€κΈ°

Fisher-Yates μ•Œκ³ λ¦¬μ¦˜μ΄λž€?

Fisher-Yates μ•Œκ³ λ¦¬μ¦˜μ€ λ°°μ—΄μ˜ μš”μ†Œλ₯Ό μž„μ˜μ˜ μˆœμ„œλ‘œ μ„žλŠ” 데 μ‚¬μš©λ˜λŠ” μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ 각 μΈλ±μŠ€μ™€ κ·Έ μ΄ν›„μ˜ λ¬΄μž‘μœ„ 인덱슀 쀑 ν•˜λ‚˜λ₯Ό μ„ νƒν•˜μ—¬ 두 μΈλ±μŠ€μ— ν•΄λ‹Ήν•˜λŠ” μš”μ†Œλ₯Ό κ΅ν™˜ν•©λ‹ˆλ‹€. 이λ₯Ό λ°°μ—΄μ˜ λκΉŒμ§€ λ°˜λ³΅ν•¨μœΌλ‘œμ¨ λ°°μ—΄ 전체λ₯Ό μ„žμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) { - λ°°μ—΄μ˜ λ§ˆμ§€λ§‰λΆ€ν„° μ²˜μŒκΉŒμ§€ (i--) 
    const j = Math.floor(Math.random() * (i + 1)); - Math.random ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 0μ—μ„œ iκΉŒμ§€ λ¬΄μž‘μœ„μ˜ 인덱슀 선택
    [array[i], array[j]] = [array[j], array[i]]; - i번째 μš”μ†Œμ™€ j번째 μš”μ†Œμ˜ μœ„μΉ˜λ₯Ό λ°”κΏˆ
    };
};
  1. λ³€μˆ˜ titleArr을 shuffleArray ν•¨μˆ˜μ— λ„£κΈ°

  2. ScrollTrigger의 onEnter ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ μœˆλ„μš° 50% μœ„μΉ˜μ— 트리거 μ‹œμž‘ 지점이 λ„λ‹¬ν–ˆμ„λ•Œ μ• λ‹ˆλ©”μ΄μ…˜μ΄ 싀행될 수 μžˆλ„λ‘ λ§Œλ“€κΈ°

  3. titleArr둜 forEach 반볡문 ν•¨μˆ˜ λ§Œλ“€κΈ° (λ§€κ°œλ³€μˆ˜ el, i)

  4. gsap.toλ₯Ό μ‚¬μš©ν•˜μ—¬ 각 μ—˜λ¦¬λ¨ΌνŠΈλ“€μ— delay와 opacity 값을 μ£Όμ–΄μ„œ 각각 λ”œλ ˆμ΄λ₯Ό 가진 μƒνƒœλ‘œ 화면에 보일 수 μžˆλ„λ‘ λ§Œλ“€κΈ°

mousemove μ• λ‹ˆλ©”μ΄μ…˜

HTML

<section class="sc-openyy">
	...
	<svg class="shape-move" viewBox="" fill="currentColor" preserveAspectRatio="none" style="">	
		<rect x="0" y="0" width="75" height="504.5" class="shape-rect"></rect>
		<rect x="75" y="504.5" width="6" height="504.5" class="shape-rect"></rect>
    	...
	</svg>
</section>

JavaScript / jQuery

$('.sc-openyy').mousemove(function(e){
	const mouseY = e.offsetY;
	const containerHeight = $(this).height();
	const mouseY2 = containerHeight - e.offsetY;
	gsap.to('.sc-openyy .shape-move .shape-rect:nth-child(odd)',{
		height: mouseY,
		duration: 0,
	});
	gsap.to('.sc-openyy .shape-move .shape-rect:nth-child(even)',{
		height: mouseY2,
		y:mouseY - 504.5,
		duration: 0,
	});
    gsap.to('.sc-openyy .shape-move .shape-rect',{
		width: 'random(1,90)',
		x: 'random(-90,90)',
		duration: 0.1,
	});
});
  1. μ• λ‹ˆλ©”μ΄μ…˜μ„ ν™œμ„±ν™” ν•  μ»¨ν…Œμ΄λ„ˆ .sc-openyy에 mousemove 이벀트 μΆ”κ°€ν•˜κΈ° (λ§€κ°œλ³€μˆ˜ e)

  2. 마우슀의 yμ’Œν‘œλ₯Ό λ³€μˆ˜ mouseY에 μ €μž₯

  3. μ»¨ν…Œμ΄λ„ˆ .sc-openyy의 높이 값을 λ³€μˆ˜ containerHeight에 μ €μž₯

  4. .sc-openyy의 높이 κ°’μ—μ„œ 마우슀의 yμ’Œν‘œλ₯Ό λΊ€ 값을 λ³€μˆ˜ mouseY2에 μ €μž₯

  5. svgμ•ˆμ— μžˆλŠ” λ§‰λŒ€λ“€μ˜ :nth-child(odd) ν™€μˆ˜ 클래슀(μœ— λ§‰λŒ€λ“€)에 gsap.toλ₯Ό μ‚¬μš©ν•˜μ—¬ mouseYλ₯Ό 높이 κ°’μœΌλ‘œ μ£ΌκΈ°
    *마우슀λ₯Ό yμΆ• λ°©ν–₯으둜 움직일 λ•Œ μœ— λ§‰λŒ€λ“€μ΄ 마우슀 μ»€μ„œλ₯Ό λ”°λΌμ˜€κ²Œ λ©λ‹ˆλ‹€.

  6. :nth-child(even) 짝수 클래슀(μ•„λž« λ§‰λŒ€λ“€)μ—λŠ” mouseY2λ₯Ό 높이 κ°’μœΌλ‘œ μ£ΌκΈ°
    *mouseY2λŠ” 전체 λ†’μ΄μ—μ„œ mouseY 즉 e.offsetYλ₯Ό λΊ€ κ°’μœΌλ‘œ λ‚˜λ¨Έμ§€ 곡간을 μ°¨μ§€ν•˜κ²Œ λ©λ‹ˆλ‹€.

  7. mouseYμ—μ„œ 504.5λ₯Ό λΊ€ 값을 짝수 클래슀의 y κ°’μœΌλ‘œ μ£Όμ–΄ μ΄ˆκΈ°ν™” μ‹œν‚€κΈ°
    *504.5λŠ” μ›λž˜ svg에 μžˆμ—ˆλ˜ yκ°’μž…λ‹ˆλ‹€.

  8. gsap의 λžœλ€ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ 마우슀λ₯Ό 움직일 λ•Œ 각 λ§‰λŒ€μ˜ width와 xμ’Œν‘œ 값을 λžœλ€ν•˜κ²Œ μ£ΌκΈ°
    *widthλŠ” 1pxλΆ€ν„° 90pxκΉŒμ§€, xμ’Œν‘œ 값은 μ›λž˜μ˜ κ°’μ—μ„œ +-90

profile
to reach new possibilities

0개의 λŒ“κΈ€