实现图片Hover时鼠标位置的径向彩色恢复CSS效果
实现鼠标悬停径向恢复图片色彩效果
实现思路
通过双层图片叠加 + CSS变量 + 鼠标移动事件监听,实现鼠标指向位置径向恢复色彩的效果:
- 底层放置彩色原图,上层放置同一张图片的灰度遮罩
- 用CSS变量记录鼠标在容器内的位置,通过
mask属性在遮罩层创建径向透明区域,让底层彩色透出 - 监听鼠标移动事件,实时更新CSS变量,使透明区域跟随鼠标移动
修改后的React组件代码
import { useRef, useEffect } from 'react'; import university from "../../assets/svgs/university.svg"; import scholarship from "../../assets/svgs/scholarship.svg"; import contactus from "../../assets/svgs/contactus.svg"; import NavigationCard from "./NavigationCard"; import classes from "./NavigationCard.module.css"; import classroom from "../../assets/images/class_hall.jpg"; const Navigation = (props) => { const bgImageRef = useRef(null); useEffect(() => { const handleMouseMove = (e) => { if (!bgImageRef.current) return; const rect = bgImageRef.current.getBoundingClientRect(); const xPercent = ((e.clientX - rect.left) / rect.width) * 100; const yPercent = ((e.clientY - rect.top) / rect.height) * 100; bgImageRef.current.style.setProperty('--mouse-x', `${xPercent}%`); bgImageRef.current.style.setProperty('--mouse-y', `${yPercent}%`); }; const container = bgImageRef.current; container?.addEventListener('mousemove', handleMouseMove); return () => container?.removeEventListener('mousemove', handleMouseMove); }, []); return ( <div className={classes['navigation-container']}> <div className={classes['navigation-inner-container']}> <div ref={bgImageRef} className={classes["background-image"]}> <img src={classroom} alt="classroom" className={classes['color-image']} /> <div className={classes['grayscale-overlay']}></div> </div> <div className={classes["cards-container"]}> <NavigationCard svg={university} navText="Universities" /> <NavigationCard svg={scholarship} navText="Scholarship" /> <NavigationCard svg={contactus} navText="Contact Us" /> </div> <div className={classes['black-cover']}></div> </div> </div> ); }; export default Navigation;
修改后的CSS代码
.navigation-inner-container { height: 30vh; border-radius: 10px; display: flex; justify-content: center; flex-direction: column; align-items: center; position: relative; } .background-image { width: 100%; height: 30vh; position: absolute; background: black; border-radius: 10px; overflow: hidden; --mouse-x: 50%; --mouse-y: 50%; } .color-image { width: 100%; height: 30vh; border-radius: 10px; object-fit: cover; } .grayscale-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; border-radius: 10px; background: url('../../assets/images/class_hall.jpg'); background-size: cover; background-position: center; filter: grayscale(100%); opacity: 0.3; mask: radial-gradient(circle at var(--mouse-x) var(--mouse-y), transparent 0, transparent 120px, black 120px); -webkit-mask: radial-gradient(circle at var(--mouse-x) var(--mouse-y), transparent 0, transparent 120px, black 120px); transition: mask 0.1s ease; } .background-image:not(:hover) .grayscale-overlay { mask: radial-gradient(circle at var(--mouse-x) var(--mouse-y), black 0, black 100%); -webkit-mask: radial-gradient(circle at var(--mouse-x) var(--mouse-y), black 0, black 100%); }
自定义调整说明
- 修改
radial-gradient中的120px可以调整彩色区域的大小 - 调整
transition的时长可以改变效果的平滑度 - 若需要调整灰度遮罩的透明度,修改
.grayscale-overlay中的opacity值即可
内容的提问来源于stack exchange,提问作者lou_codes
相关产品推荐
相关产品推荐

