실용적인 알고리즘

[자바스크립트] 마우스 이동에 따른 이미지 움직임 & 글레어 효과

hminor 2024. 4. 17. 20:09
반응형

해당 코드는 유튜브의 코딩애플님의 영상을 보며 적용했습니다.

구현 과정

  • 우선 css요소는 하나씩 적용하며 변경하면 더욱 재미있는 효과가 나올 것 같으며
  • 가장 중요했던 것으로는 이벤트 요소로 mousemove에 따른 것으로 
    • 해당 이벤트가 적용될 때마다 전달해져 오는
    • 파라미터값인 e의 offset값으로 x,y 좌표값을 가져올 수 있었다.
    • 여기서 offset은 특정 값으로부터의 위치로 
    • 예를 들어 문자열 "abcdef"가 있다면 c는 a위치에서 offset 2가 된다.
  • 그리고 마우스 움직임에 따른 회전을 적용하기 위해서 rotate를 적용할 때 
    • 해당 영상에 있는 효과처럼 Y축으로 적용할 때는 
    • x 위치에 따라 -20deg ~ 20deg를 적용하기 위해서
    • x*a+b = -20deg ~ 20deg 로 적용해서
    • 카드 폭으로 예시를 들어 아래 주석에 작성했으니 확인하면 좋을 듯.
    • 그리고 transform에 perspective를 적용하여 원근 효과까지 함께 적용하여 
    • 3D 효과를 더욱 줄 수 있다.
  • 글레어(glare) 효과를 주기 위해 
    • 우선 기존 카드 위에 있어야 하기에 position부터 absolute를 적용한 뒤
    • linear-gradient 효과로 반짝임 효과를 주기.
    • 그리고 카드와 같은 크기의 태그에 mousemove 이벤트가 적용될 때마다
    • 카드가 움직이지만 계속해서 패턴을 적용하기 위해
    • overlay에 background-position에 위치 값을 가변 값을 넣어서 적용하여
    • 의도한 효과를 적용할 수 있다.
  • 그리고 마우스가 해당 영역을 이탈했을때는
    • mouseout으로 적용하여 그에 따른 원하는 효과를 추가적으로 적용할 수 있다.
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .container {
        width: 414px;
        height: 600px;
        transition: all 0.2s;
      }
      .overlay {
        position: absolute;
        width: 414px;
        height: 600px;
        background: linear-gradient(
          105deg,
          transparent 40%,
          rgba(255, 219, 112, 0.8) 45%,
          rgba(132, 50, 255, 0.6) 50%,
          transparent 54%
        );
        filter: brightness(1.1) opacity(0.9);
        mix-blend-mode: color-dodge;
        background-size: 150% 150%;
        background-position: 100%;
        transition: all 0.2s;
      }
      .card {
        width: 414px;
        height: 600px;
        background-image: url("hero_card.png");
        background-size: cover;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="overlay"></div>
      <div class="card"></div>
    </div>
  </body>

  <script>
    var container = document.querySelector(".container");
    var overlay = document.querySelector(".overlay");
    container.addEventListener("mousemove", function (e) {
      var x = e.offsetX;
      var y = e.offsetY;

      // x*a + b = deg
      // 414a + b = -20 => 414a = -40 => -0.09
      // 0 + b = 20

      // 600a + b = 20 => 600a = 40 => a = 1/15
      // b = -20

      var Ydeg_val = -0.097 * x + 20;
      var Xdeg_val = (1 / 15) * y - 20;
      // perspective = 원근 효과
      container.style = `transform: perspective(800px) rotateX(${Xdeg_val}deg) rotateY(${Ydeg_val}deg)`;

      // glare 효과
      // background-position은 이동을 시켜도 패턴을 계속해서 적용할 수 있다.
      overlay.style = `filter: opacity(0.9); background-position: ${
        x / 5 + y / 5
      }%`;
    });

    container.addEventListener("mouseout", function () {
      overlay.style = "filter: opacity(0.5); background-position: 207%";
      container.style =
        "transform: perspective(800px) rotateY(0deg) rotateX(0deg)";
    });
  </script>
</html>

 

구현 결과물