You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现圆形区域内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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:54:28