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

侧边栏5秒未操作淡出,鼠标距20px时淡入功能实现问题

解决方案:实现侧边栏鼠标靠近20px触发淡入+超时淡出

问题梳理

  • 预期效果:
    • 超过5秒未操作(鼠标不在侧边栏20px范围内),侧边栏淡出至20%透明度
    • 鼠标进入侧边栏20px范围内时,侧边栏立即淡入至100%透明度
  • 当前问题:
    • 仅能通过hover侧边栏触发淡入,无法实现“鼠标靠近20px”触发
    • 鼠标离开侧边栏后保持100%透明度,未重新启动淡出计时器

修改后的代码实现

import { useState, useEffect, useRef } from 'react';
import classNames from 'classnames';

// 计算鼠标与元素的最短距离
const getDistanceToElement = (mouseX, mouseY, element) => {
  const rect = element.getBoundingClientRect();
  // 计算鼠标在元素各方向的距离(超出元素范围为正,内部为0)
  const dx = Math.max(rect.left - mouseX, mouseX - rect.right, 0);
  const dy = Math.max(rect.top - mouseY, mouseY - rect.bottom, 0);
  // 勾股定理计算最短距离(鼠标在元素内时距离为0)
  return Math.sqrt(dx * dx + dy * dy);
};

const Sidebar = () => {
  const [isSidebarFaded, setSidebarFaded] = useState(false);
  const [isMouseNearby, setIsMouseNearby] = useState(false);
  const sidebarRef = useRef(null);
  let fadeTimer = useRef(null);

  // 全局监听鼠标移动,判断是否在侧边栏20px范围内
  useEffect(() => {
    const handleMouseMove = (e) => {
      if (!sidebarRef.current) return;
      const distance = getDistanceToElement(e.clientX, e.clientY, sidebarRef.current);
      const isNearby = distance <= 20;
      
      if (isNearby !== isMouseNearby) {
        setIsMouseNearby(isNearby);
      }
    };

    document.addEventListener('mousemove', handleMouseMove);
    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      clearTimeout(fadeTimer.current);
    };
  }, [isMouseNearby]);

  // 管理淡出计时器:鼠标不在附近时启动,进入附近时清除
  useEffect(() => {
    if (!isMouseNearby) {
      // 5秒后触发淡出
      fadeTimer.current = setTimeout(() => {
        setSidebarFaded(true);
      }, 5000);
    } else {
      // 鼠标靠近,立即淡入并清除计时器
      clearTimeout(fadeTimer.current);
      setSidebarFaded(false);
    }

    return () => clearTimeout(fadeTimer.current);
  }, [isMouseNearby]);

  return (
    <div
      ref={sidebarRef}
      className={classNames(styles.component, {
        [styles.fadeOut]: isSidebarFaded,
      })}
    >
      {/* 侧边栏内容 */}
    </div>
  );
};

export default Sidebar;

关键修改说明

  1. 距离计算逻辑:通过getBoundingClientRect()获取侧边栏的位置信息,精准计算鼠标到元素的最短距离,判断是否在20px触发范围内。
  2. 全局鼠标监听:在document上监听mousemove事件,替代原有的侧边栏局部hover监听,实现“靠近即触发”的效果。
  3. 计时器优化:
    • 鼠标离开触发范围时,启动5秒计时器,到期后淡出侧边栏
    • 鼠标进入范围时,立即清除计时器并将侧边栏淡入
    • 用useRef存储计时器ID,避免组件重渲染丢失引用
  4. 状态简化:用isMouseNearby替代原isHovered状态,更准确反映“鼠标在附近”的触发条件

样式补充

确保添加过渡动画实现平滑的淡入淡出效果:

.component {
  transition: opacity 0.3s ease;
  opacity: 1;
}

.fadeOut {
  opacity: 0.2;
}

内容的提问来源于stack exchange,提问作者hightides1973

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:10:58