このサイトには、マウスポインタを追いかける流れ星カーソルの演出があります。実装自体は別記事で紹介していますが、ここではその一行目にある分岐について書きます。

const fine =
  window.matchMedia &&
  window.matchMedia("(hover: hover) and (pointer: fine)").matches;
if (!fine) return;

「劣化」ではなく「非表示」を選ぶ

タッチデバイス向けにこの演出を出す方法はいくつか考えられます。タップ位置に一瞬だけ光らせる、指を離した瞬間だけ演出を出す、そもそも簡略版を作る——などです。しかし今回は、pointer: fine(マウスのような精密なポインタ)でない環境では、演出を丸ごと出さないという選択をしました。

理由は単純で、この演出の価値は「ポインタの動きに追従して尾を引く」という、常時の連続入力があって初めて成立する体験だからです。タッチデバイスでは、そもそも「ホバーで先読みする」という概念自体がありません。中途半端な簡略版を作ると、それはそれで実装・保守コストが二重に発生する上、タッチユーザーにとって「劣化版」を見せることになり、体験として誰も幸せになりません。

hover: hover も一緒に見る理由

pointer: fine だけでなく hover: hover も条件に含めているのは、スタイラスペンなど「精密な入力はできるが、ホバー状態を保持できないデバイス」を除外するためです。ホバーができない環境でカーソル追従演出を出しても、指を離した瞬間にしか動きが見えず、これも中途半端な体験になります。

分岐は「入り口」に置き、以降のコードを分岐で汚さない

if (!fine) return;
// ここから先は「精密ポインタがある」ことが保証された世界

関数の先頭で早期リターンすることで、以降のコード(イージング計算やパーティクル生成など)には一切分岐を書く必要がなくなります。もし演出のあちこちに if (fine) { ... } を散りばめる実装にしていたら、コードの見通しは大きく悪化していたはずです。「対応しない環境を早期に切り捨てる」という判断は、その後のコードの単純さに直結します。

装飾的な演出を追加するときほど、「動かなかったときに何を表示するか」より先に、「そもそも動かすべきでない環境はどこか」を決めておくことが、実装をシンプルに保つ近道だと感じています。