본문 바로가기

아래로 스크롤 해주세요!

My Reference Book

-

제가 배웠던것을 한곳에 정리해보았어요!

HTML

HTML 태그 톺아보기

HTML

자세히보기

CSS

CSS 속성 톺아보기

CSS

자세히보기

JAVASCRIPT

JS 실행문 톺아보기

JAVASCRIPT

자세히보기

최신댓글

JS 응용하기

패럴렉스 이펙트_06 : 각 글자마다 효과주기 ✨

by C0Di 2022. 10. 7.
728x90

패럴렉스 이펙트_06

각 문자들을 한글자씩 쪼개 <span>태그로 감싸준뒤 그 텍스트에 각각 애니메이션을 주도록 하겠습니다 ₍ · з · ₎


HTML 코드

HTML 코드는 크게 신경쓸것이 없으나,
각 desc에 split 클래스가 달려있는것을 자바스크립트로 인식시켜 span으로 각각 한글자씩 쪼개줄거기 때문에
split 클래스명을 꼭 적도록 해야해요!

<main id="parallax__cont">
    <div id="contents">

        <!-- section1 시작 -->
        <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">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style1">우리는 사랑하는 친구들에 의해서만 알려진다. </p>
        </section>
        <!-- section1 끝 -->

        <!-- section2 시작 -->
        <section id="section2" class="content__item">
            <span class="content__item__num">02</span>
            <h2 class="content__item__title">section2</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style2">사랑은 눈으로 보지 않고 마음으로 보는 거지. </p>
        </section>
        <!-- section2 끝 -->

        <!-- section3 시작 -->
        <section id="section3" class="content__item">
            <span class="content__item__num">03</span>
            <h2 class="content__item__title">section3</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style3">두 분은 상처 하나 입지 않고, 대용사가 된 셈이오.</p>
        </section>
        <!-- section3 끝 -->

        <!-- section4 시작 -->
        <section id="section4" class="content__item">
            <span class="content__item__num">04</span>
            <h2 class="content__item__title">section4</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style4">그의 믿음은 그가 쓰는 모자의 유행처럼 변한다.</p>
        </section>
        <!-- section4 끝 -->

        <!-- section5 시작 -->
        <section id="section5" class="content__item">
            <span class="content__item__num">05</span>
            <h2 class="content__item__title">section5</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style5">잘 있거라! 우리가 언제 다시 만날지는 아무도 모른다.</p>
        </section>
        <!-- section5 끝 -->

        <!-- section6 시작 -->
        <section id="section6" class="content__item">
            <span class="content__item__num">06</span>
            <h2 class="content__item__title">section6</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style6">죄를 짓고 잘되는 사람도 있고, 덕을 베풀고 망하는 사람도 있다.</p>
        </section>
        <!-- section6 끝 -->

        <!-- section7 시작 -->
        <section id="section7" class="content__item">
            <span class="content__item__num">07</span>
            <h2 class="content__item__title">section7</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style7">모두를 사랑하되, 몇 사람만 믿으라. 누구에게도 잘못을 저지르지 말라.</p>
        </section>
        <!-- section7 끝 -->

        <!-- section8 시작 -->
        <section id="section8" class="content__item">
            <span class="content__item__num">08</span>
            <h2 class="content__item__title">section8</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style8">누구에게나 결점은 있기 마련이지. 그분의 경우는 솔직하다는 게 결점이야.</p>
        </section>
        <!-- section8 끝 -->

        <!-- section9 시작 -->
        <section id="section9" class="content__item">
            <span class="content__item__num">09</span>
            <h2 class="content__item__title">section9</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc split style9">사람은 누구나 주어진 일과 원하는 것이 있다, 비록 보잘 것 없을 지라도. </p>
        </section>
        <!-- section9 끝 -->
    </div>
</main>
<!-- //main -->
    

CSS 코드 : 애니메이션

총 6가지(wobble/bounceInLeft/tada/heartBeat/jello/swing)의 애니메이션을 사용하였습니다.

