TODO: SkipNavigation

マウスカーソルにゆるゆると追従するマウスストーカーの実装方法

おしゃれサイトでよく目にする『ゆるゆる〜っと追従するマウスストーカー』の実装方法です。

サンプル(新規ウィンドウで開きます)

HTML

html
<div class="mouse-stalker">
  <div></div>
</div>

CSS での位置調整を簡単にするため空の <div> をひとつ入れておきます。

CSS

css
.mouse-stalker {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1px;
  height: 1px;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  pointer-events: none;
  mix-blend-mode: exclusion;
}

.mouse-stalker > div {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: #fff;
  flex-shrink: 0;
}

.mouse-stalker を 1px にしたうえで display: flex; を、 .mouse-stalker > divflex-shrink: 0; をかけることで内側の要素が常に真ん中に来るようになります。

JavaScript

※コード全体は最後に載せます。

まず変数を3つ用意します。

javascript
// マウスストーカー要素
var mouseStalker

// マウスストーカー要素の位置
var stalker = {
  x: 0,
  y: 0
}

// マウスの位置
var mouse = {
  x: 0,
  y: 0
}

mouseStalker は追従する DOM要素(あとで代入します)、 stalker.x / y は追従する要素の位置、 mouse.x / y はマウスカーソルの位置です。

つぎにイベントハンドラ。

javascript
// 読み込み後に初期化をするためのハンドラ
document.addEventListener('DOMContentLoaded', setup)

// マウスの動きを監視
document.addEventListener('mousemove', mousemove)

読み込み完了後に setup に呼び出し マウスが動くたびに mousemove を呼び出すようにしておきます。

setup の中身です。

javascript
// 初期化処理
function setup() {
  // マウスストーカー要素を取得
  mouseStalker = document.querySelector('.mouse-stalker')

  // 更新処理を開始
  update()
}

最初に定義した mouseStalker にマウスストーカー要素を代入し、更新処理である update() を呼び出しています。

続いて mousemove の中身です。

javascript
// マウスが動くたびにマウスの位置を保持しておく
function mousemove(e) {
  mouse.x = e.clientX
  mouse.y = e.clientY
}

画面上のマウス座標を mouse.xmouse.y にそれぞれ代入しています。

あとは update() にてマウスストーカー要素の位置を更新し続ければ OK です。

javascript
function update() {
  // マウスストーカー要素の位置を更新
  stalker.x += (mouse.x - stalker.x) * 0.1
  stalker.y += (mouse.y - stalker.y) * 0.1

  // マウスストーカーの位置を小数点第一位まで四捨五入
  var x = Math.round(stalker.x * 10) / 10
  var y = Math.round(stalker.y * 10) / 10

  // マウスストーカー要素のスタイルを更新
  mouseStalker.style.transform = `translate3d(` + x + 'px,' + y + 'px, 0)'

  // ループ
  requestAnimationFrame(update)
}

計算式が出てきていやな感じですが特に難しいことではありません。

javascript
stalker.x += (mouse.x - stalker.x) * 0.1

『目的地(mouse.x) - 現在地(stalker.x)』の差分の値に速度調整用の少数をかけて、現在地の値に加えていきます。

こうすることで「マウス座標とマウスストーカーが離れているほど素早く移動し、近づくほどゆっくり動く」という自然なイージングを表現できます。

速度調整用の少数の値を 0.1 としていますがこの値はなんでもよくて小さいほど動きが緩やかに、大きいほど動きがタイトになります。いろいろ数値を変えて試してみてください。

JavaScript 全体

javascript
// マウスストーカー要素
var mouseStalker

// マウスストーカー要素の位置
var stalker = {
  x: 0,
  y: 0
}

// マウスの位置
var mouse = {
  x: 0,
  y: 0
}

// 読み込み後に初期化をするためのハンドラ
document.addEventListener('DOMContentLoaded', setup)

// マウスの動きを監視
document.addEventListener('mousemove', mousemove)

// 初期化処理
function setup() {
  // マウスストーカー要素を取得
  mouseStalker = document.querySelector('.mouse-stalker')

  // 更新処理を開始
  update()
}

// マウスが動くたびにマウスの位置を保持しておく
function mousemove(e) {
  mouse.x = e.clientX
  mouse.y = e.clientY
}

// 更新処理
function update() {
  // マウスストーカー要素の位置を更新
  stalker.x += (mouse.x - stalker.x) * 0.1
  stalker.y += (mouse.y - stalker.y) * 0.1

  // マウスストーカーの位置を小数点第一位まで四捨五入
  var x = Math.round(stalker.x * 10) / 10
  var y = Math.round(stalker.y * 10) / 10

  // マウスストーカー要素のスタイルを更新
  mouseStalker.style.transform = `translate3d(` + x + 'px,' + y + 'px, 0)'

  // ループ
  requestAnimationFrame(update)
}
お役立ち男

フロントエンド専門。フリーランスで10年以上活動しています。