本文详解如何利用 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 数据定义(建议保存为 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) // - 或直接用于内联样式(见下方模板示例) }});
<!-- 引入 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>
let isQueued = false;const rafHandler = () => { this.mouseX = ...; this.mouseY = ...; this.applyBlur(); isQueued = false;};const throttled = () => { if (!isQueued) { requestAnimationFrame(rafHandler); isQueued = true; }};// 然后在事件中调用 throttled()
通过以上实现,你即可获得稳定、兼容、响应式的鼠标坐标数据流,并无缝驱动视觉反馈——无论是径向模糊、悬停高亮,还是交互式粒子效果,都拥有了精准的空间锚点。