@keyframes wobble {
    0% {
        transform: translate3d(0, 0, 0);
        opacity: 0;
    }

    15% {
        transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
    }

    30% {
        transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
    }

    45% {
        transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
    }

    60% {
        transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
    }

    75% {
        transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
    }

    100% {
        transform: translate3d(0, 0, 0);
        opacity: 1;
    }
}

@keyframes bounceInLeft {

    0%,
    60%,
    75%,
    90%,
    100% {
        animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    }

    0% {
        opacity: 0;
        transform: translate3d(-3000px, 0, 0) scaleX(3);
    }

    60% {
        opacity: 1;
        transform: translate3d(25px, 0, 0) scaleX(1);
    }

    75% {
        opacity: 1;
        transform: translate3d(-10px, 0, 0) scaleX(0.98);
    }

    90% {
        opacity: 1;
        transform: translate3d(5px, 0, 0) scaleX(0.995);
    }

    100% {
        opacity: 1;
        transform: translate3d(0, 0, 0);
    }
}

@keyframes tada {
    0% {transform: scale3d(1, 1, 1); opacity: 0;}

    10%,
    20% {transform: scale3d(0.5, 0.5, 0.5) rotate3d(0, 0, 1, -10deg); opacity: 1;}

    30%,
    50%,
    70%,
    90% {transform: scale3d(1.5, 1.5, 1.5) rotate3d(0, 0, 1, 10deg); opacity: 1;}

    40%,
    60%,
    80% {transform: scale3d(1.5, 1.5, 1.5) rotate3d(0, 0, 1, -10deg); opacity: 1;}

    100% {transform: scale3d(1, 1, 1); opacity: 1;}
}

@keyframes heartBeat {
    0% {
        opacity: 0;
        transform: scale(1);
    }

    14% {
        opacity: 1;
        transform: scale(1.6);
    }

    28% {
        opacity: 1;
        transform: scale(0.5);
    }

    72% {
        opacity: 1;
        transform: scale(1.6);
    }

    100% {
        opacity: 1;
        transform: scale(1);
    }
}

@keyframes jello {
    0% {
        opacity: 0;
        transform: translate3d(0, 0, 0);
    }

    22.2% {
        opacity: 1;
        transform: skewX(-17.5deg) skewY(-17.5deg);
    }

    33.3% {
        opacity: 1;
        transform: skewX(16.25deg) skewY(16.25deg);
    }

    44.4% {
        opacity: 1;
        transform: skewX(-13.125deg) skewY(-13.125deg);
    }

    55.5% {
        opacity: 1;
        transform: skewX(1.5625deg) skewY(1.5625deg);
    }

    66.6% {
        opacity: 1;
        transform: skewX(-0.78125deg) skewY(-0.78125deg);
    }

    77.7% {
        opacity: 1;
        transform: skewX(0.390625deg) skewY(0.390625deg);
    }

    100% {
        opacity: 1;
        transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
    }
}

