GSAPでマウスストーカーを作る|Three.jsの流体・グリッチまで


GSAPで作るマウスストーカーとは、マウスの位置をGSAPのquickToで追いかけさせ、動きの遅れや弾みをイージングで付けるカーソルの演出です。位置の計算を自分で書かずに済み、リンクに吸い付く・ばねで揺れるといった上級の動きも短いコードで書けます。

jQueryやrequestAnimationFrameで書いたマウスストーカーは、ただ付いてくるだけなら十分です。ところが「ボタンに吸い付かせたい」「画像の上で色をずらしたい」と思うと、補間の計算や描画の仕組みを一から書くことになり、急に難しくなります。

この記事では、GSAPでマウスストーカーを動かす基本、リンクの上で形を変える・吸い付かせる上級の動き、Three.jsで作る流体・グリッチ・マスクリビール・ディゾルブの4種の仕組み、スマホや動きを減らす設定で止める方法までを説明します。コードは筆者が2026年11月に公開した無料ツールマウスストーカー ジェネレーターの書き出しと同じ考え方で書いています。jQueryで作る基本の仕組みはマウスストーカーでカーソルを追尾するアニメーションで説明しています。


GSAPで作るマウスストーカーとは|jQuery版との違い

GSAP版とjQuery版の違いは、「マウスへの追いかけ方」を自分で書くか、GSAPに任せるかです。jQuery版は、マウスの位置に要素の位置を毎回書き換えるか、自分で「今の位置と目標の差の何割だけ近づける」という計算を書きます。GSAP版は、目標の位置を渡すだけで、GSAPが決まった時間とイージングで追いかけさせます。

くらべる点jQuery・素のJSGSAPThree.js
得意な動きただ付いてくる・遅れて付いてくる吸い付く・ばね・形が変わる・文字が散る流体・画像の色ずれ・画像が透ける・粒に崩れる
描くものHTMLの要素HTMLの要素・SVGcanvas(WebGL)
読み込むものなし(jQuery版はjQuery)gsap.min.js(約70KB)three.js(ESモジュール)
重さ軽い軽い画面全体を毎フレーム描くので重め
向くサイトふつうのブログ・コーポレートサイトポートフォリオ・LPブランドサイト・作品紹介の頭

GSAPは2025年から、商用のサイトを含めて無料で使えます(GSAPの公式のライセンスのページ・2026年11月12日に確認)。プラグインも含めて無料になったので、GSAPを選ぶのにお金の心配は要りません。


GSAPでマウスストーカーを追従させる基本|quickToとイージング

GSAPでマウスに付いてこさせるときは、gsap.quickToを使うのが基本です。quickToは「同じ要素の同じ値を何度も新しい目標へ動かす」ための関数で、マウスが動くたびにgsap.toを呼ぶより軽く動きます(GSAPの公式ドキュメント「gsap.quickTo()」)。

<div class="stalker" aria-hidden="true"></div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
.stalker {
  position: fixed;
  top: 0;
  left: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #6366f1;
  pointer-events: none;
  z-index: 9999;
}
const el = document.querySelector(".stalker");
gsap.set(el, { xPercent: -50, yPercent: -50 });

const xTo = gsap.quickTo(el, "x", { duration: 0.4, ease: "power3" });
const yTo = gsap.quickTo(el, "y", { duration: 0.4, ease: "power3" });

addEventListener("pointermove", (e) => {
  xTo(e.clientX);
  yTo(e.clientY);
});

xPercentとyPercentに-50を入れると、丸の真ん中がマウスの先に来ます。durationを長くするほど遅れて付いてきて、easeを変えると付いてき方の感じが変わります。pointer-events: noneは必ず入れてください。入れないと、丸がリンクの上に重なってクリックできなくなります。

遅れの長さとイージングの選び方

やりたい動きdurationease
ほぼ遅れずに付いてくる0.1〜0.2power3
ふわっと遅れて付いてくる0.4〜0.8power3
止まるときに少し行き過ぎて戻る0.6back.out(2)
ばねのように揺れて止まる0.8〜1.2elastic.out(1, 0.4)

