求助:JavaScript实现鼠标跟随眼球功能的代码问题排查
问题分析与解决方案
核心问题
你的代码存在三个关键问题,导致瞳孔方向错误且触发范围受限:
- 事件监听范围过小:仅监听
.container的鼠标移动,若容器未占满视口,只有鼠标落在容器内才会触发效果。 - 角度计算基准错误:以眼球左上角而非中心作为坐标原点,且
Math.atan2参数顺序颠倒(正确应为(y差值, x差值))。 - 父元素旋转干扰:
.eye的rotate(45deg)扭曲了子元素的坐标系,导致旋转方向完全偏离预期。
修正后的完整代码
HTML
<div class="container"> <div class="eye"> <div class="eye-inner"> <div class="pupil"></div> </div> </div> </div>
CSS
* { margin: 0; padding: 0; box-sizing: border-box; background: black; } .container { width: 100vw; height: 100vh; } .eye { width: 48px; height: 48px; position: absolute; bottom: 41px; right: 50%; background: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; } .eye-inner { width: 40px; height: 40px; background-color: black; border-radius: 50%; position: relative; overflow: hidden; } .pupil { position: absolute; width: 20px; height: 20px; background: white; border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); }
JavaScript
document.addEventListener('mousemove', (e) => { const pupils = document.querySelectorAll('.pupil'); pupils.forEach(pupil => { const eye = pupil.parentElement; const eyeRect = eye.getBoundingClientRect(); // 计算眼球中心坐标 const eyeCenterX = eyeRect.left + eyeRect.width / 2; const eyeCenterY = eyeRect.top + eyeRect.height / 2; // 鼠标与眼球中心的相对差值 const dx = e.clientX - eyeCenterX; const dy = e.clientY - eyeCenterY; // 计算角度 const angle = Math.atan2(dy, dx); // 瞳孔最大移动距离(避免超出黑眼球) const maxMove = (eyeRect.width / 2) - (pupil.offsetWidth / 2); // 计算偏移量 const moveX = Math.cos(angle) * maxMove; const moveY = Math.sin(angle) * maxMove; // 应用偏移 pupil.style.transform = `translate(${moveX}px, ${moveY}px)`; }); });
关键修正说明
- 扩大触发范围:改用
document监听鼠标移动,确保页面任意位置都能触发效果。 - 精准坐标计算:以眼球中心为基准计算相对位置,解决角度偏移问题。
- 平移替代旋转:避免父元素旋转的坐标系干扰,直接通过
translate控制瞳孔移动,更符合真实眼球运动逻辑。 - 边界限制:计算最大移动距离,确保瞳孔始终在黑眼球范围内。
内容的提问来源于stack exchange,提问作者itsmarcotime
相关产品推荐
相关产品推荐

