能否用Tailwind CSS实现跟随鼠标的局部悬停透明度效果?
实现鼠标圆形跟随显示图片(React + Tailwind CSS)
核心思路
这个效果需要结合React的鼠标位置跟踪和CSS mask属性来实现:通过监听鼠标移动实时更新坐标,用径向渐变的mask只显示鼠标周围的圆形区域,其余部分保持隐藏。
实现代码
import { useState, useCallback } from 'react'; export default function WelcomePage() { // 存储鼠标相对于容器的坐标,初始设为图片中心(避免一开始完全看不到) const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); // 监听鼠标移动,更新坐标 const handleMouseMove = useCallback((e) => { const { left, top } = e.currentTarget.getBoundingClientRect(); // 计算相对于容器的坐标,避免页面滚动导致位置偏移 setMousePos({ x: e.clientX - left, y: e.clientY - top }); }, []); return ( {/* 容器占满视口,绑定鼠标移动事件 */} <div className="w-screen h-screen relative overflow-hidden" onMouseMove={handleMouseMove} > {/* 默认隐藏的图片,通过mask实现局部显示 */} <img src="/your-welcome-image.jpg" // 替换为你的图片路径 alt="Welcome" className="w-full h-full object-cover absolute inset-0" style={{ // 用径向渐变创建圆形mask:仅白色圆形区域显示图片 mask: `radial-gradient(circle 200px at ${mousePos.x}px ${mousePos.y}px, white 100%, transparent 100%)`, // 兼容webkit内核浏览器 WebkitMask: `radial-gradient(circle 200px at ${mousePos.x}px ${mousePos.y}px, white 100%, transparent 100%)` }} /> </div> ); }
关键细节说明
- 坐标计算:通过
getBoundingClientRect()获取容器的页面位置,减去鼠标的clientX/clientY,得到相对于容器的坐标,避免页面滚动导致圆形位置偏移。 - mask属性:
radial-gradient生成一个圆形白色区域,只有这个区域会透出图片内容,其余区域被mask隐藏。你可以修改200px来调整圆形的大小。 - 性能优化:用
useCallback包裹事件处理函数,避免组件每次渲染都创建新的函数实例。
扩展调整
- 鼠标移出隐藏:如果需要鼠标移出容器后图片重新隐藏,可以监听
mouseleave事件,将坐标设为容器外的值(比如x: -9999, y: -9999)。 - 平滑跟随效果:要让圆形移动更顺滑,可以用
requestAnimationFrame实现缓动效果:
import { useState, useCallback, useEffect } from 'react'; export default function WelcomePage() { const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); const [targetPos, setTargetPos] = useState({ x: 0, y: 0 }); const handleMouseMove = useCallback((e) => { const { left, top } = e.currentTarget.getBoundingClientRect(); setTargetPos({ x: e.clientX - left, y: e.clientY - top }); }, []); useEffect(() => { const animationFrame = requestAnimationFrame(function animate() { setMousePos(prev => ({ x: prev.x + (targetPos.x - prev.x) * 0.1, y: prev.y + (targetPos.y - prev.y) * 0.1 })); requestAnimationFrame(animate); }); return () => cancelAnimationFrame(animationFrame); }, [targetPos]); // 其余代码和基础版本一致 }
内容的提问来源于stack exchange,提问作者Jaycossey
相关产品推荐
相关产品推荐