2つの丸を、小さい点は短いduration、大きい輪は長いdurationで付いてこさせると、点が先に着いて輪があとから追う、よく見る形になります。


リンクの上でマウスストーカーの形を変える

リンクやボタンの上で形を変えるには、pointeroverで「いま乗っている要素」を調べ、クラスを付け外しします。大きさや色の変化はCSSのtransitionに任せると、JavaScriptは短く済みます。

document.addEventListener("pointerover", (e) => {
  const hit = e.target.closest("a, button");
  el.classList.toggle("is-hover", !!hit);
});
.stalker {
  transition: width 0.3s, height 0.3s, background-color 0.3s;
}
.stalker.is-hover {
  width: 64px;
  height: 64px;
  background: rgba(99, 102, 241, 0.25);
}

closestを使うと、リンクの中のspanや画像に乗ったときもリンクとして見てくれます。リンク以外の場所でも形を変えたいときは、選ぶものに[data-stalker]のような属性を足し、HTMLの側で印を付けると管理しやすくなります。


ボタンに吸い付くマグネットカーソルの作り方

マグネットカーソルは、ボタンに乗っている間だけ「マウスの位置」ではなく「ボタンの中心に近い位置」を目標にする動きです。同時にボタン自体もマウスの方へ少し動かすと、吸い付いたように見えます。

let target = null;

document.addEventListener("pointerover", (e) => {
  const t = e.target.closest("a, button");
  if (t === target) return;
  if (target) {
    gsap.to(target, { x: 0, y: 0, duration: 0.7, ease: "elastic.out(1, 0.4)" });
  }
  target = t;
});

addEventListener("pointermove", (e) => {
  if (!target) {
    xTo(e.clientX);
    yTo(e.clientY);
    return;
  }
  const r = target.getBoundingClientRect();
  const cx = r.left + r.width / 2;
  const cy = r.top + r.height / 2;
  const dx = e.clientX - cx;
  const dy = e.clientY - cy;
  xTo(cx + dx * 0.15);
  yTo(cy + dy * 0.15);
  gsap.to(target, { x: dx * 0.25, y: dy * 0.25, duration: 0.4, ease: "power3" });
});

0.15と0.25が「どれだけ中心に寄せるか」の割合です。0に近いほど強く吸い付き、1に近いほどふつうの追従に戻ります。ボタンから離れたときにelastic.outで元の位置へ戻すと、ばねで弾むように戻ります。

ボタンをマウスの方へ動かすと、ボタンの当たり判定も一緒に動きます。割合を大きくしすぎるとボタンがマウスから逃げたり追いかけたりして落ち着かないので、0.3くらいまでにとどめてください。


Three.jsで作るマウスストーカー4種の仕組み

Three.jsのマウスストーカーは、画面全体に透明なcanvasを1枚重ね、そこにWebGLで色や画像を描く仕組みです。HTMLの要素を動かすGSAPと違い、画素ごとに色を計算できるので、インクのにじみや画像の色ずれのような表現ができます。ツールに入れた4種は、どれも次の3つの部品でできています。

  • 画面と同じ大きさの透明なcanvas(position: fixed・pointer-events: none)
  • 画面の座標をそのまま使えるOrthographicCamera(遠近の無いカメラ)
  • 画素の色を決めるシェーダー(ShaderMaterial)と、マウスの位置を渡すuniform

フルイド|前のフレームの絵を少しずつ薄めて重ねる

フルイド(流体)は、前のフレームの絵を少しだけずらして薄め、そこにマウスの位置へ新しい色を足す、を毎フレーム繰り返します。描いた絵を次のフレームで読むために、WebGLRenderTarget(画面に出さずに描く先)を2枚用意し、読む側と書く側を毎フレーム入れ替えます(Three.jsの公式ドキュメント「WebGLRenderTarget」)。

vec4 c = texture2D(uPrev, vUv - n) * 0.99;
vec2 d = (vUv - uMouse) * vec2(uAspect, 1.0);
float s = exp(-dot(d, d) / uRadius) * uVel;
c = mix(c, vec4(uColor, 1.0), clamp(s * 0.55, 0.0, 1.0));

