跳到正文

磁吸按钮

Magnetic Button

初级网页

鼠标靠近按钮时,按钮像被磁铁吸住一样朝鼠标偏过去,里面的文字再多挪一点;鼠标离开,按钮带一点回弹地回到原位。常用在官网首屏的主按钮上,让人忍不住想去点。

你可能会说:「官网上那个「开始使用」按钮,能不能做成鼠标靠近时会被吸过去的效果?」

效果预览

正在加载演示…

怎么做

  1. 1

    按钮里多包一层文字

    按钮和里面的文字分开移动:按钮挪得多一点,文字再多挪一点,会有一种「有厚度」的感觉。

    查看代码html
    <button class="magnetic" type="button">
      <span>开始免费试用</span>
    </button>
  2. 2

    回弹的过渡

    平时用一条略带回弹的缓动曲线(cubic-bezier 第二个控制点大于 1),这样鼠标离开时按钮会轻轻弹一下再停稳;跟随鼠标时把过渡缩短,才跟得上手。

    查看代码css
    .magnetic {
      transition: transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
    }
    .magnetic span {
      display: inline-block;
      transition: inherit;
    }
    .magnetic.is-active,
    .magnetic.is-active span {
      transition-duration: 0.15s;
    }
  3. 3

    按鼠标距离计算位移

    鼠标进入「按钮边缘外扩一圈」的感应区时,算出鼠标离按钮中心的距离,乘上吸力系数作为位移。注意 getBoundingClientRect 量到的是按钮移动后的位置,要扣掉当前的位移,才是按钮原来的中心,否则按钮会越吸越抖。只响应鼠标,触屏和开启减少动效时不吸。

    查看代码js
    const RANGE = 80;      // 感应范围:按钮边缘外多少像素开始吸
    const STRENGTH = 0.35; // 吸力:鼠标偏离中心的距离 × 这个系数
    const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
    
    document.querySelectorAll('.magnetic').forEach((button) => {
      const label = button.querySelector('span');
      let x = 0;
      let y = 0;
      const move = (nextX, nextY) => {
        x = nextX;
        y = nextY;
        button.style.transform = `translate(${x}px, ${y}px)`;
        label.style.transform = `translate(${x * 0.4}px, ${y * 0.4}px)`;
      };
    
      window.addEventListener('pointermove', (event) => {
        if (reduced || event.pointerType !== 'mouse') return;
        const box = button.getBoundingClientRect();
        const dx = event.clientX - (box.left + box.width / 2 - x);
        const dy = event.clientY - (box.top + box.height / 2 - y);
        const inside = Math.abs(dx) < box.width / 2 + RANGE
          && Math.abs(dy) < box.height / 2 + RANGE;
        button.classList.toggle('is-active', inside);
        move(inside ? dx * STRENGTH : 0, inside ? dy * STRENGTH : 0);
      });
    });

适合放在哪

适合用

  • 官网首屏或落地页的主按钮(「免费试用」「立即下载」),一页只放一两个。
  • 作品集、设计工作室网站的导航链接或社交图标,增加一点趣味。
  • 活动页里希望用户一定要点的那一个按钮。

不适合用

  • 表单里的提交按钮、表格里的操作按钮,别做磁吸;用户要准确点击,按钮乱跑反而碍事。
  • 一页上有很多按钮时,别每个都磁吸;会显得浮躁,也分不清哪个最重要。
  • 主要用户在手机上时,别指望这个效果;触屏没有「靠近」,用户看不到。

让 AI 帮你做

请给【页面上最重要的那个按钮,如:首页首屏的「开始免费试用」按钮】加上磁吸效果。先阅读这个按钮所在的组件和项目里已有的动画写法,确认不需要新增依赖。要求:鼠标进入按钮边缘外约 80px 的范围时,按钮朝鼠标方向位移(距离 × 约 0.35),按钮内文字额外多移一点;计算中心点时扣掉按钮当前的位移,避免抖动;离开后用带轻微回弹的过渡回到原位;只响应鼠标,触屏和开启减少动效时不生效;组件卸载时移除事件监听。按钮原有的点击、聚焦样式保持不变。不改无关代码。最后说明怎样验证:鼠标绕着按钮移动时不抖动,键盘 Tab 聚焦正常。

用到的知识