ホバーすると丸が表示されるボタン

モーション種別
  • ドーン/ギュッ系
コンポーネント
  • ボタン
トリガー
  • ホバー
技術
  • JavaScript

概要

ホバーするとマウスの先端にViewと書かれた丸が表示されるボタンです。

ボタンにホバーしていることが一目でわかります。
ホバーした時にViewという文字も出てくるので、これはボタンとユーザーに認識させることができます。そのため、サンプルのように「装飾を減らしたボタン」に使うと良いかもしれません。

実装は、マウスの先端に表示する丸を描画するdivを用意し、CSSで丸のスタイルを作り、JavaScriptでホバーによりクラスのつけ外しをすることで表示/非表示を制御しています。

※スマホ環境時の処理について未記載だったため、以下追記
スマホ時はタップ開始、タップ中、タップ終了でイベントを検知し、タップ開始〜タップ終了まで丸が追従するようにしています。

タップ時は、指と重なって丸が見えにくくなるため、ずらして表示するようにしています。

ポイントとしては、isHoverCapableという定数でホバーができる環境かどうかをチェックした上で、マウス処理、タップ処理を分けることで、思わぬ動作バグのリスクを減らしています。
(実際、この条件がなかったときにタップ時に丸が消えないという事象がありました。)

コードサンプル

HTML

<button class="btn">Button</button>

<div class="cursor-circle">View</div>

CSS

/* ボタン */
.btn {
  position: relative;
  display: inline-block;
  padding: 0.2em 0.5em;
  border: none;
  background: transparent;
  color: #333333;
  cursor: pointer;
  overflow: hidden;
}

/* カーソル円 */
.cursor-circle {
  position: fixed;
  left: 0;
  top: 0;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: rgba(8, 37, 79, 0.8);
  color: #f4f5f9;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1em;
  font-weight: 700;
  pointer-events: none; /* マウス操作に影響しない */
  transform: translate(-50%, -50%);
  opacity: 0;
  scale: 0.8;
  transition: opacity 0.3s ease, scale 0.3s ease;
  z-index: 9999;
}

.cursor-circle.is-active {
  opacity: 1;
  scale: 1;
}

.cursor-circle { pointer-events: none; }

JavaScript

document.addEventListener("DOMContentLoaded", () => {
  const btn = document.querySelector(".btn");
  const circle = document.querySelector(".cursor-circle");
  const isHoverCapable = window.matchMedia("(hover: hover) and (pointer: fine)").matches; // hoverができる環境かどうか

  // hover あり環境(PC)
  if (isHoverCapable) {
    btn.addEventListener("mouseenter", () => {
      circle.classList.add("is-active");
    });
    btn.addEventListener("mouseleave", () => {
      circle.classList.remove("is-active");
    });

    document.addEventListener("mousemove", (e) => {
      if (circle.classList.contains("is-active")) {
        circle.style.left = e.clientX + "px";
        circle.style.top = e.clientY + "px";
      }
    });
  }

  // スマホ(タップ中のみ表示&追従)
  const setPos = (x, y) => {
    const offsetX = circle.offsetWidth / 2;
    const offsetY = circle.offsetHeight / 2;
    circle.style.left = (x - offsetX) + "px";
    circle.style.top = (y - offsetY) + "px";
  };

  btn.addEventListener("touchstart", (e) => {
    circle.classList.add("is-active");
    setPos(e.touches[0].clientX, e.touches[0].clientY);
  });

  btn.addEventListener("touchmove", (e) => {
    if (circle.classList.contains("is-active")) {
      setPos(e.touches[0].clientX, e.touches[0].clientY);
    }
  });

  btn.addEventListener("touchend", () => {
    circle.classList.remove("is-active");
  });
});

お問い合わせ Contact

制作のご依頼やその他ご相談は、お問い合わせフォームにて受け付けております。

お問い合わせフォームへ