@keyframes swing {
    0% {
        opacity: 0;
        transform: rotate3d(0, 0, 1, 15deg);
    }

    35% {
        opacity: 1;
        transform: rotate3d(0, 0, 1, -10deg);
    }

    60% {
        opacity: 1;
        transform: rotate3d(0, 0, 1, 5deg);
    }

    80% {
        opacity: 1;
        transform: rotate3d(0, 0, 1, -5deg);
    }

    100% {
        opacity: 1;
        transform: rotate3d(0, 0, 1, 0deg);
    }
}
/* parallax__nav */
    #parallax__nav {
        position: fixed;
        right: 20px;
        top: 20px;
        z-index: 2000;
        background-color: rgba(0, 0, 0, 0.4);
        padding: 20px 30px;
        border-radius: 50px;
        transition: top 0.4s ease;
    }

    #parallax__nav li {
        display: inline;
        margin: 0 5px;
    }

    #parallax__nav li a {
        display: inline-block;
        height: 30px;
        padding: 5px 20px;
        text-align: center;
        line-height: 30px;
    }

    #parallax__nav li.active a {
        background: #fff;
        color: #000;
        border-radius: 20px;
        box-sizing: content-box;
    }

    #parallax__cont {
        max-width: 1600px;
        /* background-color: rgba(255, 255, 255, 0.1); */
        margin: 0 auto;
        width: 98%;
    }

    .content__item {
        width: 1000px;
        max-width: 70vw;
        margin: 30vw auto;
        /* background-color: rgba(255, 255, 255, 0.3); */
        text-align: left;
        margin-right: 0;
        position: relative;
        padding-top: 8vw;
    }

    .content__item:nth-child(even) {
        /* 2n도 가능하고 even 도 가능하고 */
        margin-left: 0;
        text-align: right;
    }

    .content__item__num {
        font-size: 35vw;
        font-family: 'Lato';
        font-weight: 100;
        position: absolute;
        left: -5vw;
        top: -16vw;
        opacity: 0.07;
        z-index: -2;
    }

    .content__item:nth-child(even) .content__item__num {
        right: -5vw;
        left: auto;
        /* left 값 초기화 */
    }

    .content__item__title {
        font-weight: 400;
        text-transform: capitalize;
    }

    .content__item__imgWrap {
        width: 100%;
        padding-bottom: 56.25%;
        background-color: #000;
        position: relative;
        overflow: hidden;
        z-index: -1;
    }

    .content__item__img {
        background: url(../../assets/slider/effect_bg_01.jpg);
        background-position: center center;
        background-repeat: no-repeat;
        background-size: cover;
        /* 내가 작아서 넣음 */
        position: absolute;
        width: 110%;
        height: 110%;
        left: -5%;
        top: -5%;
        filter: saturate(0%);
        /* transition: all 1s; */
    }

    .content__item:nth-child(1) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_01.jpg);
    }

    .content__item:nth-child(2) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_02.jpg);
    }

    .content__item:nth-child(3) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_03.jpg);
    }

    .content__item:nth-child(4) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_04.jpg);
    }

    .content__item:nth-child(5) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_05.jpg);
    }

    .content__item:nth-child(6) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_06.jpg);
    }

    .content__item:nth-child(7) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_07.jpg);
    }

    .content__item:nth-child(8) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_08.jpg);
    }

    .content__item:nth-child(9) .content__item__img {
        background-image: url(../../assets/slider/effect_bg_09.jpg);
    }

    .content__item__desc {
        font-size: 4vw;
        line-height: 1.4;
        margin-top: -5vw;
        margin-left: -4vw;
        word-break: keep-all;
    }

    .content__item:nth-child(even) .content__item__desc {
        margin-left: auto;
        margin-right: 4vw;
    }

    #parallax__info {
        position: fixed;
        left: 20px;
        bottom: 20px;
        z-index: 2000;
        background: rgba(0, 0, 0, 0.6);
        color: #fff;
        padding: 20px;
        border-radius: 10px;
    }

    #parallax__info li,
    .scrollTop {
        line-height: 1.4;
    }

    @media (max-width: 800px) {
        #parallax__cont {
            margin-top: 70vw;
        }

        #parallax__nav {
            padding: 10px;
            right: auto;
            left: 10px;
            top: 10px;
            transform: translateY(50%);
            border-radius: 5px;
            background-color: rgba(0, 0, 0, 0.8);
        }

        #parallax__nav li {
            display: block;
            margin: 5px;
        }

        #parallax__nav li a {
            font-size: 14px;
            padding: 5px;
            border-radius: 5px;
            height: auto;
            line-height: 1;
        }

        #parallax__nav li.active a {
            border-radius: 5px;
        }
    }

    .split span {
        opacity: 0;
        transform: translateX(0px);
        transition: all 0.3s ease-in-out;
        display: inline-block;
        min-width: 1vw;
    }

    /* option */
    .style1.split span {
        opacity: 0;
        min-width: 1vw;
        transition: all 0.3s cubic-bezier(0.65, 0.16, 0.16, 0.97);
        transform: translateY(50px);
        display: inline-block;
    }

    .style1.split span.show {
        opacity: 1;
        transform: translateY(0);
    }

    .style2.split span {
        opacity: 0;
        min-width: 1vw;
        transition: all 0.3s cubic-bezier(0.65, 0.16, 0.16, 0.97);
        transform: translateY(50px);
        display: inline-block;
    }

    .style2.split span.show {
        opacity: 1;
        transform: translateY(0);
    }

    .style3.split span {
        opacity: 0;
        min-width: 1vw;
        transition: all 0.3s cubic-bezier(0.65, 0.16, 0.16, 0.97);
        transform: translateY(50px) translateX(30px) rotate(360deg);
        display: inline-block;
    }

    .style3.split span.show {
        opacity: 1;
        transform: translateY(0) translateX(0) rotate(0);
    }

    .style4.split span {
        opacity: 0;
        min-width: 1vw;
        display: inline-block;
    }

    .style4.split span.show {
        /* opacity: 1; */
        animation: wobble 0.5s 1 ease-in forwards;
    }

    .style5.split span {
        /* opacity: 0; */
        min-width: 1vw;
        display: inline-block;
    }

    .style5.split span.show {
        /* opacity: 1; */
        animation: bounceInLeft 0.5s 1 ease-in forwards;
    }

    .style6.split span {
        /* opacity: 0; */
        min-width: 1vw;
        display: inline-block;
    }

    .style6.split span.show {
        /* opacity: 1; */
        animation: tada 0.5s 1 ease-in forwards;
    }

    .style7.split span {
        /* opacity: 0; */
        min-width: 1vw;
        display: inline-block;
    }

    .style7.split span.show {
        /* opacity: 1; */
        animation: heartBeat 0.5s 1 ease-in forwards;
    }

    .style8.split span {
        /* opacity: 0; */
        min-width: 1vw;
        display: inline-block;
    }

    .style8.split span.show {
        /* opacity: 1; */
        animation: jello 0.5s 1 ease-in forwards;
    }

    .style9.split span {
        /* opacity: 0; */
        min-width: 1vw;
        display: inline-block;
    }

    .style9.split span.show {
        /* opacity: 1; */
        animation: swing 0.5s 1 ease-in forwards;
    }

    @keyframes wobble {
        0% {
            transform: translate3d(0, 0, 0);
            opacity: 0;
        }

        15% {
            transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
        }

        30% {
            transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
        }

        45% {
            transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
        }

        60% {
            transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
        }

        75% {
            transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
        }

        100% {
            transform: translate3d(0, 0, 0);
            opacity: 1;
        }
    }

    @keyframes bounceInLeft {

        0%,
        60%,
        75%,
        90%,
        100% {
            animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
        }

        0% {
            opacity: 0;
            transform: translate3d(-3000px, 0, 0) scaleX(3);
        }

        60% {
            opacity: 1;
            transform: translate3d(25px, 0, 0) scaleX(1);
        }

        75% {
            opacity: 1;
            transform: translate3d(-10px, 0, 0) scaleX(0.98);
        }

        90% {
            opacity: 1;
            transform: translate3d(5px, 0, 0) scaleX(0.995);
        }

        100% {
            opacity: 1;
            transform: translate3d(0, 0, 0);
        }
    }

    @keyframes tada {
        0% {transform: scale3d(1, 1, 1); opacity: 0;}

        10%,
        20% {transform: scale3d(0.5, 0.5, 0.5) rotate3d(0, 0, 1, -10deg); opacity: 1;}

        30%,
        50%,
        70%,
        90% {transform: scale3d(1.5, 1.5, 1.5) rotate3d(0, 0, 1, 10deg); opacity: 1;}

        40%,
        60%,
        80% {transform: scale3d(1.5, 1.5, 1.5) rotate3d(0, 0, 1, -10deg); opacity: 1;}

        100% {transform: scale3d(1, 1, 1); opacity: 1;}
    }

    @keyframes heartBeat {
        0% {
            opacity: 0;
            transform: scale(1);
        }

        14% {
            opacity: 1;
            transform: scale(1.6);
        }

        28% {
            opacity: 1;
            transform: scale(0.5);
        }

        72% {
            opacity: 1;
            transform: scale(1.6);
        }

        100% {
            opacity: 1;
            transform: scale(1);
        }
    }

    @keyframes jello {
        0% {
            opacity: 0;
            transform: translate3d(0, 0, 0);
        }

        22.2% {
            opacity: 1;
            transform: skewX(-17.5deg) skewY(-17.5deg);
        }

        33.3% {
            opacity: 1;
            transform: skewX(16.25deg) skewY(16.25deg);
        }

        44.4% {
            opacity: 1;
            transform: skewX(-13.125deg) skewY(-13.125deg);
        }

        55.5% {
            opacity: 1;
            transform: skewX(1.5625deg) skewY(1.5625deg);
        }

        66.6% {
            opacity: 1;
            transform: skewX(-0.78125deg) skewY(-0.78125deg);
        }

        77.7% {
            opacity: 1;
            transform: skewX(0.390625deg) skewY(0.390625deg);
        }

        100% {
            opacity: 1;
            transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
        }
    }
    
    @keyframes swing {
        0% {
            opacity: 0;
            transform: rotate3d(0, 0, 1, 15deg);
        }

        35% {
            opacity: 1;
            transform: rotate3d(0, 0, 1, -10deg);
        }

        60% {
            opacity: 1;
            transform: rotate3d(0, 0, 1, 5deg);
        }

        80% {
            opacity: 1;
            transform: rotate3d(0, 0, 1, -5deg);
        }

        100% {
            opacity: 1;
            transform: rotate3d(0, 0, 1, 0deg);
        }
    }
    

