如何在 Alpine.js 中精准追踪鼠标像素坐标并实现动态径向模糊效果

作者:袖梨 2026-06-15

本文详解如何利用 Alpine.js 实时获取鼠标在页面中的精确像素坐标(pageX/pageY),自动同步为带 'px' 单位的响应式数据,并结合 Tailwind CSS 实现基于鼠标位置的径向模糊悬停效果。

本文详解如何利用 alpine.js 实时获取鼠标在页面中的精确像素坐标(`pagex/pagey`),自动同步为带 `'px'` 单位的响应式数据,并结合 tailwind css 实现基于鼠标位置的径向模糊悬停效果。

在 Alpine.js 项目中实现“以鼠标为原点的径向模糊”(如 bg-[radial-gradient(circle_at_#{$mouseX}_#{$mouseY},...)])的关键,是让模板能直接消费形如 '127px' 的字符串值——这要求我们不仅捕获整数坐标,还需实时拼接单位,并确保跨浏览器兼容(尤其需兼容旧版 IE 对 pageX/pageY 的缺失支持)。

✅ 推荐实现方案:Alpine 数据函数 + 兼容性增强的 mousemove 监听

以下是一个生产就绪的 Alpine 数据定义(建议保存为 blur.js):

export default () => ({  mouseX: 0,  mouseY: 0,  mouseXAsPx: '0px',  mouseYAsPx: '0px',  init() {    // 自动同步数值 → 带单位字符串    this.$watch('mouseX', (val) => (this.mouseXAsPx = `${val}px`));    this.$watch('mouseY', (val) => (this.mouseYAsPx = `${val}px`));    // 高兼容性 mousemove 处理器(支持 IE9+)    const handleMouseMove = (e) => {      const event = e || window.event;      let { pageX, pageY } = event;      // 兜底计算:当 pageX/pageY 不可用时,手动推导(参考 jQuery 源码逻辑)      if (pageX == null) {        const doc = document.documentElement;        const body = document.body;        const clientX = event.clientX;        const clientY = event.clientY;        const scrollLeft = window.pageXOffset || doc.scrollLeft || body.scrollLeft;        const scrollTop = window.pageYOffset || doc.scrollTop || body.scrollTop;        const clientLeft = doc.clientLeft || body.clientLeft || 0;        const clientTop = doc.clientTop || body.clientTop || 0;        pageX = clientX + scrollLeft - clientLeft;        pageY = clientY + scrollTop - clientTop;      }      this.mouseX = Math.round(pageX);      this.mouseY = Math.round(pageY);      this.applyBlur();    };    // 绑定全局监听(注意:若仅需限定于某 div 内,应改用该元素的 addEventListener)    document.addEventListener('mousemove', handleMouseMove);    // 清理:避免内存泄漏(Alpine v3.13+ 支持自动 cleanup,但显式解绑更稳妥)    this.$nextTick(() => {      this.$el.addEventListener('mouseleave', () => {        // 可选:鼠标离开时重置或暂停更新      });    });  },  applyBlur() {    // 此处可触发自定义逻辑,例如:    // - 触发 $dispatch('mouse-move', { x: this.mouseX, y: this.mouseY })    // - 更新 CSS 自定义属性:document.documentElement.style.setProperty('--mouse-x', this.mouseXAsPx)    // - 或直接用于内联样式(见下方模板示例)  }});

? 在 HTML 中使用(配合 Tailwind 动态类)

<!-- 引入 Alpine & 数据 --><script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script><script type="module">  import Blur from './blur.js';  window.Alpine = await import('https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.esm.min.js');  window.Alpine.data('blur', Blur);  window.Alpine.start();</script><!-- 应用容器:使用 x-bind 动态生成 radial-gradient --><div   x-data="blur"  class="relative w-full h-96 bg-gray-100 overflow-hidden rounded-xl"  :style="`background-image: radial-gradient(circle at ${mouseXAsPx} ${mouseYAsPx}, rgba(255,255,255,0.8) 0%, transparent 70%)`">  <!-- 可选:显示坐标调试信息 -->  <div class="absolute top-4 left-4 bg-black/70 text-white px-3 py-1 text-sm rounded">    X: <span x-text="mouseX"></span>px, Y: <span x-text="mouseY"></span>px  </div></div>

⚠️ 注意事项与最佳实践

  • 作用域控制:上述代码监听 document 全局移动。若只需在特定 <div> 内生效,请将 document.addEventListener(...) 替换为 this.$el.addEventListener('mousemove', ...),并确保该元素设置了 position: relative(以支撑绝对定位子元素或 radial-gradient 坐标基准)。
  • 性能优化:高频 mousemove 可能触发重绘压力。如遇卡顿,可在 handleMouseMove 内添加 requestAnimationFrame 节流:
    let isQueued = false;const rafHandler = () => {  this.mouseX = ...; this.mouseY = ...; this.applyBlur();  isQueued = false;};const throttled = () => {  if (!isQueued) {    requestAnimationFrame(rafHandler);    isQueued = true;  }};// 然后在事件中调用 throttled()
  • Tailwind 动态类限制:radial-gradient 中的 at 位置不支持直接插值(如 bg-[radial-gradient(circle_at_{{mouseXAsPx}}_{{mouseYAsPx}},...)])。因此推荐使用 :style 绑定 CSS background-image,这是最可靠的方式。
  • 移动端适配:mousemove 在触摸设备上不触发。如需全平台支持,应补充 touchmove 事件处理(获取 touches[0].clientX/clientY 并转换为 page 坐标)。

通过以上实现,你即可获得稳定、兼容、响应式的鼠标坐标数据流,并无缝驱动视觉反馈——无论是径向模糊、悬停高亮,还是交互式粒子效果,都拥有了精准的空间锚点。

相关文章

精彩推荐