自定义圆形光标链接悬停放大效果不持久问题求助
Fixing the Flickering Circle Cursor Hover Effect
我明白你遇到的问题了——当鼠标悬停在链接上时,光标放大的效果几乎一闪而过,根本看不清。这其实是因为你的mousemove事件触发频率太高,每次都会直接修改光标元素的行内left和top样式,这会打断.grow类的过渡动画,导致缩放效果被频繁重置。
下面是修复后的完整代码,我会一步步解释修改点:
修改核心思路
- 使用CSS变量来控制光标位置,避免行内样式和类样式的冲突
- 拆分过渡效果,让位置移动和缩放动画互不干扰
- 调整过渡时长,让缩放效果更明显
修复后的HTML(结构不变,仅确保光标层级)
<main> <div class="cr"></div> <div class="dot"></div> <div class="wrapper"> <h1>simple circle cursor with <a href="#">hover</a> effect</h1> </div> </main>
修复后的CSS
@import url('https://fonts.googleapis.com/css2?family=Red+Rose:wght@300;700&display=swap'); *,*::before,*::after { box-sizing: border-box; } body { position: relative; padding: 0px; margin: 0px; outline: 0; width: 100%; height: 600px; background-color: rgba(244,230,150,1); cursor: none; color: #e56b6f; /* 新增CSS变量存储光标坐标 */ --cursor-x: 0; --cursor-y: 0; } .cr { position: absolute; /* 用CSS变量计算位置,替代行内样式 */ left: calc(var(--cursor-x) - 30px); top: calc(var(--cursor-y) - 30px); width: 60px; height: 60px; background: transparent; border: 1px solid #000; border-radius: 100%; /* 拆分过渡:位置移动保持流畅,缩放效果延长时长 */ transition: transform 200ms ease, left 80ms ease, top 80ms ease; /* 确保光标在最上层,不被其他元素遮挡 */ z-index: 9999; } .dot { position: absolute; left: calc(var(--cursor-x) + 7px); top: calc(var(--cursor-y) + 7px); width: 5px; height: 5px; background: black; border-radius: 100%; transition: left 80ms ease, top 80ms ease; z-index: 9999; } main { display: flex; justify-content: flex-end; padding: 50px } .wrapper { max-width: 600px; } h1 { font-family: 'Red Rose', cursive; font-size: 60px; line-height: 60px; text-align: right; } a { color: #e56b6f; text-decoration: none; } .grow { transform: scale(1.5); }
修复后的JavaScript
const circle = document.querySelector(".cr"); const dot = document.querySelector(".dot"); const body = document.querySelector("body"); const links = Array.from(document.querySelectorAll("a")); body.addEventListener("mousemove", function(e) { const x = e.clientX; const y = e.clientY; // 更新CSS变量,而非直接修改元素行内样式 body.style.setProperty('--cursor-x', x + 'px'); body.style.setProperty('--cursor-y', y + 'px'); }); links.forEach(item => { item.addEventListener("mouseenter", () => { circle.classList.add("grow"); }); item.addEventListener("mouseleave", () => { circle.classList.remove("grow"); }); });
关键修改点解释
CSS变量替代行内样式:
原来的代码每次mousemove都直接给光标元素设置行内位置样式,会频繁触发重绘并打断缩放过渡。改用CSS变量后,位置更新通过全局变量传递,不会和.grow类的transform属性冲突,过渡动画能完整执行。拆分过渡效果:
把统一的all过渡拆分成位置和缩放的独立动画,位置移动用80ms保证光标跟随流畅,缩放用200ms让放大效果清晰可见。添加z-index:
确保光标元素在页面最上层,避免被其他内容遮挡,保证视觉效果正常。
现在你可以测试一下,悬停链接时光标会平滑放大,离开后又会自然缩回,效果非常明显!
内容的提问来源于stack exchange,提问作者Paulette
相关产品推荐
相关产品推荐

