要素に入るとポインターに追従して白い丸が動く実装をしてみる(備忘録)
今回は、要素に入るとポインターに追従して白い丸が動く実装をしていきます。ポインター自体を別のものに切り替えるシリーズは一旦終わりです。
Webデザインギャラリーでよくみかけると思いましたので、こちらのいくつか取り上げていく予定です。
HTMLの記述について
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>要素に入るとポインターに追従して白い丸が動く実装をしてみる(備忘録)</title>
<link rel="stylesheet" href="../reset.css">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<main>
<div class="pointer-area"></div>
</main>
<script src="./style.js"></script>
</body>
</html>
これは前回と同じのため、解説は省略します。
CSSの記述について
@charset "utf-8";
/* ==========================
初期設定
========================== */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
position: relative;
word-wrap: break-word;
}
img {
width: 100%;
vertical-align: bottom;
}
/* レイアウト設定 */
main {
margin: 80px 0;
}
.pointer-area {
background-color: #c3512f;
height: 400px;
cursor: auto;
}
.custom-cursor {
width: 32px;
height: 32px;
border-radius: 50%;
background-color: #fff;
position: fixed;
pointer-events: none;
display: none;
z-index: 1000;
transition: opacity 0.5s ease-out;
}
custom-cursorでポインターに追従する白い丸の設定をしています。色や形などは任意のものに変えることができます。。
JavaScriptの記述について
"use strict";
document.addEventListener("DOMContentLoaded", () => {
// .pointer-area 要素を取得
const pointerArea = document.querySelector(".pointer-area");
// カスタムカーソル要素を作成
const cursor = document.createElement("div");
cursor.classList.add("custom-cursor");
// カスタムカーソル要素をボディに追加
document.body.appendChild(cursor);
// マウスとカーソルの位置を保持する変数を初期化
let mouseX = 0,
mouseY = 0;
let cursorX = 0,
cursorY = 0;
let fadeTimeout; // フェードアウトのタイマーを保持する変数
// マウスが pointerArea に入った時の処理
pointerArea.addEventListener("mouseenter", () => {
// フェードアウトタイマーが存在する場合はクリア
if (fadeTimeout) {
clearTimeout(fadeTimeout);
}
cursor.style.display = "block"; // カスタムカーソルを表示
cursor.style.opacity = 1; // カスタムカーソルの透明度を1に設定
});
// マウスが pointerArea 内で動いた時の処理
pointerArea.addEventListener("mousemove", (e) => {
// マウスの位置を取得
mouseX = e.clientX;
mouseY = e.clientY;
// カーソルの初期位置が未設定の場合は設定
if (!cursorX && !cursorY) {
cursorX = mouseX;
cursorY = mouseY;
}
});
// マウスが pointerArea から出た時の処理
pointerArea.addEventListener("mouseleave", () => {
cursor.style.opacity = 0; // カスタムカーソルの透明度を0に設定(フェードアウト開始)
fadeTimeout = setTimeout(() => {
cursor.style.display = "none"; // フェードアウト後にカスタムカーソルを非表示に
}, 500); // フェードアウトの時間に合わせてタイマーを設定
});
// カスタムカーソルをマウスに追従させるアニメーション関数
function animate() {
// カーソルの位置を徐々にマウスの位置に近づける
cursorX += (mouseX - cursorX) * 0.1;
cursorY += (mouseY - cursorY) * 0.1;
// カスタムカーソルの位置を更新(白い丸の中心をポインタの中心に合わせるために補正)
cursor.style.left = cursorX - 16 + "px";
cursor.style.top = cursorY - 16 + "px";
// アニメーションフレームをリクエスト
requestAnimationFrame(animate);
}
// アニメーションを開始
animate();
});
詳細はコメントアウトで記載しているとおりです。
animate関数のところで、白い丸がポインター(マウス)に追従するように設定しています。0.1の値を大きくするとより速くポインターに追従するようになります。その逆はゆっくりになります。
requestAnimationFrameは、アニメーションをスムーズに実行するために使われます。60FPS(1秒間に60フレーム)のアニメーションを実現するために、約16ミリ秒ごとにanimate関数が呼び出されます。
以上で実装完了です。
次回も引き続き別のパターンを作っていく予定です。