悬停磁吸图标(指针靠近图标被吸附的磁力动效)

CSSJS 许可:自研原创

悬停磁吸图标组件:图标会朝指针方向偏移并被「吸附」,移开后弹性归位,rAF 指数插值实现平滑跟手,附带彩色光晕跟随,纯 JS 自研零依赖。

效果演示(真实可交互)

把鼠标移入任意一个图标附近,图标会朝指针方向偏移,像被磁铁吸住一样;同时图标外围浮起一圈同色光晕。指针在图标内移动时,图标会平滑跟手,而不是瞬间跳位;移出图标后,光晕淡去,图标弹性归位。五种图标各有独立的磁吸范围与光晕配色。

🎯
⚡
🔥
🎨
🚀

把指针移入图标附近,图标会被「磁吸」到指针方向,移开后弹性归位

完整代码

HTML(图标与光晕两层):

<div class="hmi-item">
  <span class="hmi-icon">🎯</span>
  <em class="hmi-ring"></em>
</div>

CSS(光晕默认隐藏,磁吸位移由内联 transform 驱动):

.hmi-ring {
  position: absolute; inset: -10px; border-radius: 26px;
  background: radial-gradient(circle, rgba(108,140,255,.4), transparent 70%);
  opacity: 0; transition: opacity .25s ease;
  pointer-events: none;
}
.hmi-icon { will-change: transform; }

JS(rAF 指数插值,指针跟手且平滑回弹,约 25 行):

const item = document.querySelector('.hmi-item');
const icon = item.querySelector('.hmi-icon');
const ring = item.querySelector('.hmi-ring');
let tx = 0, ty = 0, cx = 0, cy = 0, raf = null;

const loop = () => {
  tx += (cx - tx) * 0.16;          // 每帧向目标靠近 16%,指数趋近
  ty += (cy - ty) * 0.16;
  icon.style.transform = `translate(${tx}px, ${ty}px)`;
  ring.style.opacity = cx || cy ? 1 : 0;
  if (Math.abs(tx - cx) < .05 && Math.abs(ty - cy) < .05 && !cx && !cy) { raf = null; return; }
  raf = requestAnimationFrame(loop);
};

item.addEventListener('pointermove', (e) => {
  const r = item.getBoundingClientRect();
  const maxX = r.width * 0.32, maxY = r.height * 0.32;
  cx = Math.max(-maxX, Math.min(maxX, e.clientX - (r.left + r.width / 2)));
  cy = Math.max(-maxY, Math.min(maxY, e.clientY - (r.top + r.height / 2)));
  if (!raf) raf = requestAnimationFrame(loop);
});
item.addEventListener('pointerleave', () => { cx = 0; cy = 0; });

磁吸的核心是「指数插值」:指针移动时记录目标位移(限制在图标尺寸的 32% 以内防止跑飞),动画循环每帧向目标靠近 16%。这个系数决定了跟手度——系数越大越「黏」,越小越「飘」;指针离开时目标归零,图标自然弹回,无需单独的归位动画。

参数说明

参数位置说明
磁吸范围maxX / maxY 的 0.32 倍限制最大偏移,防止图标脱离容器
跟手系数插值常数 0.160.1-0.3,越大跟随越快越黏
光晕颜色.hmi-ring 的 radial-gradient按图标主题色各自配置
光晕过渡transition: opacity .25s控制光晕出现与消失的速度
触发事件pointermove / pointerleave统一桌面与触屏指针

兼容性与性能

常见问题

Q: 图标偏移后点击位置不准了? 磁吸位移只作用在图标元素上,外层的按钮容器没有移动,所以点击命中区域不变;若担心视觉与命中不一致,可给图标加 pointer-events: none,让事件始终落在容器上。

Q: 磁吸幅度不够或跑飞了? 幅度由 0.32 这个比例控制,调大它图标能吸得更远;「跑飞」通常是插值系数过大导致过冲,把 0.16 调小即可。

Q: 想让光晕跟随图标一起移动? 演示里光晕保持在图标附近同步位移,直接把光晕的 transform 也写成和图标相同的 translate 值即可,代码中已留出对应写法。

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(缓动曲线)等属性即可,代码中有注释说明。

✍️ 作者与审核