icon

【JS | GSAP】マウスを特定の要素に乗せたら、画像が追従する。

JavaScriptのmousemove
投稿日時

更新日時

今回は、マウスを特定の要素に乗せたら、画像がマウスを追従して表示される機能を実装してみました。JavaScriptを使用し、GSAPでアニメーションをつけています。

まずはデモサイトをご覧ください。

DEMOサイトはこちら


GSAP導入

/**html**/

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

ソースコード一覧

HTML

/**html**/

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="robots" content="noindex">
  <title>hover-images-stalker</title>
  <link rel="stylesheet" href="https://unpkg.com/ress/dist/ress.min.css">
  <link rel="stylesheet" href="css/style.css">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@500;700;800&family=Zen+Kaku+Gothic+Antique:wght@500;700&display=swap" rel="stylesheet">
</head>

<body>
  <ul id="section">
    <li class="item">
      <a href="" class="a">
          <p>category</p>
          <div class="text">
            <h2>test-ttl-01test-ttl-01test-ttl-01</h2>
            <p>2022.04.18</p>
          </div>
      </a>
    </li>
    <li class="item">
      <a href="" class="a">
        <p>category</p>
        <div class="text">
          <h2>test-ttl-01test-ttl-01test-ttl-02</h2>
          <p>2022.04.18</p>
        </div>
      </a>
    </li>
    <li class="item">
      <a href="" class="a">
        <p>category</p>
        <div class="text">
          <h2>test-ttl-01test-ttl-01test-ttl-03</h2>
          <p>2022.04.18</p>
        </div>
      </a>
    </li>
    <li class="item">
      <a href="" class="a">
        <p>category</p>
        <div class="text">
          <h2>test-ttl-01test-ttl-01test-ttl-04</h2>
          <p>2022.04.18</p>
        </div>
      </a>
    </li>
    <div class="hover-stalker-img"></div>
  </ul>
</body>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.10.2/gsap.min.js"></script>
  <script type="text/javascript" src="js/main.js"></script>
</body>
</html>

Scss

/**scss**/

/*font-family*/
$family-poppins:'Poppins', sans-serif;
$family-zen-kaku: 'Zen Kaku Gothic Antique', sans-serif;

/*color*/
$gray: rgb(41, 41, 41);
$white: #fff;
$white02:rgba(255, 255, 255, 0.228);
$font-color-ctg: rgb(162, 162, 162);

body {
  font-family: $family-poppins;
  font-family: $family-zen-kaku;
  background-color: $gray;
}

a {
  color: #fff;
  text-decoration: none;
}

li {
  list-style: none;
}

ul {
  width: 100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  flex-flow: column;
  align-items: center;
  overflow: hidden;
  position: relative;
  li {
    width: 80%;
    margin: 0 auto;
    position: relative;
    z-index: 1;
    a {
      display: flex;
      align-items: center;
      padding: 48px 0;
      position: relative;
      &::before {
        content: "";
        height: 1px;
        width: 100%;
        background-color: $white02;
        display: block;
        position: absolute;
        top: 0;
      }
      &::after {
        content: "";
        height: 2px;
        width: 100%;
        background-color: $white;
        display: block;
        position: absolute;
        top: 0;
        transform: scale(0);
        transform-origin: right center;
        transition: transform 1s cubic-bezier(.19,1,.22,1);
      }
      > p {
        font-size: 16px;
        color: $font-color-ctg;
        margin-right: 5%;
      }
      div {
        h2 {
          font-size: 24px;
          letter-spacing: 0.07em;
        }
        p {
          font-size: 14px;
          color: $font-color-ctg;
        }
      }
      &:hover {
        &::after {
          transform: scale(1);
          transform-origin: left center;
        }
      }
      .hover-img {
        width: 350px;
        height: 350px;
        overflow: hidden;
        position: absolute;
        top: 0;
        left: 0;
        pointer-events: none;
        z-index: 0;
        opacity: 0;
        img {
          display: block;
          width: 100%;
          height: 100%;
          object-fit: cover;
          transform: scale(1.1);
        }
      }
      &.js-active {
        z-index: 2;
        p {
          z-index: 2;
        }
        .text {
          z-index: 2;
          h2 {
            opacity: 1;
            transition: opacity 2s cubic-bezier(.19,1,.22,1);
          }
        }
      }
    }
  }
  .hover-stalker-img {
    position: absolute;
    display: block;
    top: 0;
    left: 0;
    width: 350px;
    height: 350px;
    background-position: 0 0;
    background-size: cover;
    transform: translate(-50%, -50%);
    z-index: 0;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }
}

JavaScript

コードを部分的に分けて説明します。

/**js**/

const wrapper = document.getElementById('section');
wrapper.addEventListener('mouseenter', (e) => {
  gsap.to(image,{
    opacity: .5,
    visibility: "visible",
  })
})

「mouseenter」は、マウスが指定した要素内に入った時のアクションを指定します。ここでは、GSAPを使用して、マウスが「#section」に入ったら「image」要素に「opacity: .5;」「visibility: visible;」を追加します。

/**js**/

wrapper.addEventListener('mouseleave', (e) => {
  gsap.to(image, {
    autoAlpha: 0,
  })
})

「mouseleave」は、マウスが指定の要素から外に出たら行う動作を指定できます。ここでは、GSAPを使用して、「autoAlpha: 0」で「opacity: 0;」と「visibility: hidden;」を指定しています。

/**js**/

const image = document.querySelector('.hover-stalker-img');

wrapper.addEventListener('mousemove', (e) => {
  gsap.to(image, {
    duration: 2,
    x: e.pageX + 300,
    y: e.pageY - 100,
    ease: "Power4.easeOut",
  })
})

「mousemove」は、マウスが指定の要素内にある時に行う動作を指定できます。ここでは、「image」要素(マウスを追従する画像)が、少し遅れて追従し、表示位置を少し右上に指定しています。

/**js**/

  const items = document.querySelectorAll('.item');
  const imgArr = [
    './images/fashion-01.jpg',
    './images/fashion-02.jpg',
    './images/fashion-04.jpg',
    './images/fashion-13.jpg',
  ];
  items.forEach((item, i) => {
    item.addEventListener('mouseenter', (e) => {
      image.style.backgroundImage = `url("${imgArr[i]}")`;
      gsap.set(image, {
        backgroundPosition: "center",
        
      });
      gsap.to(image, {
        repeat: -1,
        ease: "liner",
      });
    })
  })

↑最後は、画像を配列に格納してそれぞれの要素にマウスが入ったら取り出す動作を行なっています。「forEach」を使用して、マウスが「.item」に入ったら繰り返し、背景に画像を追加する動作を行なっています。「image.style.backgroundImage = url("${imgArr[i]}");」は、image要素にCSSで背景を設定することを示しています