<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>个性化鼠标指针</title>
<style>
body {
margin: 0;
height: 100vh;
overflow: hidden;
background: linear-gradient(#111, #000);
display: flex;
cursor: none;
}
#cursorPt {
position: fixed;
width: 7px;
height: 7px;
pointer-events: none;
z-index: 9999;
background: #79f2e7;
border-radius: 50%;
visibility: hidden;
}
#cursor {
--color: #4ed5b4;
position: fixed;
width: 30px;
height: 30px;
pointer-events: none;
z-index: 9999;
visibility: hidden;
background-image: linear-gradient(
to right,
var(--color) 10px,
transparent 0
),
linear-gradient(to bottom, var(--color) 10px, transparent 0),
linear-gradient(to left, var(--color) 10px, transparent 0),
linear-gradient(to bottom, var(--color) 10px, transparent 0),
linear-gradient(to right, var(--color) 10px, transparent 0),
linear-gradient(to top, var(--color) 10px, transparent 0),
linear-gradient(to left, var(--color) 10px, transparent 0),
linear-gradient(to top, var(--color) 10px, transparent 0);
background-repeat: no-repeat;
background-position: top left, top left, top right, top right,
bottom left, bottom left, bottom right, bottom right;
background-size: 20px 2px, 2px 20px, 20px 2px, 2px 20px, 20px 2px,
2px 20px, 20px 2px, 2px 20px;
}
#target {
position: relative;
width: 150px;
height: 80px;
margin: auto;
border: 2px solid #888;
transition: 300ms;
display: flex;
justify-content: center;
align-items: center;
color: #888;
text-transform: uppercase;
font-family: sans-serif;
user-select: none;
}
#target:hover {
border-color: #ccc;
color: #ddd;
}
</style>
</head>
<body>
<fasdfasdfasdfafsdf id="cursor"></fasdfasdfasdfafsdf>
<div id="cursorPt"></div>
<div id="target">将鼠标悬停在此</div>
<script src="https://unpkg.com/gsap@3/dist/gsap.min.js"></script>
<script>
const cursor = document.getElementById("cursor");
const cursorPt = document.getElementById("cursorPt");
const target = document.getElementById("target");
const CURSOR_WIDTH = cursor.getBoundingClientRect().width;
const CURSOR_PT_WIDTH = cursorPt.getBoundingClientRect().width;
let isOverTarget = false;
let rotationTween;
let exitTween = null;
let enterTween = null;
function startRotation() {
gsap.set(cursor, { rotation: 0 });
rotationTween = gsap.to(cursor, {
rotation: 180,
duration: 1.2,
repeat: -1,
ease: "linear",
transformOrigin: "center center",
});
}
function stopRotation() {
if (rotationTween) rotationTween.kill();
}
document.addEventListener("mousemove", (e) => {
gsap.to(cursor, { autoAlpha: 1 });
gsap.to(cursorPt, { autoAlpha: 1 });
if (!isOverTarget) {
gsap.to(cursor, {
x: e.clientX - CURSOR_WIDTH / 2,
y: e.clientY - CURSOR_WIDTH / 2,
duration: 0.1,
ease: "expo.out",
});
}
gsap.to(cursorPt, {
x: e.clientX - CURSOR_PT_WIDTH / 2,
y: e.clientY - CURSOR_PT_WIDTH / 2,
duration: 0.1,
ease: "expo.out",
});
});
target.addEventListener("mouseenter", () => {
isOverTarget = true;
stopRotation();
const rect = target.getBoundingClientRect();
if (exitTween) exitTween.kill();
enterTween = gsap.to(cursor, {
width: rect.width,
height: rect.height,
borderColor: "red",
rotation: 360,
duration: 0.2,
ease: "easeOut",
});
});
target.addEventListener("mousemove", (e) => {
const rect = target.getBoundingClientRect();
const targetWidth = rect.width;
const targetHeight = rect.height;
const cx = rect.left + targetWidth / 2;
const cy = rect.top + targetHeight / 2;
const dx = e.clientX - cx;
const dy = e.clientY - cy;
gsap.to(cursor, {
x: rect.left + dx * 0.09,
y: rect.top + dy * 0.09,
scale: 1.1,
duration: 0.1,
ease: "power2.out",
});
});
target.addEventListener("mouseleave", () => {
isOverTarget = false;
exitTween = gsap.to(cursor, {
width: 30,
height: 30,
duration: 0.5,
ease: "elastic.out(1, .9)",
});
startRotation();
});
startRotation();
</script>
</body>
</html>