본문 바로가기
css

Css와 Javascript 또는 Gsap으로 스포트라이트 효과를 생성하세요.

by code-box 2022. 1. 27.
반응형

Combinig Css 마스크, 방사형 그라데이션 및 Javascript의 작은 조각

이번 주 초에는 css 마스크와 선형 그라데이션이 결합된 작은 코데펜(기다릴 수 없다면 여기를 체크)을 만들어 스포트라이트 효과를 냈고, 빛이 마우스 커서를 따라가게끔 자바스크립트를 조금 추가했다.

사람들이 데모를 좋아하는 것 같으니, 이 글에서는 데모가 어떻게 작동하는지 궁금하신 분들을 위해 데모 뒤에 있는 개념들을 설명하겠습니다.

시작해 봅시다!

 

배경 이미지

먼저 우리는 신체 요소의 배경 이미지를 설정해야 합니다. 또한 div 또는 원하는 모든 요소에 대해 이 작업을 수행할 수 있습니다(사이트의 한 섹션에서 사용하려는 경우).

body {
    margin: 0;
    height: 100vh;
    background-image: url(https://unsplash.it/1920/1080);
                            background-position: center center;
                            background-size: cover;
                          }

이 토막글에서는 먼저 신체의 여백을 제거하여 나중에 마스크를 둘러싸지 않도록 합니다. 또한 높이를 100vh(뷰포트 높이)로 설정하여 본체를 뷰포트와 동일한 높이로 만듭니다.

마지막으로 랜덤 1920 x 1080 이미지를 언플래시 라이브러리에서 가져와서 가운데로 설정하고 전체 요소/뷰포트를 덮을 수 있도록 커버 크기를 지정합니다.

 

마스크 요소

실제 마스크의 경우 전체 뷰포트를 커버하는 div를 만들 것입니다.

<div class="mask"></div>

뷰포트와 같은 크기로 만들기 위해 너비 100vw(뷰포트 너비)로 설정하고 본체 높이와 마찬가지로 높이 100vh로 설정합니다.

.mask {
    width: 100vw;
    height: 100vh;
    background-color: hsla(0,0%,0%, 0.9);
}
 

어두운 효과를 내기 위해 배경색을 검정으로 설정하고 hsla 함수를 사용하여 불투명도를 0.9로 합니다.

hsl 및 hsla 기능에 익숙하지 않다면 여기에서 확인할 수 있는 비디오를 가지고 있습니다: Css Hsl 색상 소개

Css 마스크 및 방사형 그레이디언트

마술의 첫 번째 조각은 css 마스크와 방사형 그라데이션의 조합입니다.

이름이 암시하듯이 css 마스크 속성은 우리가 포토샵에서 마스크를 만드는 것과 비슷한 방식으로 우리의 요소를 위한 마스크를 만들 수 있게 해준다. 하지만 이 경우에는 흑백 대신 흑백으로 처리한다.

 
.mask {
    mask: radial-gradient(
          circle at 50% 50%,
          transparent 40px,
          black 150px
        );
}

여기서는 마스크 속성을 .mask div에 설정하고 값을 방사형 그레이디언트 함수로 설정합니다.

첫 번째 줄 "50% 50% 동그라미"는 그라데이션의 중심을 화면 중앙으로 설정합니다.

그 다음 중앙에서 40px까지 투명한 색을 설정하고 150px부터 시작하는 검정색을 추가하면 그 사이의 모든 것이 투명에서 검정색으로 전환됩니다. 그 결과 검은색으로 희미해지는 투명한 원이 만들어집니다.

사용자 지정 속성

 

우리는 우리의 마스크가 움직이기를 원하기 때문에 우리는 우리의 경사 "구멍" 변수의 위치를 만들어야 한다. 그러면 이러한 값을 일부 css 사용자 지정 속성으로 대체하겠습니다.

먼저 이러한 속성을 정의하여 시작 값을 제공해야 합니다. 이 경우 :root에서 정의하지만 .mask 요소 자체에서도 이 작업을 수행할 수 있습니다.

:root {
    --mouse-x: 50%;
      --mouse-y: 50%;
}

이제 안쪽에서 방사형 경사 기능을 사용할 수 있습니다.

.mask {
    mask: radial-gradient(
          circle at var(--mouse-x) var(--mouse-y),
          transparent 40px,
                black 150px
                  );
}
 

모든 브라우저가 올바르게 동작하도록 설정

마스크에 대한 브라우저 지원은 전면적으로 이루어집니다.

Image description

하지만 우리는 모든 브라우저가 우리가 원하는 것을 할 수 있도록 하기 위해 -webkit-mask를 추가해야 합니다.

.mask {
    ...
      -webkit-mask: radial-gradient(
            circle at var(--mouse-x) var(--mouse-y),
            transparent 40px,
                  black 150px
                    );
}
 

그래서 우리의 완성된 css는 이렇게 보여야 한다.

:root {
    --mouse-x: 50%;
      --mouse-y: 50%;
}

body {
    margin: 0;
    height: 100vh;
    background-image: url(https://unsplash.it/1920/1080);
                            background-position: center center;
                            background-size: cover;
                          }

.mask {
    width: 100vw;
    height: 100vh;
    background-color: hsla(0,0%,0%, 0.9);
    mask: radial-gradient(
          circle at var(--mouse-x) var(--mouse-y),
          transparent 40px,
                black 150px
                  );
    -webkit-mask: radial-gradient(
          circle at var(--mouse-x) var(--mouse-y),
          transparent 40px,
                black 150px
                  );
}

javascript로 물건 옮기기

우리의 마우스 커서 위치에 맞게 그라데이션(gradient)을 움직이기 위해서는 약간의 자바스크립트가 필요하다.

마우스 위치를 얻기 위해 이벤트 목록 작성기를 추가하는 것부터 시작해보자.

 
document.addEventListener('pointermove', (pos) => {

}
                          ```

                          이벤트 수신기에서는 커서의 x 및 y 위치를 나타내는 pos.clientX 및 pos.clientY 속성을 각각 보유하는 pos 변수를 수신합니다!

                          방사형 그레이디언트는 % 값을 기준으로 위치를 설정하므로 마우스 위치를 0~100% 값으로 변환해야 합니다.

                          ```js
                          document.addEventListener('pointermove', (pos) => {
                              let x = parseInt(pos.clientX / window.innerWidth * 100);
                                  let y = parseInt(pos.clientY / window.innerHeight * 100);
                                  });
                                  ```

                                  저는 수학을 잘 못하니까 정확히 어떻게 작동하는지 알려달라고 부탁하지 마세요. 내가 아는 유일한 것은 그것이 작동하고 우리에게 x와 y 위치에 대해 0-100%의 값을 제공한다는 것이다! :p!

                                  <div class="content-ad"></div>

                                  구문 분석INT는 우리가 실제 숫자를 얻을 수 있도록 하기 위해 있는 것입니다. 하지만 이 경우에는 크게 문제가 되지 않습니다.

                                  이제 올바른 값을 얻었으므로 사용자 지정 속성을 업데이트할 수 있습니다.

                                  ```js
                                  const mask = document.querySelector('.mask');

                                  document.addEventListener('pointermove', (pos) => {
                                      let x = parseInt(pos.clientX / window.innerWidth * 100);
                                          let y = parseInt(pos.clientY / window.innerHeight * 100);

                                              mask.style.setProperty('--mouse-x', x + '%');
                                                  mask.style.setProperty('--mouse-y', y + '%'); 
                                                  });
                                                  ```

                                                  첫 번째 줄은 마스크 요소에 대한 참조를 얻어서 특성을 조작할 수 있습니다.

                                                  그런 다음 mask.style.setProperty를 두 번 호출하여 해당 속성의 값을 업데이트합니다. 전달된 첫 번째 인수는 업데이트할 속성의 이름이고 두 번째 인수는 설정할 값입니다. 우리의 경우 정확한 단위를 만들기 위해 백분율 기호를 붙입니다.

                                                  <div class="content-ad"></div>

                                                  완성된 js 코드는 지금과 같아야 합니다.

                                                  ```js
                                                  const mask = document.querySelector('.mask');

                                                  document.addEventListener('pointermove', (pos) => {
                                                      let x = parseInt(pos.clientX / window.innerWidth * 100);
                                                          let y = parseInt(pos.clientY / window.innerHeight * 10);

                                                              mask.style.setProperty('--mouse-x', x + '%');
                                                                  mask.style.setProperty('--mouse-y', y + '%'); 
                                                                  });
                                                                  ```

                                                                  우리는 이제 아래의 코드펜과 같이 기능적인 스포트라이트 효과를 얻어야 합니다. 펜 위로 마우스를 움직여!

                                                                  ## Gsap과 함께 좀 더 발전해 나가자, 알다시피... 할 수 있다고 해서요

                                                                  비록 이 유스케이스에 대해서는 완전히 과잉 살상이긴 하지만, 저는 Gsap에 가입되어 있지 않은 엄청난 팬입니다. 그래서 여러분이 만나게 해 주신다면 이 기회에 아주 조금 보여드리도록 하겠습니다.

                                                                  <div class="content-ad"></div>

                                                                  Gsap은 "현대 웹을 위한 전문가급 자바스크립트 애니메이션"이다. 일반적인 용어로 자바스크립트로 애니메이션을 만들 수 있는 놀라운 라이브러리입니다. 그게 네 일이라면 반응하든지!

                                                                  거의 모든 사람이 다 하는 것 같아! :p!

                                                                  하지만 걱정 마세요... 이 경우 우리는 Gsap 기능 두 개만 사용할 것입니다.

                                                                  저는 css/javascript 조합에 좀 더 깊이 들어가 있는 다른 콘텐츠들을 연구하고 있으며 Gsap 라이브러리도 조금 더 다룰 예정입니다. 궁금하시다면 여기 Dev나 트위터에서 저를 팔로우해주세요!

                                                                  이제 Gsap을 프로젝트에 투입하겠습니다.

                                                                  <div class="content-ad"></div>

                                                                  ```js
                                                                  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
                                                                  ```

                                                                  멋지고 간단해! 이제 gsap.utils에서 mapRange라는 도우미 함수를 가져옵니다.

                                                                  ```js
                                                                  const {mapRange} = gsap.utils;
                                                                  ```

                                                                  다시 말하지만 나는 수학을 잘하지 못하지만, mapRange는 내가 설명할 수 있는 것이다. 아니면 적어도 한번 해보는 건 어때?

                                                                  이름이 mapRange를 의미하는 것처럼 한 범위를 다른 범위로 매핑합니다. 그래서 우리가 0에서 1000의 범위를 가지고 있고, 또 다른 0에서 100의 범위를 가지고 있다고 가정해보자. 첫 번째 범위에서 우리의 값이 100이면 두 번째 범위에서는 10으로 매핑됩니다.

                                                                  <div class="content-ad"></div>

                                                                  0-1000: 100
                                                                  0-100: 10

                                                                  그게 말이 됐으면 좋겠어!? 어쨌든, 마우스의 x 위치는 뷰포트 폭(window.innerWidth)의 0과 폭 사이이며, 0에서 100% 사이의 값으로 매핑해야 합니다. 우리는 아래와 같이 mapRange 기능을 사용하여 그렇게 할 수 있습니다.

                                                                  ```js
                                                                  document.addEventListener('pointermove', (pos) => {
                                                                      let x = mapRange(
                                                                            0, window.innerWidth,
                                                                                  0, 100, 
                                                                                        pos.clientX
                                                                                            );
                                                                                            });
                                                                                            ```

                                                                                            말했듯이 0과 window.innerWidth 사이의 값을 0과 100 사이의 값으로 매핑하고 실제 값 pos.clientX를 커서 x 위치로 전달합니다.

                                                                                            그런 다음 이 과정을 반복하여 innerWidth와 inner를 교환하여 y 값을 얻을 수 있습니다.높이

                                                                                            <div class="content-ad"></div>

                                                                                            ```js
                                                                                            document.addEventListener('pointermove', (pos) => {
                                                                                                let x = mapRange(
                                                                                                      0, window.innerWidth,
                                                                                                            0, 100, 
                                                                                                                  pos.clientX
                                                                                                                      );
                                                                                                                          let y = mapRange(
                                                                                                                                0, window.innerHeight,
                                                                                                                                      0, 100,
                                                                                                                                            pos.clientY
                                                                                                                                                );
                                                                                                                                                });
                                                                                                                                                ```

                                                                                                                                                이제 우리의 가치관을 다시 얻었으니 gsap을 사용할 수 있습니다.기능을 설정하여 사용자 지정 속성을 업데이트합니다.

                                                                                                                                                ```js
                                                                                                                                                document.addEventListener('pointermove', (pos) => {
                                                                                                                                                    ...
                                                                                                                                                        gsap.set(mask,{
                                                                                                                                                              '--mouse-x': x + '%'
                                                                                                                                                                  })
                                                                                                                                                                      gsap.set(mask,{
                                                                                                                                                                            '--mouse-y': y + '%'
                                                                                                                                                                                })
                                                                                                                                                                                });
                                                                                                                                                                                ```

                                                                                                                                                                                Gsap.set에는 두 개의 매개 변수가 사용됩니다. 첫 번째는 값을 설정하려는 요소입니다. 우리의 경우 마스크 참조를 전달하지만 요소의 css 선택기가 되는 문자열을 전달할 수도 있습니다. 그래서 우리는 ".mask"를 사용할 수 있었고, 그것은 같은 일을 했다.

                                                                                                                                                                                두 번째 매개 변수는 설정하려는 속성과 각각의 값에 대한 키 값 쌍을 포함하는 개체여야 합니다. 이 경우 키의 사용자 지정 속성 이름과 생성한 x 및 y 값 및 % 기호를 사용합니다.

                                                                                                                                                                                <div class="content-ad"></div>

                                                                                                                                                                                이 모든 것을 합치면 우리는 아래에 코드를 만들어야 합니다.

                                                                                                                                                                                ```js
                                                                                                                                                                                const mask = document.querySelector('.mask');
                                                                                                                                                                                const {mapRange} = gsap.utils;

                                                                                                                                                                                document.addEventListener('pointermove', (pos) => {
                                                                                                                                                                                    let x = mapRange(
                                                                                                                                                                                          0, window.innerWidth,
                                                                                                                                                                                                0, 100, 
                                                                                                                                                                                                      pos.clientX
                                                                                                                                                                                                          );

                                                                                                                                                                                                              let y = mapRange(
                                                                                                                                                                                                                    0, window.innerHeight,
                                                                                                                                                                                                                          0, 100,
                                                                                                                                                                                                                                pos.clientY
                                                                                                                                                                                                                                    );

                                                                                                                                                                                                                                        gsap.set(mask,{
                                                                                                                                                                                                                                              '--mouse-x': x + '%'
                                                                                                                                                                                                                                                  })

                                                                                                                                                                                                                                                      gsap.set(mask,{
                                                                                                                                                                                                                                                            '--mouse-y': y + '%'
                                                                                                                                                                                                                                                                })
                                                                                                                                                                                                                                                                });
                                                                                                                                                                                                                                                                ```

                                                                                                                                                                                                                                                                Gsap을 굳이 사용할 필요가 없었는데, 이것이 할 수 있는 일의 일부일 뿐인데, 여러분이 더 많은 것을 탐험하는 것에 호기심을 가지셨기를 바랍니다.

                                                                                                                                                                                                                                                                여기 업데이트된 코드가 담긴 코드펜이 있습니다.

                                                                                                                                                                                                                                                                ### 따라와요?

                                                                                                                                                                                                                                                                <div class="content-ad"></div>

                                                                                                                                                                                                                                                                유튜브, 트위터 또는 Dev.to @Vanaf1979에서 저를 팔로우하시면 더 많은 것들을 보실 수 있습니다.

                                                                                                                                                                                                                                                                코데펜에 사용한 사진은 토드 콰켄부시가 `언스플래시`에서 무료로 제공해준 거예요

                                                                                                                                                                                                                                                                읽어주셔서 감사합니다, 안전하게 지내고 올바른 종류의 긍정적으로 지내세요!

댓글