Blinking Hello Kitty Angel

애니메이션효과

마우스 드래그 패럴렉스 효과

xoouxa 2023. 4. 20. 20:07

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90

안녕하세요 ヾ(≧▽≦*)o 오늘은 마우스 드래그를 하면 사진과 멘트가 나오는 패럴렉스 효과를 한 번 만들어 보도록 하겠습니다.

포트폴리오에도 많이 사용되고 사이트를 만들 때에도 자주 사용되는 효과이니 여기서 잘 익히고 나중에 작업하실 때 한 번 이용해 보세요 ~ 😏🙌

 

💛 완성 화면 입니다 . 스크롤하시면 효과를 확인하실 수 있습니다

귀여운 저희 학원 사람들입니도 ..? 🐣

 

폰트와  CSS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>패럴렉스</title>
    <link href="https://webfontworld.github.io/recia/ReciaSerifDisplay.css" rel="stylesheet">
    <style>
       *{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'ReciaSerifDisplay';
        }
        body {
            height: 20000px;
            background-color: #fff4b4;
        }
        .scrollTop {
            position: fixed;
            left: 10px;
            top: 10px;
            z-index: 1000;
            width: 40px;
            height: 40px;
            color: #000000;
            text-align: center;
            font-size: 14px;
            line-height: 40px;
            background-color: #fff4b4;
        }
        .fixed {
            position: fixed;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            z-index: 1;
        }
        .s1-text1 {
            font-size: 30vw;
            line-height: 1;
            padding-top: 8vw;
        }
        .s1-text2 {
            font-size: 20vw;
            line-height: 1;
            padding-top: 8vw;
        }
        .s1-text3 {
            font-size: 20vw;
            line-height: 1;
            padding-top: 8vw;
        }
        .s1-img1 {
            width: 200vw;
            height: 100vh;
        }
        .s1-img1 > div {
            height: 20vh;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .s1-img1 > div > div {
            width: 19vh;
            height: 19vh;
            background-position: center;
            background-size: cover;
            background-repeat: no-repeat;
            border: 5px solid #000000;
            filter: saturate(80%);
        }
        .s1-img1 > div > div:first-child {
            width: 19vh;
            height: 19vh;
            background-position: center;
            background-size: cover;
        }
        .s1-img1 > div > div:last-child {
            width: 19vh;
            height: 19vh;
            background-position: center;
            background-size: cover;
        }
        .AA img {
            width: 1000px;
            background-position: center;
            background-size: cover;
            background-repeat: no-repeat;
            align-items: center;
            justify-content: center;
        }

 

폰트는 폰트어썸에서 스타일과 어울리는 폰트를 셀랙해 줍니다.

저는 ReciaSerifDisplay 폰트를 사용했습니다 ! 

 

 box-sizing: border-box;을 사용한 이유는 요소의 전체 크기를 계산할 때 콘텐츠 영역뿐만 아니라 패딩(padding)과 테두리(border)까지 포함한 크기로 하기 위함이고 반응형에서도 유용하게 사용할 수 있기 때문입니다.\

 

전체적인 배경색을 깔아둔 뒤 scrollTop을 지정해 줍니다.

저는 멘트를 세 개 지정해 주었기 때문에 text 작업을 해주도록 합니다.

 

사이즈와 line-height를 설정해 주도록 합니다. line-height를 설정하는 이유는 텍스트 블록의 가운데 정렬, 행간을 일정하게 유지하기 위해 사용해 줍니다.

 

position: fixed도 사용해 주도록 합니다. position: fixed를 사용하는 이유는 HTML 요소의 위치는 문서 흐름(flow)에 따라 결정되는데  다른 요소들과 함께 흐름에 따라 배치되며 스크롤될 때 같이 움직입니다. 하지만 position: fixed를 사용하면, 해당 요소는 뷰포트 상단 또는 좌측 모서리를 기준으로 고정됩니다. 이는 스크롤과 상관없이 항상 같은 위치에 위치하게 됩니다.

 

저는 학원에서 회식하는 이미지도 넣어 주기 위해 img의 width,height값을 지정해 줍니다.

vw로 넣는 이유는 뷰포트의 크기에 상대적인 단위인 vw를 사용하면, 반응형 웹 디자인을 구현할 때 유용합니다.

뷰포트의 크기에 따라 요소의 크기를 조정할 수 있기 때문입니다. 예를 들어, width: 50vw;를 사용하면, 해당 요소의 너비가 뷰포트의 너비의 50%로 조정되어 스크린의 크기에 따라 자동으로 조정됩니다.

높이 또한 100vh로 설정해 주도록 합니다.

 

 

다음은 s1.img > div 입니다. justify-content 속성을 사용하여 flex item들의 수평 정렬 방법을 지정합니다. space-between 값은 flex item들 사이에 동일한 간격을 두고 수평으로 정렬하는 것을 의미합니다.

마지막으로 align-items 속성을 사용하여 flex item들의 수직 정렬 방법을 지정합니다. center 값은 flex container의 수직 중앙에 flex item들을 배치하는 것을 의미합니다.

 

first-child, last-child에 background-size : cover;를 한 이유는 이 속성을 사용하면 배경 이미지가 해당 요소의 전체 영역을 가득 채우도록 크기를 조정합니다. 만약 이미지가 요소의 크기보다 작다면, 이미지를 확대하여 요소 전체를 채우며, 이미지가 요소의 크기보다 크다면, 이미지를 축소하여 요소에 맞춥니다.

즉, background-size: cover;를 사용하면 배경 이미지의 가로 세로 비율을 유지하면서 요소에 꽉 차도록 크기를 조정하여 배경 이미지를 보기 좋게 표시할 수 있습니다.

 

이미지 넣어주기

.s1-img1-1 > div:first-child {background-image: url(https:/이유나블로그입니다.jpg);}

화면에 보여질 이미지를 넣어줍니다.

저는 27명의 사람들이기 때문에 27개의 이미지를 넣어주었습니다.

 

javascript

<body>
<div class="scrollTop"></div>
<section id="section1">
    <div class="s1-text1 fixed"
        data-0="font-size: 0vw; opacity:1"
        data-1000="font-size: 30vw; opacity:1"
        data-2000="font-size: 30vw; opacity:1"
        data-3000="font-size: 0vw; opacity:0"
    >@Webs</div>
    <div class="s1-text2 fixed"
        data-2500="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity:1"
        data-3500="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:0"
    >Legend</div>
    <div class="s1-text3 fixed"
        data-3500="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity:0"
        data-4500="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:1"
        data-5000="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:0"
    >Student</div>

    <div class="s1-img1 fixed"
        data-3500="width: 200vw; opacity:1"
        data-4500="width: 20vw; opacity:1"
        data-5000="width: 20vw; opacity:1"
        data-6000="width: 20vw; opacity:0">

        <div class="s1-img1-1">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            >
            </div>
            <div
            data-4000="transform :translateX(100px) rotate(-60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            ></div>
        </div>
        <div class="s1-img1-2">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            ></div>
            <div
            data-4000="transform :translateX(100px) rotate(-60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-3">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(-60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-4">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            ></div>
            <div
            data-4000="transform :translateX(100px) rotate(-60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-5">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            ></div>
            <div
            data-4000="transform :translateX(100px) rotate(-60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            ></div>
        </div>
    </div>

    <div class="s1-img1 fixed"
        data-3500="width: 200vw; opacity:1"
        data-4500="width: 40vw; opacity:1"
        data-5000="width: 40vw; opacity:1"
        data-6000="width: 40vw; opacity:0"
        >

        <div class="s1-img1-6">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            ></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"
            ></div>
        </div>
        <div class="s1-img1-7">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-8">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-9">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-10">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
    </div>

    <div class="s1-img1 fixed"
    data-3500="width: 200vw; opacity:1"
    data-4500="width: 60vw; opacity:1"
    data-5000="width: 60vw; opacity:1"
    data-6000="width: 60vw; opacity:0"
    >

        <div class="s1-img1-11">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-12">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-13">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-14">
            <div
            data-4000="transform :translateX(100px) rotate(60deg)"
            data-5000="transform :translateX(0px) rotate(0deg)"></div>
        </div>
        <div class="s1-img1-15">
        </div>
        <div class="s1-img1-16">
            <div></div>
            <div></div>
        </div>
        <div class="s1-img1-17">
            <div></div>
            <div></div>
        </div>
    </div>
</section>

<section id="section2">
    <div class="s1-text3 fixed"
        data-5500="opacity:0; transform: rotate(45deg) translate(800px)"
        data-6500="opacity:1;transform: rotate(45deg) translate(800px)"
        data-7500="opacity:1;transform: rotate(45deg) translate(-5000px)"
        >
        <div class="AA fixed"><img src="../parallax/img/AA.jpg" alt=""></div>
    </div>
    <div class="s1-text3 fixed"
    data-8000="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity:0"
    data-8500="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:1"
    data-9000="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:0"
>🥰</div>
    <div class="s1-text3 fixed"
        data-9000="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity:0"
        data-9500="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:1"
        data-10000="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:0"
    >We</div>
    <div class="s1-text3 fixed"
        data-10000="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity:0"
        data-10500="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:1"
        data-11000="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:0"
    >can</div>
    <div class="s1-text3 fixed"
        data-12000="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity:0"
        data-12500="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:1"
        data-13000="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:0"
    >DoIt!</div>
    <div class="s1-text3 fixed"
    data-13000="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity:0"
    data-13500="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:1"
    data-14000="font-size: 40vw; transform: translate(-50%, -50%) rotate(360deg); opacity:0"
>THX!</div>
</section>

 

스크립트를 작업해 주도록 하겠습니다.

사실 스크립트에서 애니매이션 효과를 줄 수 있는 방법은 노가다(?) 입니다 ㅎㅎ..

이렇게 안 하신 분들도 분명 계실테지만 저는 왕왕왕초보이기 때문에.. 노가다로 작업해 주었답니다 ..? 😢

 

우선 처음 @webs라는 문구가 나오게 해주기 위한 작업입니다.

css에서 지정해준 text를 기반으로 잡아주고 사용자 정의 데이터 속성이 1000에 맞춰지게 되면 @webs 문구가 서서히 화면에 나타나게 됩니다.

 

계속 스크롤 하다가 사용자 정의 데이터 속성이 2500에 맞춰지게 되면 자연스레 멘트가 사라지도록 작업하였습니다.

이와 같이 legend , student 멘트도 동일하게 작업해주고 이 멘트들이 data에 지정 된 값이 겹친다면 

멘트가 겹치기 때문에 각각 원하는 사용자 정의 데이터 속성으로 맞춰주어야 합니다.

 

각 div 태그와 각각의 요소의 다음과 같은 요소를 설정해 주도록 합니다.

font-size: 40vw; : 요소의 폰트 크기를 화면의 너비에 대한 비율인 40vw로 지정합니다.

transform: translate(-50%, -50%) rotate(360deg); : 요소를 수평, 수직으로 중앙으로 이동시키고, 360도 회전합니다.

opacity:0 : 요소를 완전히 투명하게 만듭니다.

opacity:1 : 해당 요소가 완전히 불투명해지며, 배경이나 내용물이 모두 보이게 됩니다.

 

🐣 여기서 잠깐 !

opacity: 1은 CSS의 속성 중 하나로, 해당 요소의 투명도를 나타내는 값입니다.

opacity 값은 0에서 1 사이의 값으로 지정할 수 있으며, 0에 가까울수록 투명해지고, 1에 가까울수록 불투명해집니다. 🐣

 

위에서 지정해준 이미지 갯수만큼 속성을 지정해 주도록 합니다.

다 반복작업이니 1번을 예로 들어 설명하도록 하겠습니다.

<div class="s1-img1-1">
<div
data-4000="transform :translateX(100px) rotate(60deg)"
data-5000="transform :translateX(0px) rotate(0deg)"
>
</div>

여기서 사용자 정의 데이터 속성이 4000에 맞춰지게 되면 이미지 1이 나오면서 x값과 rotate60도 값을 설정해 이미지가 동적으로 움직이면서 화면에 나타날 수 있도록 작업해 줍니다.

밑에 있는 5000은 두 번째 이미지 사진 입니다.

한 div 박스 안에 두 개의 이미지를 작업해 주는 것이고 > 안에 작성해야 하는 걸 잊지 마세요 !

 

데이터 속성 설정

<script src="https://cdnjs.cloudflare.com/ajax/libs/skrollr/0.6.30/skrollr.min.js"></script>
<script type="text/javascript">
    let s = skrollr.init();
    window.addEventListener("scroll", () => {
        let scrollTop = window.pageYOffset || window.scrollY;
        document.querySelector(".scrollTop").innerText = parseInt(scrollTop);
    });
</script>

마지막으로 왼쪽 상단에 보이는 데이터 속성을 작업해 주도록 하겠습니다.

데이터 속성이 있어야만 사용자 정의 데이터 속성을 알고 작업할 수 있습니다.

저는 제가 직접 그 속성을 보면서 어느 부분에서 어떤 속성이 나타나고 사라질 지에 대한 걸 보면서 작업해 주었기 때문에

여러분들도 원하시는 애니매이션 효과를 주기 위해선 꼭 이 작업을 해주셔야 합니다 !

 

맨 처음 url을 설정해 주도록 합니다. 저 url은 해당 코드는 외부 라이브러리인 Skrollr의 미니파일을 웹 페이지에 추가하는 HTML 코드입니다.

Skrollr은 웹 사이트에 스크롤 이벤트를 활용한 다양한 애니메이션 효과를 적용할 수 있도록 도와주는 자바스크립트 라이브러리입니다.

이 라이브러리를 웹 페이지에 추가하면, 스크롤 이벤트를 사용하여 요소들의 위치, 크기, 색상, 투명도 등을 다양하게 조작하여 동적인 애니메이션 효과를 만들 수 있습니다.

 

let s = skrollr.init();은 Skrollr 라이브러리를 초기화하고 인스턴스를 생성하는 코드입니다.

Skrollr 라이브러리를 사용하기 위해서는, 해당 라이브러리를 불러와서 초기화 과정을 거쳐야 합니다.

일반적으로 skrollr.init() 메서드를 사용하여 Skrollr 인스턴스를 생성하고 초기화합니다.

위 코드에서는 skrollr.init() 메서드를 호출하여 Skrollr 인스턴스를 생성하고, 이를 변수 s에 할당하고 있습니다.

이렇게 생성된 인스턴스를 사용하여 다양한 Skrollr 기능을 사용할 수 있습니다.

 

스크롤하면 이벤트가 발생하도록 addEventListener 작업을 해주도록 합니다.

또한 화면에 스크롤한 값이 출력되도록 document.querySelector 작업을 해주고 scrollTop을 설정한 뒤

텍스트 내용을 나타내기 위해 innerText를 사용하고 소수점을 정수로 변환하기 위해 parseInt를 해주고 scrollTop값을 구하기 위해 scrollTop을 넣어주면 화면에 출력되는 걸 확인하실 수 있습니다.

 

querySelector  메서드는 CSS 선택자를 사용하여 HTML 문서 내에서 원하는 요소를 찾습니다. 이 메서드를 사용하면 HTML 문서 내의 어떤 요소에도 접근할 수 있습니다.

querySelector 메서드는 문서 내에서 첫 번째로 일치하는 요소만 반환합니다.

만약 원하는 요소가 여러 개 있다면, querySelectorAll 메서드를 사용하여 모든 일치하는 요소를 반환할 수 있습니다.


 

 

소스코드입니다.https://github.com/leeyouna21/web2023/blob/master/javascript/parallax/parallaxAA.html

 

GitHub - leeyouna21/web2023: 수업시간에 배운 사이트입니다.

수업시간에 배운 사이트입니다. Contribute to leeyouna21/web2023 development by creating an account on GitHub.

github.com

 

 

🥰 오늘도 감사합니다.