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

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

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

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

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


1. HTML

<section id="section1" class="content__item">
    <span class="content__item__num">01</span>
    <h2 class="content__item__title">section1</h2>
    <figure class="content__item__imgWrap reveal reveal-TWO reveal-BTT">
        <div class="content__item__img"></div>
    </figure>
    <p class="content__item__desc split reveal reveal-TWO reveal-BTT">
        ๊ฒฐ๊ณผ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ, ๊ณผ์ •์„ ๋” ์ค‘์š”ํ•˜๊ฒŒ ์ƒ๊ฐํ•œ๋‹ค.
    </p>
</section>

์ด๋ฒˆ์— ์ž‘์—…ํ•  ๋ฆฌ๋นŒ ํšจ๊ณผ๋Š” ๊ต‰์žฅํžˆ ๋ณต์žกํ•˜๋ฉฐ, HTML, CSS, JAVASCRIPT ์„ธ ๊ฐ€์ง€ ์†Œ์Šค ๋ชจ๋‘๊ฐ€ ์ ˆ๋ฌ˜ํ•œ ํ•˜๋ชจ๋‹ˆ๋ฅผ ์ด๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์นœ์ ˆํ•˜๊ฒŒ HTML ์†Œ์Šค๋ฅผ ์‚ฝ์ž…ํ•˜๋‹ˆ, ์ด๊ฒƒ์„ ๋จผ์ € ์‚ดํŽด๋ณด๋„๋ก ํ•ฉ์‹œ๋‹ค.
์„น์…˜์€ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์ด 9๊ฐ€์ง€๋ฅผ ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์„น์…˜์€ ๋ฒˆํ˜ธ, ์ด๋ฏธ์ง€, ํ…์ŠคํŠธ๋กœ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ์›€์ง์ž„ ํšจ๊ณผ๋Š” reveal ํด๋ž˜์Šค์— ์ž‘์—…ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ์œ„์™€ ๊ฐ™์ด reveal(๊ธฐ๋ณธ), reveal-TWO(๋ฐ•์Šค ์ถ”๊ฐ€), reveal-XXX(๋ฐฉํ–ฅ)์œผ๋กœ ์„น์…˜๋‹น ์ตœ๋Œ€ 3๊ฐœ์˜ ํšจ๊ณผ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์›€์ง์ž„ ํšจ๊ณผ๋ฅผ ์ž‘์—…ํ•ด๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

2. CSS

2-1) reveal ํšจ๊ณผ ์ดˆ๊ธฐ๊ฐ’ ์ž‘์—…

.reveal > div,
.reveal > span {
    opacity: 0;
}
.reveal.show > div,
.reveal.show > span {
    animation: opacity 1s linear forwards;
}
.reveal {
    position: relative;
}
.reveal::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 100%;
    background: #fff;
    z-index: 1;
}
.reveal.reveal-TWO::after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    z-index: 1;
    height: 100%;
    background: rgb(46, 46, 46);
}

์„œ์„œํžˆ ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ดˆ๊ธฐ๊ฐ’์œผ๋กœ opacity: 0์„ ์„ค์ •ํ•ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋ฆฌ๋นŒ ํšจ๊ณผ์˜ ํ•ต์‹ฌ์€, before ๋ฐ after๋กœ ์ƒ์„ฑํ•œ ๋ฐ•์Šค๊ฐ€ ์ง€๋‚˜๊ฐ€๋Š” ํƒ€์ด๋ฐ์— ๋งž์ถ”์–ด ์ด๋ฏธ์ง€์™€ ํ…์ŠคํŠธ๊ฐ€ ๋“œ๋Ÿฌ๋‚˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2-2) keyframes ์ž‘์—…ํ•˜๊ธฐ

