悬停倾斜图标(指针驱动 3D 倾斜图标按钮源码)
悬停倾斜图标源码:指针位置驱动图标按钮 3D 旋转倾斜,rotateX/rotateY 跟随光标方向实时响应,移出平滑回正并放大,原生 JS 零依赖,适合导航与工具栏。
效果演示(真实可交互)
图标按钮是界面里最密集的微交互场景,给图标加一点「拟物」回应能明显提升精致度。演示区有爱心、星星、齿轮、发送四枚自绘 SVG 图标,把鼠标移到任意图标上,它会朝着光标所在的方向做 3D 倾斜:光标在左上方,图标就向左上方仰起,最大倾斜 16 度,同时图标放大到 1.06 倍并泛起蓝色投影;移出后平滑回正。倾斜角度由指针在元素内的相对坐标实时计算,没有任何预设动画,因此每次悬停的手感都不同,比固定角度的 CSS 动画更「活」。倾斜跟随指针的机制也适合做成整个卡片的倾斜效果,图标只是最常见的载体。四枚图标均为自绘 SVG,描边风格统一,stroke 继承按钮的 color,换主题色只需一行 CSS。相比固定角度的悬停动画,指针驱动的倾斜每次角度都不同,重复操作也不会腻。倾斜量随指针距离中心的变化连续变化:靠近边缘时角度最大、靠近中心时趋近零度,形成自然的「透视跟随」手感,这也是很多 3D 产品展示卡片的通用做法,可以直接迁移到图片、LOGO 等任意元素上。
鼠标移入图标,它会朝光标方向 3D 倾斜并放大
完整代码
HTML:每个图标是按钮,内部是内联 SVG + 文字标签:
<button class="ht-tile" type="button" aria-label="爱心图标">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.6l-1-1a5.5 5.5 0 0 0-7.8 7.8l1 1L12 21.2l7.8-7.8 1-1a5.5 5.5 0 0 0 0-7.8z"/>
</svg>
<span>爱心</span>
</button>
CSS:开启 3D 透视并预告 transform 优化:
.ht-tile {
width: 96px; height: 96px;
display: flex; flex-direction: column; align-items: center; justify-content: center;
border: 1px solid #e2e7f6; border-radius: 18px; background: #fff; cursor: pointer;
transform-style: preserve-3d;
transition: box-shadow .25s ease;
will-change: transform;
}
原生 JS:把指针坐标归一化到 0~1,再映射成旋转角:
document.querySelectorAll('.ht-tile').forEach((tile) => {
const MAX = 16; // 最大倾斜角度(度)
tile.addEventListener('pointermove', (e) => {
const rect = tile.getBoundingClientRect();
const px = (e.clientX - rect.left) / rect.width; // 0~1:左→右
const py = (e.clientY - rect.top) / rect.height; // 0~1:上→下
const rx = (0.5 - py) * MAX * 2; // 指针靠上 → 正角仰起
const ry = (px - 0.5) * MAX * 2; // 指针靠左 → 正角左倾
tile.style.transform =
`perspective(420px) rotateX(${rx.toFixed(2)}deg) rotateY(${ry.toFixed(2)}deg) scale(1.06)`;
});
tile.addEventListener('pointerleave', () => {
tile.style.transform = 'perspective(420px) rotateX(0) rotateY(0) scale(1)';
});
});
参数说明
| 参数 | 默认值 | 说明 |
|---|---|---|
最大倾斜角 MAX | 16 度 | 数值越大倾斜越明显,超过 25 度会出现透视变形 |
| 透视距离 | 420px | 越小立体感越强,过小会产生鱼眼畸变 |
| 放大倍率 | 1.06 | 悬停时轻微放大,与倾斜叠加更有层次 |
| 回正方式 | pointerleave 重置 transform | 直接清零,由浏览器按合成帧平滑过渡 |
| 图标配色 | stroke="currentColor" | 改 hover 态 color 即可统一换色 |
兼容性与性能
- 原生 JS +
pointermove,零依赖;transform走 GPU 合成,每帧仅改一个字符串属性,性能开销可忽略 transform-style: preserve-3d与perspective()在 Chrome / Firefox / Safari / Edge 最新版均无前缀支持- 指针坐标每次移动都会触发样式写入,建议保持图标数量在几十个以内;页面级大量图标可加 rAF 节流
- 触屏设备无 hover 概念,
pointerleave在触摸结束时也会触发,因此不会出现「卡在倾斜态」的问题 - 若页面同时存在大量可倾斜元素,建议统一在容器上做事件委托,用一个监听器分发坐标,避免每枚图标各绑一个事件;移出时直接重置 transform,浏览器会按帧插值,不需要额外补间代码
常见问题
Q: 倾斜后图标文字也跟着转,看起来歪了? 想要文字保持水平,可对内部 <span> 反向设置相同的旋转角度,或在倾斜容器里只放 SVG,把文字移到容器外。
Q: 倾斜角度太小没感觉? 调大 MAX 并减小透视距离到 300px 左右;同时把 scale 提到 1.1,立体感会明显增强。
Q: 页面里有滚动条,倾斜会卡顿吗? 不会,pointermove 期间滚动条已停;若在滚动过程中频繁进入元素,可在 pointerleave 时顺便重置一次 transform 避免累积误差。
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(缓动曲线)等属性即可,代码中有注释说明。