๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Javascript Effect

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒจ๋Ÿด๋ž™์Šค ํšจ๊ณผ : ํ…์ŠคํŠธ ํšจ๊ณผ

by ์ฝ”ํŒŒ์นด 2022. 9. 29.
728x90

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ : ํŒจ๋Ÿด๋ž™์Šค ํšจ๊ณผ : ํ…์ŠคํŠธ ํšจ๊ณผ

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋‹ค์–‘ํ•œ ํšจ๊ณผ๋“ค ์ค‘, ํŒจ๋Ÿด๋ž™์Šค ํšจ๊ณผ์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ์Šคํฌ๋กค์„ ๋‚ด๋ฆด ๋•Œ๋งˆ๋‹ค ํ•ด๋‹นํ•˜๋Š” ์„น์…˜์˜ ํ…์ŠคํŠธ๊ฐ€ ํ•œ ๊ธ€์ž์”ฉ ๋‚˜ํƒ€๋‚˜๋„๋ก ์ž‘์—…ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


1. ๊ธ€์”จ ์ชผ๊ฐœ๊ธฐ

document.querySelectorAll(".split").forEach((text) => {
    let splitText = text.innerText;
    let splitWrap = splitText.split("").join("</span><span aria-hidden='true'>");
    splitWrap = "<span aria-hidden='true'>" + splitWrap + "</span>";
    text.innerHTML = splitWrap;

    // p ํƒœ๊ทธ(split)์— label ์†์„ฑ ์ถ”๊ฐ€
    text.setAttribute("aria-label", splitText);
});

๊ธ€์ž๊ฐ€ ํ•˜๋‚˜์”ฉ ๋‚˜ํƒ€๋‚˜๋„๋ก ํ•˜๋ ค๋ฉด, ๋ชจ๋“  ๊ธ€์ž๊ฐ€ ํ•œ ๊ธ€์ž์”ฉ span ํƒœ๊ทธ์— ๋‹ด๊ฒจ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 9๊ฐœ์˜ ์„น์…˜ ์† ๊ธ€์ž๋ฅผ ๋ชจ๋‘ ์ง์ ‘ HTML๋กœ ์ชผ๊ฐค ์ˆ˜๋Š” ์—†์œผ๋‹ˆ, ์Šคํฌ๋ฆฝํŠธ๋กœ ์ž‘์—…ํ•ด ์ค๋‹ˆ๋‹ค.
split์€ ๊ฐ ์„น์…˜์˜ ํ…์ŠคํŠธ ๋ฐ•์Šค์ž…๋‹ˆ๋‹ค. ์„น์…˜๋งˆ๋‹ค ํ…์ŠคํŠธ ๋ฐ•์Šค๋Š” ์กด์žฌํ•˜๋ฏ€๋กœ, ์ด 9๊ฐœ์˜ split์ด ์กด์žฌํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— querySelectorAll์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ ํƒํ•ด ์ค๋‹ˆ๋‹ค. splitText ๋ณ€์ˆ˜๋Š” ๊ฐ๊ฐ์˜ split์— ์ ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ split ๋ฐ•์Šค์— split(), join() ๋ฉ”์„œ๋“œ๋ฅผ ์ฐจ๋ก€๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์—์„œ๋Š” ์ ‘๊ทผ์„ฑ ํ–ฅ์ƒ์„ ์œ„ํ•ด, split(p ํƒœ๊ทธ)์— ์ „์ฒด ๋ฌธ์žฅ์„ ์ž‘์„ฑํ•œ aria-label์„ ์ถ”๊ฐ€ํ•ด ์ฃผ๊ณ , ํ•œ ๊ธ€์ž์”ฉ์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ๊ฐ์˜ span์— aria-hidden='true'๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