@keyframes opacity {
    0% { opacity: 0; }
    60% { opacity: 0; }
    70% { opacity: 1; }
    100% { opacity: 1; }
}
@keyframes reveal {
    0% { width: 0; left: 0; }
    50% { width: 100%; left: 0; }
    80% { width: 100%; left: 0; }
    100% { width: 0; left: 100%; }
}
@keyframes reveal-RTL {
    0% { width: 0; right: 0; left: auto; }
    50% { width: 100%; right: 0; left: auto; }
    80% { width: 100%; right: 0; left: auto; }
    100% { width: 0; right: 100%; left: auto; }
}
@keyframes reveal-TTB {
    0% { width: 100%; height: 0%; top: 0; }
    50% { width: 100%; height: 100%; top: 0; }
    80% { width: 100%; height: 100%; top: 0; }
    100% { width: 100%; height: 0; top: 100%; }
}
@keyframes reveal-BTT {
    0% { width: 100%; height: 0; top: auto; bottom: 0; }
    50% { width: 100%; height: 100%; top: auto; bottom: 0; }
    80% { width: 100%; height: 100%; top: auto; bottom: 0; }
    100% { width: 100%; height: 0; top: auto; bottom: 100%; }
}

keyframes๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ๋ฐ•์Šค๋“ค์ด ์ด๋ฆ„๊ฐ’์„ ํ•˜๋„๋ก width, height, ์œ„์น˜๋ฅผ ์„ค์ •ํ•ด ์ค๋‹ˆ๋‹ค. auto๋Š” ๊ธฐ์กด์˜ ์œ„์น˜๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
reveal์˜ ๊ฒฝ์šฐ, ๋ฐ•์Šค๊ฐ€ ์™ผ์ชฝ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ง€๋‚˜๊ฐ‘๋‹ˆ๋‹ค.
reveal-RTL(right to left)์˜ ๊ฒฝ์šฐ, ๋ฐ•์Šค๊ฐ€ ์˜ค๋ฅธ์ชฝ์—์„œ ์™ผ์ชฝ์œผ๋กœ ์ง€๋‚˜๊ฐ‘๋‹ˆ๋‹ค.
reveal-TTB(top to bottom)์˜ ๊ฒฝ์šฐ, ๋ฐ•์Šค๊ฐ€ ์œ„์ชฝ์—์„œ ์•„๋ž˜์ชฝ์œผ๋กœ ์ง€๋‚˜๊ฐ‘๋‹ˆ๋‹ค.
reveal-BTT(bottom to top)์˜ ๊ฒฝ์šฐ, ๋ฐ•์Šค๊ฐ€ ์•„๋ž˜์ชฝ์—์„œ ์œ„์ชฝ์œผ๋กœ ์ง€๋‚˜๊ฐ‘๋‹ˆ๋‹ค.

2-3) ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉํ•˜๊ธฐ

/* 1๊ฐœ */
.reveal.show::before { animation: reveal 1s; }
.reveal.reveal-RTL.show::before { animation: reveal-RTL 1s; }
.reveal.reveal-TTB.show::before { animation: reveal-TTB 1s; }
.reveal.reveal-BTT.show::before { animation: reveal-BTT 1s; }

/* 2๊ฐœ */
.reveal.show::after { animation: reveal 1s 0.3s; }
.reveal.reveal-RTL.show::after { animation: reveal-RTL 1s 0.3s; }
.reveal.reveal-TTB.show::after { animation: reveal-TTB 1s 0.3s; }
.reveal.reveal-BTT.show::after { animation: reveal-BTT 1s 0.3s; }

์—ด์‹ฌํžˆ ๋งŒ๋“  ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ•ด ์ค๋‹ˆ๋‹ค. after์˜ ๊ฒฝ์šฐ, reveal-TWO๋ฅผ ์ ์šฉํ•  ๊ฒฝ์šฐ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ๋ฐ•์Šค๊ฐ€ 0.3s์˜ ๋”œ๋ ˆ์ด๋ฅผ ๋‘๊ณ  ์ง€๋‚˜๊ฐ€๋Š” ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.

3. JAVASCRIPT

3-1) ํ…์ŠคํŠธ span์œผ๋กœ ๊ฐ์‹ธ์ฃผ๊ธฐ

const reveal = document.querySelectorAll(".reveal");
reveal.forEach((el)=>{
    let textspan = el.innerText;
    if(textspan){
        el.innerHTML = '<span>' + textspan + '</span>';
    }
})

