Lumpy Space Princess - Adventure Time

JAVASCRIPT

Parallax Effect 를 적용한 사이트 만들기

jongyung 2023. 4. 20. 23:41

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

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

설명:

패럴랙스 효과를 이용해서 사이트를 간단하게 만들어 봤습니다.

스크롤을 내리면 효과가 적용이 되는 것을 알 수 있습니다.

 

왼쪽 상단에는 스크롤의 값이 숫자로 나오게 설정했습니다.

 

설명은 style, body 그리고 script 로 나눠서 하겠습니다.

style

 @font-face {
    font-family: 'ReciaSerifDisplay';
    font-weight: normal;
    font-style: normal;
    src: url('https://cdn.jsdelivr.net/gh/webfontworld/recia/ReciaSerifDisplay.eot');
    src: url('https://cdn.jsdelivr.net/gh/webfontworld/recia/ReciaSerifDisplay.eot?#iefix') format('embedded-opentype'),
        url('https://cdn.jsdelivr.net/gh/webfontworld/recia/ReciaSerifDisplay.woff2') format('woff2'),
        url('https://cdn.jsdelivr.net/gh/webfontworld/recia/ReciaSerifDisplay.woff') format('woff'),
        url('https://cdn.jsdelivr.net/gh/webfontworld/recia/ReciaSerifDisplay.ttf') format("truetype");
    font-display: swap;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: "ReciaSerifDisplay";
}
body {
    height: 20000px;
    background-color: #e0e4dd;
}
.scrollTop {
    position: fixed;
    left: 10px;
    top: 10px;
    z-index: 1000;
    width: 40px;
    height: 40px;
    color: #fff;
    text-align: center;
    line-height: 40px;
    background-color: rgba(0, 0, 0, 0.6);
}
.fixed {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
}
.s1-text1 {
    font-size: 30vw;
    padding-top: 8vw;
    line-height: 1;
}
.s2-text2 {
    font-size: 0vw;
    line-height: 1;
    padding-top: 8vw;
}
.s1-img1 {
    width: 100vw;
    height: 100vh;            
}
.s1-img1 > div {
    height: 20vh;
    display: flex;
    justify-content: space-between;
}
.s1-img1 > div > div {
    width: 19vh;
    height: 19vh;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
    border: 3px solid #000;           
}
.s1-img1-1 > div:first-child {
    background-image: url(https://i.pinimg.com/236x/2e/6a/c1/2e6ac1196206d176c6e4db89bb379aea.jpg)           
}
.s1-img1-1 > div:last-child {
    background-image: url(https://i.pinimg.com/236x/16/2b/88/162b88a46f682bc0335467e6b6b367c4.jpg);
}        
.s1-img1-2 > div:first-child {
    background-image: url(https://i.pinimg.com/236x/e3/1c/fd/e31cfd1177424fa62103dbb0daa2334d.jpg);           
}
.s1-img1-2 > div:last-child {
    background-image: url(https://i.pinimg.com/236x/0e/78/dd/0e78dd8e15834e6e210d7d6f6328cc65.jpg);           
}
.s1-img1-3 > div:first-child {
    background-image: url(https://i.pinimg.com/236x/ca/93/7a/ca937ae94e99355ab0ca24ef6f8f2c0c.jpg);          
}
.s1-img1-3 > div:last-child {
    background-image: url(https://i.pinimg.com/236x/b1/41/88/b14188e79e6f3eefb566ea87fe68ff8a.jpg);           
}
.s1-img1-4 > div:first-child {
    background-image: url(https://i.pinimg.com/236x/cd/73/e6/cd73e6651b49cd220c45769fe42efb50.jpg);           
}
.s1-img1-4 > div:last-child {
    background-image: url(https://i.pinimg.com/236x/61/6e/ee/616eee37d03c20df23cffe0446db364b.jpg);           
}
.s1-img1-5 > div:first-child {
    background-image: url(https://i.pinimg.com/236x/0e/25/35/0e2535fa555aaa07357f0a5a9a93ef81.jpg);           
}
.s1-img1-5 > div:last-child {
    background-image: url(https://i.pinimg.com/236x/38/fb/7e/38fb7e4fe5e50e71f9c6477c60488864.jpg);           
}

font-face 로 글씨체를 적용했습니다.

각각의 위치 값을 설정해주고, 색도 지정했습니다.

이미지가 나올 부분들은 배경이미지로 사진의 주소를 복사해서 가져왔습니다.

 

여기에서 쓰인 태그들에 대해서 설명하겠습니다.

@font-face는 웹 페이지에서 사용자의 컴퓨터에 설치되어 있지 않은 폰트를 사용할 수 있도록 CSS에서 제공하는 규칙입니다.
이를 통해 웹 디자이너는 특정 폰트를 웹 페이지에서 사용하고, 사용자는 해당 폰트를 자동으로 다운로드하여 볼 수 있게 됩니다.
@font-face는 폰트 형식에 따라 서로 다른 속성을 사용하며, TrueType(.ttf) 및 OpenType(.otf) 폰트를 사용하는 경우 가장 많이 사용됩니다.

예를 들어, 다음과 같은 코드를 사용하여 웹 페이지에서 사용할 폰트를 추가할 수 있습니다.
@font-face { font-family: 'MyCustomFont'; src: url('mycustomfont.ttf') format('truetype'); }​

위의 코드에서는 MyCustomFont라는 폰트 패밀리를 정의하고, mycustomfont.ttf라는 TrueType 폰트 파일을 사용하여 폰트를 추가합니다.
추가된 폰트는 다른 CSS 규칙에서 font-family 속성을 사용하여 사용할 수 있습니다.

z-index는 CSS 속성 중 하나로, 요소의 쌓임 순서를 결정하는 데 사용됩니다.
각 요소는 화면 상에 위치한 다른 요소 위에 렌더링됩니다.
z-index는 이러한 요소들의 상대적인 쌓임 순서를 지정하는 데 사용됩니다.
z-index 속성은 정수 값을 사용하며, 값이 높을수록 요소가 높은 층위에 위치합니다.
즉, z-index 값이 큰 요소는 z-index 값이 작은 요소 위에 렌더링됩니다.
만약 z-index 값을 지정하지 않으면 기본값으로 0이 할당됩니다.

예를 들어, 다음과 같은 CSS 코드가 있다고 가정해보겠습니다.

div { position: absolute; top: 100px; left: 100px; width: 100px; height: 100px; background-color: red; z-index: 1; } 
span { position: absolute; top: 150px; left: 150px; width: 100px; height: 100px; background-color: blue; z-index: 2; }

위의 코드에서는 div 요소와 span 요소가 모두 절대 위치(position: absolute)로 설정되어 있습니다.
z-index 속성을 사용하여 span 요소의 쌓임 순서를 div 요소보다 높게 설정했습니다.
따라서 span 요소가 div 요소 위에 렌더링됩니다.

transform: translate()는 CSS transform 속성의 하위 속성 중 하나로, 요소를 지정된 값만큼 이동시키는 데 사용됩니다. translate() 함수는 X축과 Y축 방향으로 이동할 거리를 지정할 수 있으며, 이동 거리는 픽셀(px), 백분율(%) 또는 em 등의 단위를 사용하여 지정할 수 있습니다.
translate() 함수는 transform 속성 값으로 사용됩니다.

예를 들어, 다음과 같은 CSS 코드를 살펴보겠습니다.

.box { transform: translate(50px, 100px); }

위의 코드에서는 box 클래스를 가진 요소가 X축으로 50px, Y축으로 100px 이동합니다.
이동 거리가 양수인 경우 요소는 오른쪽과 아래쪽으로 이동하며, 음수인 경우 요소는 왼쪽과 위쪽으로 이동합니다.

translate() 함수는 다른 transform 속성과 함께 사용될 수 있으며, 여러 변환 효과를 동시에 적용할 수 있습니다.

예를 들어, 다음과 같은 CSS 코드에서는 요소를 X축으로 50px 이동시키고, Y축으로 100px 회전시키는 효과를 적용합니다.

.box { transform: translate(50px) rotate(45deg); }

translate() 함수는 요소를 이동시키는 가장 일반적인 transform 함수 중 하나이며, CSS 애니메이션 및 전환과 함께 사용될 때 매우 유용합니다.

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"
        >Vintage</div>
    </section>
    <section id="section2">
        <div class="s2-text2 fixed"
            data-2500="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity: 1"
            data-3000="font-size: 30vw; transform: translate(-50%, -50%) rotate(720deg); opacity: 1"
            data-18000="opacity: 0"
        >Photos</div>
        <div class="s1-img1 fixed"
            data-3500="width: 200vw;"
            data-4500="width: 30vw;">                              
                <div class="s1-img1-1">
                    <div
                        data-4490="transform: scale(0.5); opacity: 0"                                              
                        data-4500="transform: scale(0.5); opacity: 1"
                        data-5000="transform: scale(2); opacity: 1"                            
                        data-6000="transform: scale(1); opacity: 0"
                    ></div>
                    <div                           
                        data-5990="transform: scale(0.5); opacity: 0"
                        data-6000="transform: scale(0.5); opacity: 1"
                        data-6500="transform: scale(2); opacity: 1"
                        data-7500="transform: scale(1); opacity: 0"
                    ></div>
                </div>
                <div class="s1-img1-2">
                    <div
                        data-7490="transform: scale(0.5); opacity: 0"
                        data-7500="transform: scale(0.5); opacity: 1"
                        data-8000="transform: scale(2); opacity: 1"
                        data-9000="transform: scale(1); opacity: 0"
                    ></div>
                    <div
                        data-8990="transform: scale(0.5); opacity: 0"
                        data-9000="transform: scale(0.5); opacity: 1"
                        data-9500="transform: scale(2); opacity: 1"
                        data-10500="transform: scale(1); opacity: 0"
                    ></div>
                </div>                
                <div class="s1-img1-3">
                    <div
                        data-10490="transform: scale(0.5); opacity: 0"
                        data-10500="transform: scale(0.5); opacity: 1"
                        data-11000="transform: scale(2); opacity: 1"
                        data-12000="transform: scale(1); opacity: 0"
                    ></div>
                    <div
                        data-11990="transform: scale(0.5); opacity: 0"
                        data-12000="transform: scale(0.5); opacity: 1"
                        data-12500="transform: scale(2); opacity: 1"
                        data-13500="transform: scale(1); opacity: 0"
                    ></div>
                </div>
                <div class="s1-img1-4">
                    <div
                        data-13490="transform: scale(0.5); opacity: 0"
                        data-13500="transform: scale(0.5); opacity: 1"
                        data-14000="transform: scale(2); opacity: 1"
                        data-15000="transform: scale(1); opacity: 0"
                    ></div>
                    <div
                        data-14990="transform: scale(0.5); opacity: 0"
                        data-15000="transform: scale(0.5); opacity: 1"
                        data-15500="transform: scale(2); opacity: 1"
                        data-16500="transform: scale(1); opacity: 0"
                    ></div>
                </div>
                <div class="s1-img1-5">
                    <div
                        data-15990="transform: scale(0.5); opacity: 0"
                        data-16000="transform: scale(0.5); opacity: 1"
                        data-16500="transform: scale(2); opacity: 1"
                        data-17000="transform: scale(1); opacity: 0"
                    ></div>
                    <div
                        data-16990="transform: scale(0.5); opacity: 0"
                        data-17000="transform: scale(0.5); opacity: 1"
                        data-17500="transform: scale(2); opacity: 1"
                        data-18000="transform: scale(1); opacity: 0"
                    ></div>
                </div>
        </div>
    </section>
    <section id="section3">
        <div class="s3-text3 fixed"
            data-18000="font-size: 0vw; transform: translate(-50%, -50%) rotate(0deg); opacity: 1"
            data-18500="font-size: 10vw; transform: translate(-50%, -50%) rotate(360deg); opacity: 1"                
        >don't Run from it, Learn from it</div>
    </section>

scrolloTop 은 좌측 상단에 있는 스크롤 값을 나타내는 박스입니다.

그 외의 부분들은 영역별로 묶어서 설정했습니다. 

 

여기에 쓰인 태그들에 대해서 설명하겠습니다.

data-는 HTML5에서 새로 도입된 사용자 정의 데이터 속성의 접두어입니다.
data- 속성은 HTML 요소에 임의의 데이터를 저장하고 이를 JavaScript를 통해 읽고 수정할 수 있도록 합니다.
data- 속성은 일반적으로 data- 다음에 원하는 이름을 지정하여 사용합니다.

예를 들어, 다음과 같이 data- 속성을 사용하여 username이라는 데이터를 저장할 수 있습니다.
<div data-username="john_doe">John Doe</div>​

위의 코드에서는 div 요소에 data-username 속성을 추가하여 john_doe라는 데이터를 저장합니다. 
이제 이 요소를 JavaScript로 가져와서 해당 데이터를 읽거나 수정할 수 있습니다.

var div = document.querySelector('div');
var username = div.dataset.username; // 'john_doe'
div.dataset.username = 'jane_doe'; // 데이터 수정

위의 코드에서는 querySelector를 사용하여 div 요소를 가져오고, dataset 속성을 사용하여 data- 속성의 값을 읽고 수정합니다.

data- 속성은 HTML 요소의 기능을 확장하는 데 유용하며, HTML 마크업과 JavaScript 코드 간의 데이터 공유를 쉽게 만듭니다. 또한, data- 속성은 검색 엔진 최적화(SEO)에도 도움이 됩니다. 
예를 들어, 검색 엔진은 data- 속성에 포함된 데이터를 색인화할 수 있으며, 이를 활용하여 웹 사이트의 검색 결과를 개선할 수 있습니다.

transform: scale은 CSS transform 속성 중 하나로, 요소의 크기를 비례적으로 조정하는 데 사용됩니다. 
scale 속성은 기본 값이 1이며, 1보다 작은 값을 지정하면 요소가 축소되고, 1보다 큰 값을 지정하면 요소가 확대됩니다.

transform: scale 속성은 다음과 같은 방법으로 사용됩니다.

.element {
  transform: scale(1.5);
}

위의 코드에서는 element 클래스를 가진 요소의 크기를 1.5배로 확대합니다.

scale 속성은 다른 값과 함께 사용하여 요소를 다양한 방식으로 조정할 수 있습니다. 예를 들어, scaleX와 scaleY 속성을 사용하여 요소를 수평 또는 수직으로만 조정할 수 있습니다.

.element {
  transform: scaleX(2) scaleY(0.5);
}

위의 코드에서는 element 클래스를 가진 요소의 가로 크기를 2배로 늘리고, 세로 크기를 반으로 줄입니다.

scale 속성은 CSS transition과 함께 사용하여 요소를 부드럽게 확대/축소하는 효과를 적용할 수 있습니다. 

예를 들어, 다음과 같은 코드는 element 클래스를 가진 요소를 1초 동안 서서히 확대합니다.

Copy code
.element {
  transform: scale(1);
  transition: transform 1s;
}

.element:hover {
  transform: scale(1.5);
}

위의 코드에서는 transition 속성을 사용하여 transform 속성에 대한 애니메이션을 적용합니다. 
요소에 마우스를 올리면 scale 속성이 1에서 1.5로 변경되므로, 요소가 부드럽게 확대되는 효과를 볼 수 있습니다.

opacity는 CSS 속성 중 하나로, 요소의 불투명도(opacity)를 설정하는 데 사용됩니다. 
이 속성은 0에서 1 사이의 값으로 지정되며, 0은 요소를 완전히 투명하게 만들고, 1은 요소를 완전히 불투명하게 만듭니다.

opacity 속성은 다음과 같은 방법으로 사용됩니다.

.element {
  opacity: 0.5;
}

위의 코드에서는 element 클래스를 가진 요소의 불투명도를 0.5로 설정합니다. 이 경우, 요소는 반투명한 상태가 되어 배경이나 다른 요소를 부분적으로 노출시킵니다.

opacity 속성은 요소의 자식 요소에도 영향을 미칩니다. 따라서, 부모 요소의 불투명도를 0으로 설정하면, 모든 자식 요소가 투명해지게 됩니다.

opacity 속성은 CSS 애니메이션과 함께 사용하여 요소를 서서히 나타내거나 사라지게 만드는 효과를 적용할 수 있습니다. 예를 들어, 다음과 같은 코드는 element 클래스를 가진 요소를 1초 동안 서서히 나타나게 만듭니다.

.element {
  opacity: 0;
  animation: fadeIn 1s forwards;
}

@keyframes fadeIn {
  to {
    opacity: 1;
  }
}

위의 코드에서는 opacity 속성을 0으로 설정하여 요소를 숨김 상태로 만들고, animation 속성을 사용하여 fadeIn이라는 애니메이션을 적용합니다. 
이 애니메이션은 1초 동안 실행되며, 요소의 불투명도를 서서히 0에서 1로 증가시킵니다. 
forwards 키워드는 애니메이션이 끝난 후에도 요소를 표시된 상태로 유지하도록 합니다.

script 

<script src="https://cdnjs.cloudflare.com/ajax/libs/skrollr/0.6.30/skrollr.min.js" integrity="sha512-A2+khatRDWHUE2VUtN4xUTkr1nc4YfDBw9Sg3ea6x0aRPfpcYieDZji4D2edDHy/yF5NsYzP7kL8sSM8s5EqCw==" crossorigin="anonymous" referrerpolicy="no-referrer"></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>

scrollTop 값을 구하는 함수식입니다.

 

여기에 쓰인 메서드들에 대해서 설명하겠습니다.

skrollr은 웹사이트에서 스크롤(scroll) 이벤트를 이용하여 요소의 위치나 속성 등을 애니메이션으로 변경하는 데 사용되는 JavaScript 라이브러리입니다.
skrollr은 다양한 속성을 제공하여 요소의 위치, 크기, 회전, 투명도 등을 애니메이션으로 변경할 수 있습니다.
또한, 요소를 트리거(trigger)로 사용하여 특정 스크롤 위치에 도달했을 때 애니메이션을 실행할 수도 있습니다.
skrollr의 사용 방법은 다음과 같습니다.

skrollr 라이브러리를 다운로드하고 HTML 파일에 추가합니다.
<script src="skrollr.min.js"></script>​

애니메이션을 적용할 요소에 data-* 속성을 추가합니다. data-* 속성은 요소의 위치나 속성 등을 지정하는 데 사용됩니다.

<div data-0="opacity: 1;" data-500="opacity: 0;"></div>

위의 코드에서는 data-* 속성을 사용하여 요소의 불투명도를 스크롤 위치에 따라 조정합니다. data-0 속성은 스크롤 위치가 0일 때의 상태를, data-500 속성은 스크롤 위치가 500일 때의 상태를 지정합니다.

skrollr을 초기화합니다.

var s = skrollr.init();

위의 코드에서는 skrollr을 초기화하여 스크롤 이벤트를 감지합니다.

skrollr을 사용하면 요소를 부드럽게 애니메이션으로 변경할 수 있으며, 스크롤 위치에 따라 요소가 동적으로 변화하는 효과를 적용할 수 있습니다. 
그러나 skrollr을 사용할 때는 성능 이슈가 발생할 수 있으므로, 요소의 개수와 애니메이션의 복잡도를 최소화하는 것이 좋습니다.

pageOffset은 문서(document)가 스크롤되었을 때 스크롤된 거리를 나타내는 프로퍼티입니다. 
pageOffset은 window 객체와 HTMLElement 객체에서 사용할 수 있습니다.

window 객체에서의 pageOffset 프로퍼티는 현재 문서의 스크롤 위치를 나타냅니다. 
pageXOffset과 pageYOffset 프로퍼티는 각각 문서의 가로축과 세로축으로 스크롤된 거리를 반환합니다.

console.log(window.pageXOffset); // 문서의 가로축으로 스크롤된 거리
console.log(window.pageYOffset); // 문서의 세로축으로 스크롤된 거리

HTMLElement 객체에서의 pageOffset 프로퍼티는 해당 요소의 위치를 기준으로 스크롤된 거리를 나타냅니다. 
offsetLeft와 offsetTop 프로퍼티는 해당 요소의 좌측과 상단에서부터의 거리를 반환합니다.

const element = document.getElementById('myElement');
console.log(element.offsetLeft); // 요소의 좌측에서부터의 거리
console.log(element.offsetTop); // 요소의 상단에서부터의 거리

pageOffset은 스크롤 위치를 측정하여 동적인 스크롤 이벤트나 애니메이션 등에 활용할 수 있습니다.