split() ๋ฉ”์„œ๋“œ๋Š” ๋ฌธ์ž์—ด์—์„œ ์›ํ•˜๋Š” ๊ฐ’์„ ์ถ”์ถœํ•˜์—ฌ ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. join() ๋ฉ”์„œ๋“œ๋Š” ๋ฐฐ์—ด์˜ ๋ชจ๋“  ์š”์†Œ๋ฅผ ์—ฐ๊ฒฐํ•ด ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
"์•ˆ๋…•ํ•˜์„ธ์š”"๋ผ๋Š” ๊ธ€์ž๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, split('') ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด "์•ˆ","๋…•","ํ•˜","์„ธ","์š”"๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ์ดํ›„ join("<span></span>") ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด "์•ˆ<span></span>๋…•<span></span>ํ•˜<span></span>์„ธ<span></span>์š”"๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

2. scroll ์ด๋ฒคํŠธ ๋งŒ๋“ค์–ด ์ฃผ๊ธฐ

function scroll() {
    let scrollTop = window.scrollY;
    document.querySelector("#parallax__info .scroll").innerText = Math.round(scrollTop);

    requestAnimationFrame(scroll);
}
scroll();

๋จผ์ €, scroll ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. scroll ์ด๋ฒคํŠธ๋Š” requestAnimationFrame์œผ๋กœ ์ž‘์—…ํ•ด ์ฃผ๋Š” ๊ฒƒ์ด ๋ฒ„๋ฒ…๊ฑฐ๋ฆผ์„ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. scrollTop์˜ ๊ฐ’์€ scrollY๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์นœ์ ˆํ•˜๊ฒŒ info ๋ฐ•์Šค์—๋„ ์ถœ๋ ฅํ•ด ์ค์‹œ๋‹ค.
์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋Š” CSS๋กœ๋„, JAVASCRIPT๋กœ๋„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2-1) CSS๋กœ ํšจ๊ณผ ์ฃผ๊ธฐ

document.querySelectorAll(".content__item").forEach((item) => {
    if (scrollTop >= item.offsetTop - 500) {
        item.querySelector(".split").classList.add("show");
    }
});

content__item์€ split์˜ ๋ถ€๋ชจ ๋ฐ•์Šค์ž…๋‹ˆ๋‹ค. split์„ ์ง์ ‘ ์„ ํƒํ•˜๋ฉด ๋ชจ๋“  ํ…์ŠคํŠธ๊ฐ€ ๋™์‹œ์— ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋˜๋ฏ€๋กœ, ์ƒ์œ„ ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•˜๊ณ , if๋ฌธ ์•ˆ์—์„œ split์„ ์„ ํƒํ•ด ์ค์‹œ๋‹ค. ๊ฐ ์„น์…˜์— scroll์ด ์œ„์น˜ํ–ˆ์„ ๋•Œ, split์— show ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ๋ฉด ๋˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ด์ง€๋งŒ, ์•„๋ž˜ ์†Œ์Šค์ฒ˜๋Ÿผ CSS๋กœ span์— ๊ฐ๊ฐ transition-delay๋ฅผ ์ง€์ •ํ•ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค... ํž˜๋“ญ๋‹ˆ๋‹ค.