0.99が「1フレームでどれだけ薄くなるか」で、1に近いほど尾が長く残ります。nはsinとcosで作った小さなずれで、これがあるので色がまっすぐ消えずに煙のように揺れます。uVelはマウスの速さで、止まっているときはインクを足さないようにしています。

グリッチ|赤・緑・青を別々の位置から読む

グリッチ(RGBずれ)は、画像を1枚の板としてcanvasに描き、赤・緑・青の3色を少しずつずれた位置から読みます。ずらす量と向きをマウスの動きの速さと向きから決めるので、動かした向きに色が割れ、止めると元に戻ります。

float r = texture2D(uTex, vUv + uShift).r;
float g = texture2D(uTex, vUv).g;
float b = texture2D(uTex, vUv - uShift).b;
gl_FragColor = vec4(r, g, b, 1.0);

マスクリビール|なぞった所だけもう1枚の画像を見せる

マスクリビールは、マウスでなぞった跡を白黒の絵(マスク)として別に描き、白い所だけ2枚目の画像、黒い所は1枚目の画像を出します。マスクもフルイドと同じく前のフレームを少しずつ薄めるので、なぞった跡は少したつと消え、元の画像に戻ります。

ディゾルブ|画像を細かい粒にして散らす

ディゾルブは、画像を細かい点の集まり(Points)として描き、マウスに近い点だけを外へ押し出します。押し出した点は少しずつ元の位置へ戻るので、マウスが離れると画像に戻ります。点の数が多いほどきれいですが重くなるので、画像の大きさに合わせて点の間隔を決めます。

Three.jsで画像を板として扱う考え方は、Three.js×GSAPで作る画面トランジションアニメーションでも使っています。


GSAPとThree.jsのどちらを選ぶか

迷ったらGSAPを選び、画像そのものを変化させたいときだけThree.jsを選ぶのがおすすめです。Three.jsの4種は見た目の強さがある分、画面全体を毎フレーム描くので、ノートパソコンでは電池とファンの音に響くことがあります。

やりたいことおすすめ理由
付いてくる丸・輪GSAPHTMLの要素を動かすだけで軽い
ボタンに吸い付かせるGSAPボタン自体も一緒に動かせる
文字を散らす・入れ替えるGSAP文字ごとの要素を動かせる
インクのように尾を引かせるThree.js前のフレームの絵を残す必要がある
画像の色をずらす・透けさせる・崩すThree.js画像の画素ごとに色を計算する必要がある

同じページに両方を入れるのはおすすめしません。マウスストーカーは1ページに1つにし、ページの性格に合わせて選んでください。


スマホと「視差効果を減らす」設定ではマウスストーカーを止める

マウスストーカーは、マウスで操作していない端末と、動きを減らす設定にしている人には出さないのが決まりです。スマホにはマウスの位置がなく、タップした所に丸が残るだけになります。また、OSの「視差効果を減らす」(Windowsは「アニメーション効果」)をオンにしている人には、画面の動きで酔う人もいます。

if (!matchMedia("(hover: hover) and (pointer: fine)").matches) return;
if (matchMedia("(prefers-reduced-motion: reduce)").matches) return;

1行目は「ホバーができて、細かく指せる道具(マウスやトラックパッド)で操作しているか」、2行目は「動きを減らす設定がオンか」を調べます(MDN「pointer」・MDN「prefers-reduced-motion」)。この2行をマウスストーカーの処理の最初に入れ、当てはまるときは何もしないで終わります。元の矢印のカーソルを消すcursor: noneも、この2行を通ったときだけhtml要素にクラスを付けて当てると、スマホや設定をオンにした人の画面は変わりません。


マウスストーカーでサイトを重くしないための確かめ方

