You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现图片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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 20:35:26