JS 코드 : split 기준으로 한글자씩 span으로 감싸주기!

우선 저희는 split을 이용해 글씨를 각각 분리한 뒤 span태그로 묶을것이기 때문에 하단의 사항을 적용하였습니다. 1. .content__item__desc를 다중으로 선택 후 해당 요소를 forEach를 통해 추출합니다.
2. 각 꺼낸 요소를 .innerText로 문자열로 변환 후 splitText라는 변수안에 넣고 3. 각 단어마다 split을 이용해 splitText에 저장되어있는 문자를 한글자씩('')쪼개고 각 쪼갠 문자마자("</span><span aria-hidden='true'>")를 붙여줍니다.
* 3번과 같이 태그를 붙인이유는 일반적인 방법으로 사용시 span태그가 붙지 않는 경우가 생기기 때문에 사용했습니다.
4. splitWrap 변수에는 "<span aria-hidden='true'>" + splitWrap + "</span>";를 담아주어
5. splitwrap을 각 뽑아낸 요소에 innerHTML로 넣습니다~

//글씨 쪼개기
let text = document.querySelectorAll(".content__item__desc");

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;
    text.setAttribute("aria-label", splitText);
})

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

    document.querySelectorAll(".content__item").forEach(item => {
        if (scrollTop >= item.offsetTop) {
            item.querySelectorAll(".split span").forEach((e, i) => {
                setTimeout(() => {
                    e.classList.add("show");
                }, i * i)
            })
        }
    })

    requestAnimationFrame(scroll);
}
scroll();

결과

느무느무 믓즈인~~~~~ 패럴렉스 이펙트 06번 완승~~~💃🏻


728x90
반응형

댓글

#HASH_TAGS

-

1

내일은 즐거운 월요일 선택해주세요 오늘 조업 마감했습니다. scroll-snap-align 코드 오징어 한마리 수확 완료! 오늘도 웹표준은.. 필터선택자 제이쿼리 이건 또 뭐람 공부 슬라이드 결과 : 월요일 코딩 멈추지 않는 ' j ' 시리-즈 Method 오징어 두마리 포획 완료 메서드 scroll-snap-type 오늘은 내가바로 오징어! 숙제가 다양해서 너무 좋아요 HTML 오징어 1Kg 당 3000원 ImageSlideEffect 다크모드 울적하니 꽃을 달아봤습니다 화사한가요? JQuery