メニュー

マウスカーソルを追従するマウスストーカーを自作する【JavaScript / jQuery】


こんにちはWEBの佐野です。

今回は、WEBサイトでたまに見かける「マウスストーカー」を作ってみたいと思います。
マウスストーカーとはこんなものになります。

See the Pen
Untitled
by otwo (@otwo)
on CodePen.

このマウスストーカーはWEBサイトの演出として多用されるものではありませんが、テーマに合わせて使うことで、より世界観が凝られたサイトを演出することが出来ます。
実装もさほど難しくないので、ぜひアイデアの一つとして作れるようになってみてください!

ここでは学習向けに作りながらハマったポイントも交えながら実装方法を紹介しますので、参考になれば幸いです。
※ちなみにマウスストーカーはスマホでは動かないので記事の閲覧はPC推奨です

今回の実装内容

この記事ではシンプルなものと少し要件を加えたものを作っていきます。
最終的な要件はこちら。

▼使用ライブラリ
・jQuery
▼要件
・カーソルを追従する
・サイト全体ではなく指定した範囲のみで機能する
・指定範囲からカーソルが外れると指定した位置に戻る
・指定要素(今回はaタグ)にカーソルが合うとアニメーションを付ける

コピペ用のコードを用意しておくので、ローカルでの確認用に使ってください!

シンプルなマウスストーカー

まずはシンプルなマウスストーカーを作ってみます。
今回はコピペの手間が少ないように1ファイルに全部書いていきます。

<!DOCTYPE html>
<html>
<head>
  <title>マウスストーカー</title>
  <meta charset="UTF-8">
  <style type="text/css">
    /* マウスストーカー */
    #stkr{
      position: fixed;
      top: 0px;
      left: 0px;
      width: 25px;
      height: 25px;
      background: rgba(0, 0, 0, 0.5);
      border-radius: 50%;
      transition: 0.2s;
      transition-timing-function: ease-out;
      pointer-events: none;
      z-index: 10;
    }

    /* マウスストーカーに影響のない装飾CSS */
    *{ margin: 0;  padding: 0; }
    html, body{ width: 100%; height: 100%; }
    .links div{ margin: 20px 10px; }
  </style>
</head>
<body>
  <div id="stkr"></div>
  <div class="links">
    <div><a href="#" class="stkr-target">リンク1</a></div>
    <div><a href="#" class="stkr-target">リーーンク2</a></div>
    <div><a href="#" class="stkr-target">リーーーーンク3</a></div>
  </div>

  <!-- JavaScript -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script type="text/javascript">
    // マウスストーカー関連の要素(任意で変更してください)
    const mouseStalker = "#stkr";           // マウスストーカーになる要素を指定
    const mouseTarget = ".stkr-target";     // リンクなどアクションを付けたい要素を指定
    const mouseStalkerArea = window;        // マウスストーカーが機能する要素を指定

    // 処理で使う変数たち
    const stkrSize = parseInt($(mouseStalker).css("width").replace(/px/, ""));
    const stkrPosX = parseInt($(mouseStalker).css("left").replace(/px/, ""));
    const stkrPosY = parseInt($(mouseStalker).css("top").replace(/px/, ""));
    const cssPosAjust = stkrPosX + (stkrSize / 2);
    let scale = 1;

    // 追従用の処理
    $(mouseStalkerArea).hover(function(){
      $(mouseStalkerArea).mousemove(function(e){
        let x = e.clientX - cssPosAjust;
        let y = e.clientY - cssPosAjust;
        $(mouseStalker).css({
          "transform": "translate(" + x + "px," + y + "px) scale(" + scale + ")",
        });
      });
    });

    // リンクホバーの処理
    $(mouseTarget).hover(function(e){
      scale = 2;
      let x = e.clientX - cssPosAjust;
      let y = e.clientY - cssPosAjust;
      $(mouseStalker).css({
        "transform": "translate(" + x + "px," + y + "px) scale(" + scale + ")",
      });
    }, function(){
      scale = 1;
    });
  </script>
</body>
</html>

これを実行するとこうなります。

See the Pen
Untitled
by otwo (@otwo)
on CodePen.


作りはシンプルで
JavaScriptでマウスカーソルの座標を取得し、マウスストーカーの座標に反映
これの繰り返しです。

ただ、そのまま作るとカーソルにピッタリと付いてきてしまい不格好なものになるのでCSSでカーソルに少し遅れて付いてくる動きを実装しています。

実装にあたっていくつかポイントを紹介します。

CSS : transitionでアニメーション

少し遅れて付いてくる、を実装するならtransitionを使いましょう。

jQueryのanimateで出来るか試しましたが、カクカクする動きになったのと他のサイトをいくつか見てみましたがコレ一択です。

CSS : transformで座標指定

要素位置の操作にはtransformがオススメです。

位置操作だけであれば他にもcssのtop,leftやmargin,paddingでも実装できるとは思いますが、マウスストーカーのサイズ変更を視野に入れるのであれば位置、サイズを1つのプロパティで操作できるtransformを使うのがスマートだと思います。

機能追加

ここからは上で作ったマウスストーカーに機能を追加していきます。

・リンクホバーでマウスストーカーの色を変更
・リンクホバー時にマウスストーカーの位置を固定
・マウスストーカーの可動範囲を追加して、それ以外は固定位置に戻る

これらを盛り込んだものがこちら。

