3D 倾斜容器组件(鼠标跟随倾斜卡片,倾角/视距/高光可调)

JSCSS 许可:自研原创

3D 倾斜容器组件:鼠标位置实时驱动卡片 rotateX/rotateY 倾斜,内层元素按 translateZ 深度错位形成景深,倾角、视距、高光扫过可调,自研 JS 平滑插值零依赖。

效果演示(真实可交互)

🖱 在卡片上移动鼠标:卡片 3D 倾斜,内层元素按深度错位

🧊
3D 倾斜容器
移动鼠标感受分层景深
自研 CSS 3D

完整代码

实现思路分三步:鼠标在容器内的相对位置归一化到 [-0.5, 0.5];把该值乘以最大倾角得到目标 rotateX/rotateY;用指数平滑(lerp)逐帧逼近目标,避免抖动。内层元素通过 translateZ 分布在不同深度,倾斜时天然产生错位景深。

<div class="scene" id="scene">
  <div class="card" id="card">
    <div class="layer layer--bg"></div>
    <div class="layer layer--icon" style="--dz:48px">🧊</div>
    <div class="layer layer--title" style="--dz:34px">3D 倾斜容器</div>
  </div>
</div>
.scene { perspective: 900px; }        /* 视距决定 3D 强度 */
.card {
  width: 280px; height: 330px;
  transform-style: preserve-3d;       /* 层与层保持空间关系 */
  will-change: transform;
}
.layer {
  position: absolute; inset: 0;
  border-radius: 20px;
  transform: translateZ(var(--dz, 0px));  /* 每层不同深度 */
}
.layer--bg {
  background: linear-gradient(160deg, #2b3a67, #141b33);
  border: 1px solid rgba(255, 255, 255, .14);
}
const scene = document.getElementById('scene');
const card = document.getElementById('card');
const state = { tx: 0, ty: 0, rx: 0, ry: 0, running: false };
const MAX = 16;   // 最大倾角(度)

scene.addEventListener('pointermove', e => {
  const r = scene.getBoundingClientRect();
  state.tx = (e.clientX - r.left) / r.width - 0.5;   // -0.5 ~ 0.5
  state.ty = (e.clientY - r.top) / r.height - 0.5;
  if (!state.running) { state.running = true; requestAnimationFrame(loop); }
});
function loop() {
  const tx = -state.ty * 2 * MAX;
  const ty = state.tx * 2 * MAX;
  state.rx += (tx - state.rx) * 0.12;   // 指数平滑,0.12 为跟随速度
  state.ry += (ty - state.ry) * 0.12;
  card.style.transform = `rotateX(${state.rx.toFixed(2)}deg) rotateY(${state.ry.toFixed(2)}deg)`;
  if (Math.abs(tx - state.rx) > 0.05 || Math.abs(ty - state.ry) > 0.05) {
    requestAnimationFrame(loop);
  } else { state.running = false; }
}

参数说明

参数位置说明
最大倾角MAX 常量演示中 4-32° 可调,越大倾斜越明显
视距perspective500-1400px,影响景深强度
跟随速度平滑系数 0.12越大跟手越快,越小越丝滑
层深度--dz每层 translateZ 值,控制景深错位幅度
高光扫过--gx/--gy径向渐变跟随鼠标位置,营造光泽感

兼容性与性能

常见问题

Q: 倾斜很生硬、像开关不像跟随? 平滑系数过小或过大都会造成此感。建议 0.08-0.2 之间;同时确认 will-change: transform 已设置,避免每帧触发重排。

Q: 内层元素没有景深、全部贴在一起? 检查三点:容器必须 transform-style: preserve-3d;每层要有不同的 translateZ;容器本身被倾斜(rotateX/rotateY)——三者缺一,层间深度都不可见。

Q: 移动端触摸时卡片乱转? 指针事件在触摸时会同时派发 mouse 事件导致抖动。可改用 pointermove 并配合 touch-action: none(演示已采用该写法),或仅在 pointerType === 'mouse' 时响应。

Q: 可以商用吗? 可以。本组件为粤喵自研原创代码,免费商用无需署名,颜色、层数、倾角均可自由定制。

许可与来源

  • 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
  • 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
  • 首次发布:2026-09-01 · 最近更新:2026-09-01
  • 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
  • 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理

常见问题

这个组件可以商用吗?

可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。

浏览器兼容性如何?

支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。

怎么修改动画参数?

直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。

✍️ 作者与审核