重くなっていないかは、Chromeのデベロッパーツールの「パフォーマンス」でマウスを動かしながら録画し、1フレームが16ミリ秒(60fps)に収まっているかで確かめます。見た目だけで判断すると、速いパソコンでは問題が見えません。

  • 動かすのはtransform(x・y・scale)だけにし、top・left・width・heightを毎フレーム変えない
  • マウスの動きのたびに呼ぶ処理の中で、getBoundingClientRectを必要な要素の分だけにする
  • Three.jsはsetPixelRatioを2までにし、canvasの解像度を上げすぎない
  • デベロッパーツールの「CPUのスロットリング」を4倍遅くにして、遅いパソコンでも動きが止まらないか見る
  • ページを離れて別のタブにしたとき、描画が止まっているか(requestAnimationFrameは裏のタブで止まる)

GSAPのアニメーションをほかにも入れているページでは、GSAPアニメーションをコピペで使える無料ツールの動きと合わせて、1ページで動かす量が多くなりすぎないかも見てください。


マウスストーカー ジェネレーターで写して使う

ここまでの動きは、無料のマウスストーカー ジェネレーターで見た目を確かめ、そのままコードを写して使えます。初級25種・中級35種・GSAPの上級25種・Three.jsの上級4種・キャラ15種の104種があり、色・大きさ・遅れを変えると、書き出すHTML・CSS・JavaScriptもその値に変わります。

  1. 段(初級・中級・上級・キャラ)を選び、試したい動きを選ぶ
  2. プレビューの上でマウスを動かし、リンクやボタンにも乗せてみる
  3. 色・大きさ・遅れを調整し、元のカーソルを消すかを決める
  4. HTML・CSS・JavaScriptを写し、自分のページのbodyの終わりの近くに貼る

書き出すコードには、上で説明したスマホと動きを減らす設定で止める2行が最初から入っています。GSAPやThree.jsを使う動きは、読み込みの行も一緒に書き出します。


よくある質問

Q. GSAPのマウスストーカーはWordPressでも使えますか?

はい、使えます。テーマのfooter.phpのbodyの終わりの近くに書き出したコードを貼るか、子テーマでGSAPを読み込んでから、マウスストーカーのスクリプトを読み込みます。プラグインのコードを入れる機能を使う方法でも動きます。

Q. quickToとgsap.toの違いは何ですか?

quickToは同じ要素の同じ値を何度も動かすために、最初に一度だけ準備をしておく関数です。マウスの動きのたびにgsap.toを呼ぶと毎回新しいアニメーションを作るので、マウスストーカーのように何十回も呼ぶ処理ではquickToのほうが軽く動きます。

Q. Three.jsのマウスストーカーが表示されません。何を確かめればよいですか?

まず、ブラウザのコンソールにエラーが出ていないかを見てください。画像をcanvasに描く種類は、画像が別のドメインにあると読み込めないことがあるので、画像を同じサイトに置くか、画像の配信元で読み込みを許す設定にします。

Q. 元の矢印のカーソルは消したほうがいいですか?

ふつうの丸や輪のマウスストーカーなら、元の矢印は残すほうが分かりやすいです。マウスストーカー自体を指す場所として見せる、マグネットカーソルのような動きのときだけ、cursor: noneで消すと自然に見えます。

Q. マウスストーカーはSEOに悪い影響がありますか?

マウスストーカー自体が検索の順位を下げることはありません。ただし、重いマウスストーカーで操作が遅くなると、Core Web VitalsのINP(操作への反応の速さ)が悪くなることがあるので、上の確かめ方で重さを見てください。


まとめ

  • GSAPのマウスストーカーは、gsap.quickToにマウスの位置を渡すだけで付いてこさせられる
  • 遅れの長さはduration、付いてき方の感じはeaseで決める
  • マグネットカーソルは、ボタンに乗っている間だけ目標をボタンの中心に寄せる
  • Three.jsの4種は、透明なcanvasにシェーダーで画素の色を計算して描く
  • マウスで操作していない端末と、動きを減らす設定の人には出さない

jQueryで作るシンプルなマウスストーカーの仕組みはマウスストーカーでカーソルを追尾するアニメーションで、GSAPでマウスの位置に合わせてカードを傾ける動きはGSAPでカードをマウス追従で傾けるで説明しています。


関連記事