jackmiwamiwa devblog

フロントエンドをメインに行ったことをまとめていくサイトになります。

マウスストーカーの実装について

マウスストーカーを制作したので、その方法について紹介します。

制作物

See the Pen mouse-stalker3 by miwa_shuntaro (@miwashutaro0611) on CodePen.

今回行ったこと

  • マウスの場所に応じて、要素が移動
  • ポインター要素の周り線のアニメーションの追加
  • リンク要素をホバー時にポインター要素のサイズ変更

今回行った手順

1. マウスカーソルの要素作成

cssでマウスカーソルを変更することもできますが、以下の要素にしたいため、bodyタグ・aタグにnoneを設定。

body {
  cursor: none;
}
  
a {
  cursor: none;
}

f:id:jackswim3411:20210530143221p:plain

また、カーソルについて、cssで変更できるものは以下になります。

developer.mozilla.org

2. ポインター要素の周り線のアニメーションの追加

カーソル周りに円形でアニメーションを行うものの追加を行うため、svgでアニメーションの対応をします。 今回は、輪郭の調整を行うアニメーションをしたいので、 stroke-dasharrayプロパティを変更して対応します。

developer.mozilla.org

circle {
  fill: transparent;
  stroke: #fff;
  stroke-width: 1px;
  animation: circle var3s infinite;
}

@keyframes circle {
  0%  {
    stroke-dasharray: 0 189; /* 60 * 3.14の結果*/
  }
  99.9%,
  to {
    stroke-dasharray: 189 189; /* 60 * 3.14の結果*/
  }
}

SVGでの参考にした記事は以下になります。

qiita.com

今回は対応していませんが、cssで同様のものを作成する場合は @Keita_I さんの記事がわかりやすいです。

qiita.com

3. マウスの移動に応じて、マウスカーソルの要素の移動

アイコンについては、作成を行うことができたので、カーソルが動いた時に位置を取得して、ポインター要素がマウス位置に応じて移動されるようにします。

移動時のアニメーションについては、 GSAPを使用します。

greensock.com

また、今回使用するCDNファイルは以下になります。

https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.1/TweenMax.min.js

// 大きい円のポインター要素
const elemStalker: HTMLElement = document.querySelector('.js-stalker')
// 小さい円のポインター要素
const elemCursor: HTMLElement = document.querySelector('.js-cursor')

let cWidth: number = 16 // カーソルの直径
const fWidth = 60 // ストーカーの直径
const delay = 10 // 遅延時間
let posX: number = 0 //フォロワーのX座標
let posY: number = 0 //フォロワーのY座標
let mouseX: number = 0 //マウスのX座標
let mouseY: number = 0 //マウスのY座標

// アニメーション
TweenMax.to({}, .001, {
  repeat: -1,
  onRepeat: () => {
    posX += (mouseX - posX) / delay;
    posY += (mouseY - posY) / delay;
    
    TweenMax.set(elemStalker, {
      x: posX - (fWidth / 2),
      y: posY - (fWidth / 2)
    })
    
    TweenMax.set(elemCursor, {
      x: mouseX - (cWidth / 2),
      y: mouseY - (cWidth / 2)
    })
  }
})

// マウスを移動させた時に値の変更
document.addEventListener('mousemove', (e) => {
  mouseX = e.pageX
  mouseY = e.pageY
})

マウスカーソルでの参考にした記事は以下になります。

www.evoworx.co.jp

4. リンク要素をホバー時にポインター要素のサイズ変更

ポインターの処理自体は完了しましたが、リンク時にカーソルの要素を変更させる方法として、以下になります。

  1. aタグの要素一覧を取得
  2. aタグにマウス乗ったらポインター要素にclassを付与

コードについては、以下になります。(cssについては、横幅を変更しているだけなので、省略)

// aタグの一覧を取得
const elemLinks: HTMLLinkElement[] = document.querySelectorAll('a')

// aタグの要素を全て取得し、aタグにマウスが乗ったらストーカー要素のclass名変更
elemLinks.forEach((elemLink) => {
  elemLink.addEventListener('mouseenter', () => {
    elemCursor.classList.add('is-hover') // カーソルにclass名付与
    cWidth = 60
  })
  elemLink.addEventListener('mouseleave', () => {
    elemCursor.classList.remove('is-hover') // カーソルのclass名削除
    cWidth = 16
  })
})

マウスが乗っていない時

f:id:jackswim3411:20210530171414p:plain

マウスが乗っている時

f:id:jackswim3411:20210530171427p:plain

5. body要素から外れた時(ブラウザから離れた時)、ポインター要素の非表示

ポインター要素について、以下の時に表示がおかしくなる(端に残ったまま)ため、

  • 初期ロード時
  • windowからマウスを離した時

初期ロード時(初期で0, 0の値を宣言しているため、左上にある)

f:id:jackswim3411:20210530173009p:plain

windowからマウスを離した時(画像のような状態の場合、右側に存在したまま)

f:id:jackswim3411:20210530173048p:plain

コードについては、以下になります。(cssについては、透明度を変更しているだけなので、省略)

// マウスポインター要素の全体のHTML
const elemMouseWrapper: HTMLElement = document.querySelector('.js-mouseWrapper')

// bodyに要素が乗った際にマウスカーソル・ストーカー表示
document.body.addEventListener('mouseenter', () => {
  elemMouseWrapper.classList.add('is-show')
})
document.body.addEventListener('mouseleave', () => {
  elemMouseWrapper.classList.remove('is-show')
})

最後に

今回の実装については、あたり関係ないですが、 mix-blend-modeプロパティを使用することで、マウスに要素が乗った時などにいい感じに色の反転などをしてくれるので、おすすめです!

developer.mozilla.org