<!DOCTYPE html>
<html>
<head>
  <title>マウスストーカー</title>
  <meta charset="UTF-8">
  <style type="text/css">
    /* マウスストーカー */
    #stkr{
      position: absolute;
      top: 10px;
      left: 10px;
      width: 25px;
      height: 25px;
      background: rgba(0, 0, 0, 0.5);
      border-radius: 50%;
      transition: 0.2s;
      transition-timing-function: ease-out;
      pointer-events: none;
      z-index: 10;
    }
    /* マウスストーカーの可動範囲 */
    #stkr-area{
      width: 100%;
      height: 300px;
      padding: 10px;
      box-sizing: border-box;
      position: relative;
      background-color: rgb(184, 149, 247, 0.5);
    }
    /* ホバーした時の色 */
    .color1{ background-color: rgb(247, 77, 155, 0.5) !important; }
    .color2{ background-color: rgb(77, 200, 247, 0.6) !important; }
    .color3{ background-color: rgb(77, 247, 82, 0.5) !important; }

    /* マウスストーカーに影響のない装飾CSS */
    *{ margin: 0;  padding: 0; }
    html, body{ width: 100%; height: 100%; }
    .ttl{ padding-left: 30px; }
    .links div{ margin: 20px 10px; }
  </style>
</head>
<body>
  <div id="stkr-area">
    <div id="stkr"></div>
    <div class="ttl">←マウスストーカー</div>
    <div class="links">
      <div><a href="#" class="stkr-target" data-color="color1">リンク1</a></div>
      <div><a href="#" class="stkr-target" data-color="color2">リーーンク2</a></div>
      <div><a href="#" class="stkr-target" data-color="color3">リーーーーンク3</a></div>
    </div>
  </div>

  <!-- JavaScript -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script type="text/javascript">
    // マウスストーカー関連の要素(任意で変更してください)
    const mouseStalker = "#stkr";           // マウスストーカーになる要素を指定
    const mouseTarget = ".stkr-target";     // リンクなどアクションを付けたい要素を指定
    const mouseStalkerArea = "#stkr-area";  // マウスストーカーが機能する要素を指定

    // 処理で使う変数たち
    const stkrSize = parseInt($(mouseStalker).css("width").replace(/px/, ""));
    const stkrPosX = parseInt($(mouseStalker).css("left").replace(/px/, ""));
    const stkrPosY = parseInt($(mouseStalker).css("top").replace(/px/, ""));
    const cssPosAjust = stkrPosX + (stkrSize / 2);
    let stkrFix = false;
    let scale = 1;
    let scroll = 0;

    // 追従用の処理
    $(mouseStalkerArea).hover(function(){
      $(mouseStalkerArea).mousemove(function(e){
        if(stkrFix == false){
          let x = e.clientX - cssPosAjust;
          let y = e.clientY + scroll - cssPosAjust;
          $(mouseStalker).css({
            "transform": "translate(" + x + "px," + y + "px) scale(" + scale + ")",
          });
        }
      });
    }, function(){
      $(mouseStalker).css({
        "transform": ""
      });
    });

    // リンクホバーの処理
    $(mouseTarget).hover(function(){
      stkrFix = true;
      scale = 2;
      let _width = parseInt($(this).css("width").replace(/px/,""));
      let _top = $(this).position().top;
      let _left = $(this).position().left;
      let x = _left - stkrPosX - (stkrSize / 2) + (_width / 2);
      let y = _top - stkrPosX;
      $(mouseStalker).css({
        "transform": "translate(" + x + "px," + y + "px) scale(" + scale + ")",
      }).addClass($(this).data("color"));
    }, function(){
      stkrFix = false;
      scale = 1;
      $(mouseStalker).removeClass($(this).data("color"));
    });

    $(window).scroll(function(){
      scroll = $(window).scrollTop();
    });
  </script>
</body>
</html>

ソースが長くなって申し訳ないですが、これが今回の完成形です。

See the Pen
Untitled
by otwo (@otwo)
on CodePen.


ちらほらと手を入れていますがポイントになりそうなところを紹介します。

CSS : absoluteで可動域を固定

シンプルなマウスストーカーではcssのpositionにサイト全体で動くようにfixedを指定していましたが、完成形では特定の範囲でのみ機能するようにfixed → absoluteに変更しています。

それに伴ってスクロールが発生するとマウスストーカーとカーソルの位置にズレる現象が発生するので、JavaScriptにスクロール量を保持しながら位置計算時に加算する対応を加えています。

JS : data属性でクラスを付与

今回、ホバーでマウスストーカーの色を変更する処理にはdata属性を使っています。
このdata属性はHTMLとJavaScriptで任意のデータをやり取りするためのもので非常に使い勝手がいいので覚えておきましょう。

▼指定方法(タグはなんでもOK)
<a href="#" data-[任意]="なんでもOK">
の形式でHTMLタグに指定します。
例)
<a href="#" data-test="なんでもOK">

▼jQueryで値の取得
$("a").data("[任意]");
例)
console.log($("a").data("test"));   // 結果:なんでもOK

要素ごとに特定のパラメーターで処理したい時に重宝します。


いかがだったでしょうか。
モバイルファーストのサイトが多くなっているので活用場面は限られますが、一瞬でもユーザーの目を引けるギミックは見ていて楽しいですよね!
色んないアイデアと組み合わせて上手く使えたら面白いと思うのでぜひ自分流にカスタマイズしてみてください!
それではまた!

この記事をシェアする

  • twitter
  • facebook
  • Google+
  • B!はてブ
  • pocket
トップへ戻る

CONTACT

ゲーム開発、Webサイト制作に関するご相談等ございましたら、お気軽にお問い合わせください。

ゲーム開発に関する
お問い合わせはこちら

Webサイト制作に関する
お問い合わせはこちら