๋จผ์ €, ํ•  ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์˜ HTML์„ ์‚ดํŽด๋ณด๋ฉด, ํ…์ŠคํŠธ๊ฐ€ p ํƒœ๊ทธ์— ์†ํ•ด์žˆ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ•ด์ฃผ๊ธฐ ์œ„ํ•ด, p ํƒœ๊ทธ ์•ˆ์— ์žˆ๋Š” ํ…์ŠคํŠธ๋ฅผ span ํƒœ๊ทธ๋กœ ๊ฐ์‹ธ์ฃผ๊ธฐ๋กœ ํ•ฉ๋‹ˆ๋‹ค.
reveal ์„ ํƒ์ž๋Š” ๋ชจ๋“  p ํƒœ๊ทธ๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. innerText๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐ๊ฐ์˜ p ํƒœ๊ทธ ์•ˆ์— ํ…์ŠคํŠธ๊ฐ€ ์žˆ๋Š”์ง€ ๋จผ์ € ํ™•์ธํ•ด ๋ด…๋‹ˆ๋‹ค. ํ…์ŠคํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด, if๋ฌธ์ด ์‹คํ–‰๋˜์–ด span ์˜ท์„ ์ž…ํ˜€์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

function scroll() {
    let scrollTop = window.scrollY;
    document.querySelector(".scroll span").innerHTML = Math.round(scrollTop);
    requestAnimationFrame(scroll);
}
scroll();

ํ…์ŠคํŠธ๋“ค์ด ๋”ฐ๋œปํ•ด์กŒ๋‹ค๋ฉด ์ด์ œ ์Šคํฌ๋กค ์ด๋ฒคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๋ชจ๋“  ์ž‘์—…๋“ค์€ ์Šคํฌ๋กค ์ด๋ฒคํŠธ ๋‚ด์—์„œ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.
์ด์ œ scroll๊ฐ’์„ ๊ตฌํ•ด ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์€ ๊ปŒ์ž…๋‹ˆ๋‹ค. request ์–ด์ฉŒ๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋„ ๋ชจ๋‘ ์••๋‹ˆ๋‹ค.

3-3) ํŒจ๋Ÿด๋ž™์Šค ํšจ๊ณผ ์ž‘์—…ํ•˜๊ธฐ

reveal.forEach((el) => {
    let revealOffset = el.offsetTop + el.parentElement.offsetTop;

    let revealDelay = el.dataset.delay;
    if (scrollTop >= revealOffset - window.innerHeight) {
        if (revealDelay == undefined) {
            el.classList.add("show");
        } else {
            setTimeout(() => {
                el.classList.add("show");
            }, revealDelay);
        }
    }
})

์ง€๋‚œ ํšจ๊ณผ์—์„œ๋Š” transitionDelay๋กœ ๋”œ๋ ˆ์ด ์†์„ฑ์„ ๋ถ€์—ฌํ•ด ์ฃผ์—ˆ์ง€๋งŒ, ์ด๋ฒˆ์—๋Š” show ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€, ์ œ๊ฑฐํ•จ์œผ๋กœ์จ ์†์„ฑ์„ ๋ถ€์—ฌํ•˜๊ธฐ๋กœ ํ•ฉ๋‹ˆ๋‹ค. transition์„ ์‚ฌ์šฉํ•˜๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ css๋ฅผ ์ผ์ผ์ด ํ•ด์„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ classList๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹นํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋ถ€์—ฌํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฒ„๋ฒ…๊ฑฐ๋ฆผ์„ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์ผ์„ ๋‚จ์—๊ฒŒ ๋– ๋„˜๊ธฐ์ง€ ๋ง์ž๋„ค์š”.
๋˜, revealDelay ์„ ํƒ์ž๋Š” data-delay ์†์„ฑ์„ ๋ถ€์—ฌํ•œ HTML ํƒœ๊ทธ๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค. setTimeout ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ , ์‹œ๊ฐ„์„ revealDelay ๊ฐ’์œผ๋กœ ์„ค์ •ํ•˜๋ฉด, ์†์‰ฝ๊ฒŒ ์›ํ•˜๋Š” ๊ฐ’๋งŒํผ ๋”œ๋ ˆ์ด๋ฅผ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๊ฒฐ๊ณผ

ํŒจ๋Ÿด๋ž™์Šค๊ฐ€ ์‰ฌ์šด ํŽธ์ด๋ผ ์ข‹์•„ํ–ˆ๋Š”๋ฐ... ์ด๊ฑด ์ข€ ์ • ๋–จ์–ด์ง€๋„ค์š”...

728x90

๋Œ“๊ธ€

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

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