マウスストーカーを作ってみた。作り方もご紹介します。
マウスストーカーというものをご存知でしょうか? マウスカーソルに追従してくるアイコンなどのこと指します。
昔のホームページではキラキラしたものやキャラクターが追従してきて結構鬱陶しいものが多くありました(笑)
しかし、現在ではお洒落なサイトでよく見かけるようになってきました。主に半透明の丸アイコンが多い印象です。
今回の記事ではマウスストーカーを調べながら作ってみましたのでご紹介します!
目次
マウスストーカーを作ってみた。
今回作成したマウスストーカーの特徴は以下となります。
- 大きさの違う2つの丸アイコンが時間差で追従
- リンク(aタグ)にホバーしたときに追従アイコンの大きさと色を変更
- クリックで追従アイコンを縮小
- マウスカーソルが画面外に行くと追従アイコンを非表示
デモを用意しましたので御覧ください
PCでご確認ください。
マウスストーカーの作り方
ソースコードの紹介とともに作り方を紹介します。
TweenMaxをインストール
今回ご紹介する方法はアニメーション用ライブラリであるTweenMaxを使用します。
CDN(scriptタグ)の場合
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
NPMの場合
npm i gsap
import {TweenMax} from "gsap/TweenMax";
CSS(scss)を記述
CSSを下記のように記述します。HTMLはJavaScriptで生成するため不要です。
.js-cursor__main {
pointer-events: none;
position: fixed;
top: 0;
left: 0;
width: 10px;
height: 10px;
background: #000;
border-radius: 50%;
z-index: 1001;
opacity: 0;
transition: opacity .2s;
.is-moved & {
opacity: 1;
}
.is-outside & {
opacity: 0;
}
}
.js-cursor__option {
pointer-events: none;
position: fixed;
top: 0;
left: 0;
width: 40px;
height: 40px;
border-radius: 50%;
background: #ddd;
z-index: 1000;
opacity: 0;
transition: opacity .2s .2s, background .2s;
.is-moved & {
opacity: 0.5;
}
.is-outside & {
opacity: 0;
}
.is-hover & {
background: #00FFFF;
}
}
.js-cursor__main
は小さい黒丸のアイコンです。
.js-cursor__option
は半透明のグレーのアイコンです。
JavaScriptを記述(ES6)
少々長いので後ほど解説します。
class Cursor {
constructor() {
const el = `
<div class="js-cursor">
<div class="js-cursor__main"></div>
<div class="js-cursor__option"></div>
</div>`
document.body.insertAdjacentHTML('beforeend', el);
this.wrap_el = document.querySelector('.js-cursor');
this.main_el = document.querySelector('.js-cursor__main');
this.option_el = document.querySelector('.js-cursor__option');
this.position = {
mouseX: 0,
mouseY: 0,
currentX: 0,
currentY: 0
}
this.eventStatus = {
click: false,
hover: false
}
}
init() {
this.attachEvent();
this.tween();
}
attachEvent() {
//カーソルの位置を取得
document.addEventListener('mousemove', (e) => {
this.position.mouseX = e.clientX;
this.position.mouseY = e.clientY;
this.wrap_el.classList.add('is-moved');
});
//画面外判定
document.body.addEventListener("mouseleave", () => {
this.wrap_el.classList.add('is-outside');
}, false);
document.body.addEventListener("mouseenter", () => {
this.wrap_el.classList.remove('is-outside');
}, false);
//クリック判定
document.addEventListener('mousedown', (e) => {
this.eventStatus.click = true;
})
document.addEventListener('mouseup', (e) => {
this.eventStatus.click = false;
})
// aタグのホバー判定
// 監視ターゲットの取得
const body = document.body;
// オブザーバーの作成
const observer = new MutationObserver(records => {
let link = document.querySelectorAll('a');
for (const target of link) {
target.addEventListener('mouseenter', (e) => {
this.eventStatus.hover = true;
this.wrap_el.classList.add('is-hover');
})
target.addEventListener('mouseleave', (e) => {
this.eventStatus.hover = false;
this.wrap_el.classList.remove('is-hover');
})
}
})
// 監視の開始
observer.observe(body, {
childList: true
})
}
tween() {
TweenMax.to({}, .001, {
repeat: -1,
onRepeat: () => {
//減速処理
this.position.currentX += (this.position.mouseX - this.position.currentX) * 0.5;
this.position.currentY += (this.position.mouseY - this.position.currentY) * 0.5;
TweenMax.set(this.main_el,
{
css: {
x: this.position.currentX - 5,
y: this.position.currentY - 5
}
});
TweenMax.to(this.option_el, 0.3,
{
css: {
x: this.position.currentX - 20,
y: this.position.currentY - 20,
scale: this.scale(this.eventStatus)
}
});
}
});
}
scale(v) {
if (v.hover == true && v.click == false) {
return 1.6
} else if (v.hover == false && v.click == true) {
return 0.6
} else if (v.hover == true && v.click == true) {
return 0.6
} else {
return 1
}
}
}
let cursor = new Cursor();
cursor.init();
ソースコードの解説
先程ご紹介したJavaScriptのソースコード解説をします。
HTMLを生成
マウスストーカー用のHTMLを</body>
の直前に生成します。
const el = `
<div class="js-cursor">
<div class="js-cursor__main"></div>
<div class="js-cursor__option"></div>
</div>`
document.body.insertAdjacentHTML('beforeend', el);
マウスカーソルの操作に応じた状態を取得
- カーソルのX座標、Y座標を取得
- 画面外(ブラウザの外)に出たかを判定
- クリック判定
- aタグのホバー判定
上記4点の状態を取得します。
aタグのホバーに関してはAjaxなどで動的に追加された場合に対応するためMutationObserver
を使用しbody内を監視しています。
attachEvent() {
//カーソルの位置を取得
document.addEventListener('mousemove', (e) => {
this.position.mouseX = e.clientX;
this.position.mouseY = e.clientY;
this.wrap_el.classList.add('is-moved');
});
//画面外判定
document.body.addEventListener("mouseleave", () => {
this.wrap_el.classList.add('is-outside');
}, false);
document.body.addEventListener("mouseenter", () => {
this.wrap_el.classList.remove('is-outside');
}, false);
//クリック判定
document.addEventListener('mousedown', (e) => {
this.eventStatus.click = true;
})
document.addEventListener('mouseup', (e) => {
this.eventStatus.click = false;
})
// aタグのホバー判定
// 監視ターゲットの取得
const body = document.body;
// オブザーバーの作成
const observer = new MutationObserver(records => {
let link = document.querySelectorAll('a');
for (const target of link) {
target.addEventListener('mouseenter', (e) => {
this.eventStatus.hover = true;
this.wrap_el.classList.add('is-hover');
})
target.addEventListener('mouseleave', (e) => {
this.eventStatus.hover = false;
this.wrap_el.classList.remove('is-hover');
})
}
})
// 監視の開始
observer.observe(body, {
childList: true
})
}
マウスストーカーの状態を更新
TweenMaxを使用し0.001秒毎に状態を更新します。
repeat
を-1にすると無限にループします。ループ時にonRepeat
が実行されます。
減速処理
現在値 += (ターゲット値 - 現在値) * 減速率
this.position.currentX += (this.position.mouseX - this.position.currentX) * 0.5
と計算することでマウスストーカーがマウスカーソルに近づくにつれて減速します。
この計算式はパララックスや慣性スクロールなどにも使用されたりします。
減速率を小さくするほど遅くなります。
マウスストーカーをマウスカーソルの中心にする
x: this.position.currentX - 5,
y: this.position.currentY - 5
マウスストーカーのサイズは10px * 10pxなのでXY座標を-5することでマウスカーソルの中心にします。
tween() {
TweenMax.to({}, .001, {
repeat: -1,
onRepeat: () => {
//減速処理
this.position.currentX += (this.position.mouseX - this.position.currentX) * 0.5;
this.position.currentY += (this.position.mouseY - this.position.currentY) * 0.5;
TweenMax.set(this.main_el,
{
css: {
x: this.position.currentX - 5,
y: this.position.currentY - 5
}
});
TweenMax.to(this.option_el, 0.3,
{
css: {
x: this.position.currentX - 20,
y: this.position.currentY - 20,
scale: this.scale(this.eventStatus)
}
});
}
});
}
ホバーやクリックでのマウスストーカーのサイズ変更
scale: this.scale(this.eventStatus)
ホバーでサイズを1.6倍、クリックで0.6倍に変更する処理です。
scale(v) {
if (v.hover == true && v.click == false) {
return 1.6
} else if (v.hover == false && v.click == true) {
return 0.6
} else if (v.hover == true && v.click == true) {
return 0.6
} else {
return 1
}
}
以上でソースコードの解説は終わりです。
最後に
マウスストーカーをうまく使用することでサイトをお洒落に見せることができます。この記事が少しでも参考になればと思います。
またソースコードについてですが僕自身書き方が正しいのか?もっとキレイな書き方があるのではいないか?といつも思っています。みなさんはどうなんでしょう?という余談でした。
参考にさせて頂いた記事・サイト
https://www.evoworx.co.jp/blog/mouse-stoker-gsap/
https://www.sonicjam.co.jp/