๋…ธ๊ฐ€๋‹ค์˜ ํ”์ 
.split span {
    opacity: 0;
    transform: translateY(50px);
    transition: all 0.3s cubic-bezier(0, 0.71, 0.11, 1.66);
    /* transform์€ block ๊ตฌ์กฐ๋งŒ ๋จนํžŒ๋‹ค! */
    display: inline-block;
    /* block ๊ตฌ์กฐ๋กœ ๋ฐ”๊พธ๋ฉด ๋„์–ด์“ฐ๊ธฐ๊ฐ€ ์‚ฌ๋ผ์ง€๋ฏ€๋กœ, ์ตœ์†Œ ๋„ˆ๋น„๋ฅผ ์ง€์ •ํ•ด์ฃผ๊ธฐ */
    min-width: 1vw;
}
.split.show span {
    opacity: 1;
    transform: translateY(0);
}
.split span:nth-child(1) {
    transition-delay: 100ms;
}
.split span:nth-child(2) {
    transition-delay: 150ms;
}
.split span:nth-child(3) {
    transition-delay: 200ms;
}
.split span:nth-child(4) {
    transition-delay: 250ms;
}
.split span:nth-child(5) {
    transition-delay: 300ms;
}
.split span:nth-child(6) {
    transition-delay: 350ms;
}
.split span:nth-child(7) {
    transition-delay: 400ms;
}
.split span:nth-child(8) {
    transition-delay: 450ms;
}
.split span:nth-child(9) {
    transition-delay: 500ms;
}
.split span:nth-child(10) {
    transition-delay: 550ms;
}
.split span:nth-child(11) {
    transition-delay: 600ms;
}
.split span:nth-child(12) {
    transition-delay: 650ms;
}
.split span:nth-child(13) {
    transition-delay: 700ms;
}
.split span:nth-child(14) {
    transition-delay: 750ms;
}
.split span:nth-child(15) {
    transition-delay: 800ms;
}
.split span:nth-child(16) {
    transition-delay: 850ms;
}
.split span:nth-child(17) {
    transition-delay: 900ms;
}
.split span:nth-child(18) {
    transition-delay: 950ms;
}
.split span:nth-child(19) {
    transition-delay: 1000ms;
}
.split span:nth-child(20) {
    transition-delay: 1050ms;
}
.split span:nth-child(21) {
    transition-delay: 1100ms;
}
.split span:nth-child(22) {
    transition-delay: 1150ms;
}
.split span:nth-child(23) {
    transition-delay: 1200ms;
}
.split span:nth-child(24) {
    transition-delay: 1250ms;
}
.split span:nth-child(25) {
    transition-delay: 1300ms;
}
.split span:nth-child(26) {
    transition-delay: 1350ms;
}
.split span:nth-child(27) {
    transition-delay: 1400ms;
}
.split span:nth-child(28) {
    transition-delay: 1450ms;
}
.split span:nth-child(29) {
    transition-delay: 1500ms;
}
.split span:nth-child(30) {
    transition-delay: 1550ms;
}
.split span:nth-child(31) {
    transition-delay: 1600ms;
}
.split span:nth-child(32) {
    transition-delay: 1650ms;
}
.split span:nth-child(33) {
    transition-delay: 1700ms;
}
.split span:nth-child(34) {
    transition-delay: 1750ms;
}
.split span:nth-child(35) {
    transition-delay: 1800ms;
}
.split span:nth-child(36) {
    transition-delay: 1850ms;
}
.split span:nth-child(37) {
    transition-delay: 1900ms;
}
.split span:nth-child(38) {
    transition-delay: 1950ms;
}
.split span:nth-child(39) {
    transition-delay: 2000ms;
}
.split span:nth-child(40) {
    transition-delay: 2050ms;
}
.split span:nth-child(41) {
    transition-delay: 2100ms;
}
.split span:nth-child(42) {
    transition-delay: 2150ms;
}
.split span:nth-child(43) {
    transition-delay: 2200ms;
}
.split span:nth-child(44) {
    transition-delay: 2250ms;
}

2-2) JAVASCRIPT๋กœ ํšจ๊ณผ ์ฃผ๊ธฐ

document.querySelectorAll(".content__item").forEach((item) => {
    if (scrollTop >= item.offsetTop - 500) {
        item.querySelector(".split").classList.add("show");
        item.querySelectorAll(".split span").forEach((span, index) => {
            span.style.transitionDelay = 100 + 50 * index + "ms";
        });
    }
});

์ด๋ฒˆ์—๋Š” JAVASCRIPT์ž…๋‹ˆ๋‹ค. forEach๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋จผ์ € split์— show ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ๊ณ , ๊ฐ๊ฐ์˜ span์— forEach๋ฌธ์„ ์‚ฌ์šฉํ•ด ์ค๋‹ˆ๋‹ค. transitionDelay์˜ ์ดˆ๊ธฐ๊ฐ’์€ 100ms๋กœ ์ง€์ •ํ•˜๊ณ , index๋ฅผ ๊ณฑํ•ด์ฃผ์–ด 50ms์”ฉ ์ฆ๊ฐ€ํ•˜๊ฒŒ ์ž‘์—…ํ•ด ์ฃผ๋ฉด ์™„์„ฑ์ž…๋‹ˆ๋‹ค.


๊ฒฐ๊ณผ

728x90

๋Œ“๊ธ€

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๐Ÿฆ™

CSS
๊ด‘๊ณ  ์ค€๋น„์ค‘