今天学着 B 站上的教程,手写了一个好看的目标光标
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style> * { margin: 0; padding: 0; font-size: 1vmin; cursor: none; }
body { display: flex; flex-direction: column; justify-content: center; align-items: center; width: 100%; height: 100vh; background-color: #171717; overflow: hidden; }
.pointer { --width: 4rem; --height: 4rem;
position: fixed; top: calc(var(--height) / -2); left: calc(var(--width) / -2);
width: var(--width); height: var(--height);
transition: all 0.1s ease-out; pointer-events: none; }
.pointer div { position: absolute; width: 1rem; height: 1rem; border-width: 0.3rem; border-color: pink; }
.pointer div:nth-child(1) { top: 0; left: 0; border-top: 0.3rem solid pink; border-left: 0.3rem solid pink; }
.pointer div:nth-child(2) { top: 0; right: 0; border-top: 0.3rem solid pink; border-right: 0.3rem solid pink; }
.pointer div:nth-child(3) { bottom: 0; left: 0; border-bottom: 0.3rem solid pink; border-left: 0.3rem solid pink; }
.pointer div:nth-child(4) { bottom: 0; right: 0; border-bottom: 0.3rem solid pink; border-right: 0.3rem solid pink; }
/* ====================== 中心 十字 + 圆点====================== */ .pointer-center { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100%; height: 100%; pointer-events: none; }
/* 十字线 */ .pointer-center::before, .pointer-center::after { content: ''; position: absolute; background: pink; } .pointer-center::before { width: 0.25rem; height: 1.6rem; top: 50%; left: 50%; transform: translate(-50%, -50%); } .pointer-center::after { width: 1.6rem; height: 0.25rem; top: 50%; left: 50%; transform: translate(-50%, -50%); }
/* 中心原点 */ .pointer-center-dot { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 0.5rem; height: 0.5rem; background: pink; border-radius: 50%; }
._target { margin-bottom: 5rem; }
p, section { font-family: Impact; font-size: 4rem; color: #f7f7f7; cursor: none; }
section { padding: 5rem; background-color: #f7f7f7; color: #171717; } </style> </head>
<body> <div class="pointer"> <div></div> <div></div> <div></div> <div></div> <!-- 中心十字 + 圆点 --> <!-- <div class="pointer-center"></div> --> <!-- <div class="pointer-center-dot"></div> --> </div>
<p class="_target">HOVER ME</p> <p class="_target">HOVER ME WITH MOUSE</p> <section class="_target">HOVER ME</section>
<script> const pointer = { container: document.querySelector(".pointer"), current_target: null,
angle: 0, mouseX: 0, mouseY: 0,
followSpeed: 0.3,
init() { window.addEventListener("mousemove", (e) => { this.mouseX = e.clientX; this.mouseY = e.clientY; }); this.bind_targets_events(); this.autoRotate(); },
autoRotate() { requestAnimationFrame(() => this.autoRotate());
if (!this.current_target) { this.angle -= 2; }
this.updateTransform(); },
updateTransform() { if (this.current_target) { const rect = this.current_target.getBoundingClientRect(); const x = rect.left + rect.width / 2; const y = rect.top + rect.height / 2; this.container.style.transform = `translate(${x}px, ${y}px) rotate(0deg)`; } else { let currentX = parseFloat(getComputedStyle(this.container).transform.split(',')[4]) || 0; let currentY = parseFloat(getComputedStyle(this.container).transform.split(',')[5]) || 0;
const speed = this.followSpeed; currentX += (this.mouseX - currentX) * speed; currentY += (this.mouseY - currentY) * speed;
this.container.style.transform = `translate(${currentX}px, ${currentY}px) rotate(${this.angle}deg)`; } },
bind_targets_events() { […document.querySelectorAll("._target")].forEach(ele => { ele.onmouseenter = () => { this.current_target = ele; const rect = ele.getBoundingClientRect(); this.container.style.setProperty("--width", rect.width + innerWidth / 50 + "px"); this.container.style.setProperty("--height", rect.height + innerWidth / 50 + "px"); };
ele.onmouseleave = () => { this.current_target = null; this.container.style.setProperty("--width", "4rem"); this.container.style.setProperty("--height", "4rem"); }; }); } };
pointer.init(); </script> </body></html>组件
后面又发现了更专业的组件target-cursor