丸がカーソルを追いかける インタラクションの動き

通称:カーソルストーカーCursor Follower

見本の中でマウスを動かしてください。リンクの上では丸が大きくなります。マウスのある画面でだけ出ます(指で触る画面・キーボードの操作では出ません)。

マウスを動かすと、小さな丸が少し遅れてついてきます。リンクやボタンの上では丸が大きくなり、押せる場所だと伝わります。本物のカーソルは消しません。

自分のサイトの中身で、この形を作らせる指示文です。最初の「サイトの情報」を書き換えてから渡します。今あるページを直させるときは、その HTML を貼ります。

この形で作る
# 動かすもの(ここを書き換える)
- 動かす要素:〈例:各セクションの見出しとカード、商品の写真〉
- 今あるページ:〈今のページに付けるなら、その HTML と CSS を貼る。新しく作るなら空ける〉

# 動きの呼び名
一般に「カーソルストーカー」(Cursor Follower)と呼ばれる動きです。

# 作ってほしい動き
Cursor Follower(丸がカーソルを追いかける)。マウスを動かすと、直径 16px の丸が少し遅れてついてくる。リンクやボタンの上では丸が 2.5倍に大きくなる。本物のカーソルは消さない。

# 動き
- きっかけ:ページの上でマウスを動かしたとき(pointermove)。マウスだけで動き、指・ペン・キーボードでは何も起きない
- 追いかけ方:requestAnimationFrame で、毎フレーム カーソルまでの残りの距離の (1 − 0.8) だけ近づく(0.8 が大きいほど遅れる)。画面の更新の速さ(60Hz・120Hz)で速さが変わらないよう、前のフレームからの経過時間で補正する
- 位置:丸は position: fixed で、transform: translate3d(x, y, 0) で動かす。丸の中心がカーソルに来るようにする
- リンクの上:カーソルの下の要素が a か button のとき、丸を scale(2.5) にし、少し薄くする(0.25秒・cubic-bezier(0.22, 1, 0.36, 1))
- 追いついたら requestAnimationFrame を止める。マウスがページの外へ出たら丸を隠す

# 付ける場所
- 作品集やブランドのサイトのページ全体

# 守ってほしいこと
- 丸は pointer-events: none と aria-hidden="true" にする(クリックの邪魔をせず、読み上げない)
- matchMedia('(hover: hover) and (pointer: fine)') が当てはまらない画面(スマホ・タブレット)では出さない
- cursor: none にしない。丸は飾りで、本物のカーソルの代わりにしない
- 丸に情報を載せない(マウスを使わない人には見えないため)
- 動きを控える設定では丸を出さない

# 軽さと配慮(どの動きでも守る)
- 動かすのは transform と opacity だけにする(top・left・width・height・margin は動かさない)
- 動きを控える設定(prefers-reduced-motion: reduce)のときは動かさず、最後の状態で表示する
- 画面に入ったかは IntersectionObserver で見る。scroll イベントで毎回位置を測らない
- JavaScript が動かない環境でも中身が見えるようにする(最初に隠す指定は、JavaScript が付ける class の下に書く)
- will-change を付けるなら動いている間だけにする

# 出力
- 足す CSS と JavaScript を分けて出す。ライブラリは使わない
- 時間・距離・速さの変わり方は CSS 変数にまとめ、あとから変えやすくする
- 今あるページを渡したときは、HTML に足す class や属性だけを書き、ほかの見た目は変えない

マウスの動き・ボタンを押したこと・送信が済んだことに返事をする動きを4種類の型に分け、AIへの指示文・試せる見本・コードを載せています。見本の下で量や時間を変えると、指示文とコードも同じものに変わります。

インタラクションの動きはどの型を選ぶか

インタラクションの動きは、読み手の操作に画面が返事をするための演出です。カーソルにつきそう2つの型はマウスのある画面だけの遊びで、押したことに返事をする2つの型は、指でもキーボードでも同じように返ってきます。遊びの型ほど、使う場所を絞ると上品に見えます。

こんなとき 向いている動き 形の型(UIパターン集)
作品集やブランドのサイトで、マウスの動きに遊びを付けたい丸がカーソルを追いかける(カーソルストーカー)—
写真の多いサイトのトップで、なぞると写真が次々に出る仕掛けを入れたい写真がカーソルの跡に並ぶ(イメージトレイル)—
ボタンを押したことを、押した場所ですぐに返したい押した所から波紋が広がる(リップルエフェクト)CTA
申し込みや登録が済んだことを、特別な場面として祝いたい紙吹雪が舞う(紙吹雪エフェクト)フォーム(送信完了型)

どの型でも守ること

  1. カーソルにつきそう型は、マウスのある画面でだけ出す。matchMedia('(hover: hover) and (pointer: fine)') が当てはまらないスマホやタブレットでは出しません。キーボードで操作する人にも見えないので、丸や写真に情報を載せず、飾りにとどめます。
  2. 常に出しておく飾りにしない。カーソルの型は作品集やブランドのサイトなど、遊びが似合う場面に絞ります。本物のカーソルは消さず、丸や写真は pointer-events: none にして操作の邪魔をしません。
  3. 返事は、押した場所で、押した瞬間に。波紋は click ではなく pointerdown で始め、キーボードで押したときはボタンの真ん中から広げます。
  4. 紙吹雪は1回だけ、ここぞという時だけ。送信や登録が済んだあとに1回だけ出し、ボタンを押すたびには出しません。済んだことは「送りました」の文字(role="status")でも伝えます。
  5. 足した要素は、終わったら外し、数に上限を付ける。写真・波紋・紙片は動き終わったら DOM から外します。動きを控える設定では、カーソルの2型と紙吹雪は出さず、波紋は色の変化だけを残します(見本の「動きを控える設定で見る」で確かめられます)。

よくある質問 (FAQ)

カーソルにつきそう2つの型は出ず、押したことに返事をする2つの型は指でも動きます。スマホにはカーソルがなく、指でなぞるとページのスクロールと取り合いになるため、丸と写真は (hover: hover) and (pointer: fine) の画面でだけ出しています。波紋は指で押した位置から広がり、紙吹雪は送信が済んだときに同じように舞います。

消さないことをおすすめします。丸は少し遅れてついてくるので、本物のカーソルを消すと、押したい場所と丸の位置がずれて見え、押し間違いが起きます。動きを控える設定の人には丸が出ないので、カーソルを消していると何も見えなくなります。丸は飾りとして、本物のカーソルに添えるだけにします。

1回だけ舞わせるなら、ライブラリなしで足ります。ここのコードは、紙片の要素を作って Web Animations API(element.animate)で transform と opacity を動かし、全部が終わったら層ごと外しています。紙片は 30〜60枚くらいで十分お祝いらしく見えます。コードでは上限を 120枚にして、連打されても重ねて出さないようにしています。

出す条件と、片付け方です。「カーソルに丸をつけて」「紙吹雪を出して」だけだと、スマホでも出る作りや、要素が増え続ける作り、押すたびに紙吹雪が出る作りになりがちです。ここの指示文は、どの画面で出すか・何をきっかけに出すか・同時に出す数の上限・終わったら外すことを書き、Cursor Follower のような英語の一般名も添えています。