如何实现圆形区域内div跟随鼠标并模拟球面3D旋转效果
圆形区域内div跟随鼠标模拟球面3D旋转实现方案
实现核心逻辑
要模拟.face元素贴在球面跟随鼠标旋转的效果,无需单独计算skew斜切值——通过rotate3d实现3D旋转,搭配位移限制、缩放控制,靠透视关系自然呈现斜切、近大远小的视觉效果,比手动计算斜切参数更自然流畅。核心步骤:
- 先移除
.face上预设的CSS动画,避免动画规则覆盖JS动态写入的transform属性 - 初始化时获取球形容器(.head)的中心坐标、半径值,作为所有偏移计算的基准
- 鼠标移动时,实时计算鼠标位置相对于球心的X/Y轴偏移量
- 对偏移量做归一化边界限制,保证face元素始终不会超出圆形区域,移动过程无卡顿跳变
- 按照偏移占半径的比例,同步计算对应位移距离、3D旋转角度、缩放值,统一写入transform属性即可
完整修改代码
现有HTML结构无需调整,仅需修改CSS和补全JS逻辑即可。
CSS调整部分
修改原有CSS规则,移除默认动画,补充3D变换基准:
*, *::before, *::after { box-sizing: border-box; } .head { /* 新增透视属性增强3D质感,可按需调整数值 */ perspective: 1000px; /* 原有样式保留 */ width: 500px; height: 500px; border-radius: 50%; background-image: linear-gradient(120deg, yellow, #c47400); box-shadow: inset -5px -5px 20px yellow; position: relative; } .head::before { content: ""; position: absolute; left: 75px; top: 75px; border-radius: 50%; width: 150px; height: 150px; background-color: white; opacity: 0.35; filter: blur(45px) } .eye { width: 65px; height: 100px; margin: 10px; border-radius: 100px; display: inline-block; background-color: #8a6b0c; } .mouth { width: 175px; height: 50px; background-color: #8a6b0c; border-radius: 100px; } .container { width: 500px; height: 500px; display: flex; align-items: center; justify-content: center; } .face { display: inline-block; /* 移除原有animation规则,避免和JS控制冲突 */ transform-origin: center center; will-change: transform; /* 优化变换渲染性能 */ }
JavaScript交互补全
直接替换预留的mousemove监听逻辑即可:
const head = document.querySelector('.head'); const face = document.querySelector('.face'); // 配置参数和原有CSS动画的视觉效果对齐 const CONFIG = { maxOffset: 150, // 元素距离中心的最大位移 maxRotate: 40, // 边缘位置最大旋转角度 minScale: 0.9, // 边缘位置最小缩放值 baseRotateZ: 0 // 基础Z轴旋转角度,可按需调整 } // 预先获取球体基准坐标,页面尺寸变化时重新计算 let headRect = head.getBoundingClientRect(); let centerX = headRect.left + headRect.width / 2; let centerY = headRect.top + headRect.height / 2; let radius = headRect.width / 2; window.addEventListener('resize', () => { headRect = head.getBoundingClientRect(); centerX = headRect.left + headRect.width / 2; centerY = headRect.top + headRect.height / 2; radius = headRect.width / 2; }) addEventListener('mousemove', e => { // 计算鼠标相对于球心的偏移 let deltaX = e.clientX - centerX; let deltaY = e.clientY - centerY; // 计算鼠标到球心的直线距离 const distance = Math.sqrt(deltaX ** 2 + deltaY ** 2); // 鼠标移出圆形范围时按比例压缩偏移量,保证元素始终在圆内 if (distance > radius) { const ratio = radius / distance; deltaX *= ratio; deltaY *= ratio; } // 将偏移量映射为实际变换参数 const offsetRatio = distance / radius; const moveX = (deltaX / radius) * CONFIG.maxOffset; const moveY = (deltaY / radius) * CONFIG.maxOffset; const rotateX = -(deltaY / radius) * CONFIG.maxRotate; const rotateY = (deltaX / radius) * CONFIG.maxRotate; const scale = 1 - offsetRatio * (1 - CONFIG.minScale); // 统一应用变换 face.style.transform = ` translateX(${moveX}px) translateY(${moveY}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${CONFIG.baseRotateZ}deg) scale(${scale}) `; });
效果说明
最终表现和提供的CSS动画完全一致:元素移动到圆形边缘时会自然产生斜切透视、缩小的视觉效果,还原绕球体旋转的3D观感。所有可调参数都集中在CONFIG对象中,可根据实际需要修改数值调整效果。
内容的提问来源于stack exchange,提问作者ScooterMcGee
相关产品推荐
相关产品推荐

