マウスストーカーが盛んに取り上げられるようになって早数年。さすがにそろそろやり方くらいは……と思い、試してみることにしました。
まずは成果物を。
最初の方(要素ホバーで拡大)は参考コードほぼそのままです。次のものはマウスストーカーが大きくなるだけでなく、背景画像をスポットライト的に切り抜いて表示する機能も付けたものになります。
リポジトリ。
<div class="c-mouseStalker_wrapper">
<div class="c-mouseStalker">
<div class="c-mouseStalker_cursor" id="c-mouseStalker_cursor"></div>
<div class="c-mouseStalker_delay" id="c-mouseStalker_delay"></div>
</div>
</div>
HTMLはいたってシンプル。カーソル用の要素とディレイがかかって追いかけてくる要素の2つの div
を用意します。
今回はさらにラッパーで覆って overflow: hidden;
をかけることで、画面端にカーソルが移動した際にディレイ要素の大きさ分だけはみ出てスクロールバーが表示されないようにしました。
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js" defer></script>
それから、今回はサクッと試すために CDN で TweenMax を読み込むようにしました。
body {
position: relative;
// 元々のマウスカーソルを消す
cursor: none;
}
.c-mouseStalker {
// イベント反応させなくする
pointer-events: none;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
&_wrapper {
// イベント反応させなくする
pointer-events: none;
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
// 端にカーソルを持って行ったときにディレイの部分だけはみ出てスクロールバーが表示されてしまうのを抑止
overflow: hidden;
}
&_cursor,
&_delay {
position: absolute;
top: 0;
left: 0;
pointer-events: none; // イベント反応させなくする
}
&_cursor {
width: 0.5rem;
height: 0.5rem;
background-color: f.$color;
z-index: 10001;
border-radius: 50%;
}
&_delay {
$delayRadius: 100px / 4;
width: 100%;
height: 100%;
background-color: f.$main-color;
z-index: 10000;
transition: clip-path ease 0.1s; // 遅くするともっさりした感じになる
opacity: 0.4;
// at 以降は円の中心の定義
clip-path: ellipse($delayRadius $delayRadius at 50% 50%);
&.active {
$activeTimes: 4;
background: {
image: url("../img/img.jpg");
attachment: fixed;
size: cover;
position: center center;
}
opacity: 1;
clip-path: ellipse($delayRadius * $activeTimes $delayRadius * $activeTimes at 50% 50%);
}
}
}
body
の cursor: none;
: デフォルトのマウスカーソルを非表示に.c-mouseStalker
と .c-mouseStalker_wrapper
:
pointer-events: none;
.c-mouseStalker_wrapper
: overflow: hidden;
で端にカーソルを持って行ったときにディレイの部分だけはみ出てスクロールバーが表示されてしまうのを抑止.c-mouseStalker_delay
: 肝
clip-path
で切り取った円形の範囲のみ見える状態にする
background-image
で指定した画像にする
background-attachment
, background-size
, background-position
指定ありtransition: clip-path ease 0.1s;
でホバー時の拡大縮小等の切り替えを easing
0.3s
にすると TweenMax のディレイも相まってもっさりした動きになってしまうので、 0.1s
で// mouse stalker
const mouseStalker = () => {
const $cursor = $('#c-mouseStalker_cursor');
const $delay = $('#c-mouseStalker_delay');
const paramsArray = {
cursor: {
width: $cursor.outerWidth(),
coorX: 0,
coorY: 0,
delay: 0.001,
},
delay: {
width: $delay.outerWidth(),
coorX: 0,
coorY: 0,
delay: 6,
},
};
const activeClass = 'active';
let clipRadius = 100 / 4;
let clipScale = 1;
let clipPathCoor = `ellipse(${clipRadius * clipScale}px ${clipRadius * clipScale}px at 50% 50%)`;
// カーソルの遅延アニメーション
// ほんの少しだけ遅延させる (0.001秒)
TweenMax.to(
{},
paramsArray.cursor.delay,
{
repeat: -1,
onRepeat: function() {
paramsArray.delay.coorX += (paramsArray.cursor.coorX - paramsArray.delay.coorX) / paramsArray.delay.delay;
paramsArray.delay.coorY += (paramsArray.cursor.coorY - paramsArray.delay.coorY) / paramsArray.delay.delay;
clipPathCoor = `ellipse(${clipRadius * clipScale}px ${clipRadius * clipScale}px at ${paramsArray.delay.coorX}px ${paramsArray.delay.coorY}px)`;
// delay
TweenMax.set(
$delay,
{
css: {
clipPath: clipPathCoor,
}
}
);
// cursor
TweenMax.set(
$cursor,
{
css: {
left: paramsArray.cursor.coorX - (paramsArray.cursor.width / 2),
top: paramsArray.cursor.coorY - (paramsArray.cursor.width / 2),
}
}
);
}
}
);
// mouse hover
$('#hoverElmID').on({
mouseenter: function () {
$cursor.addClass(activeClass);
$delay.addClass(activeClass);
clipScale = 4;
},
mouseleave: function () {
$cursor.removeClass(activeClass);
$delay.removeClass(activeClass);
clipScale = 1;
},
});
// get mouse coordinate
$(document).on('mousemove', function (e) {
paramsArray.cursor.coorX = e.pageX;
paramsArray.cursor.coorY = e.pageY;
});
};
window.addEventListener('load', () => {
mouseStalker();
});
clipPathCoor
で指定した値が実際の clip-path
で切り取られるディレイ要素の指定
to
で指定するパラメータが top
, left
から clip-path
のみに変更clip-path
で切り取られる範囲を拡大縮小(拡大率の数値を変更している)今回はこれで望んだ挙動になりました。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント