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

如何在Material-UI中将Tooltip定位至光标位置(自定义坐标)

在Material-UI 5中实现Tooltip自定义光标定位(支持内部交互)

针对React 18.2.0 + MUI 5.9.3的场景,由于followCursor会干扰Tooltip内部交互元素(如滑块、图片)的操作,我们可以通过手动控制光标坐标+自定义Popper定位的方式实现需求,具体方案如下:

核心思路

  1. 手动管理Tooltip的显示/隐藏状态,避免默认hover逻辑的干扰
  2. 监听鼠标事件获取光标坐标(或点击坐标),存储为组件状态
  3. 通过PopperProps覆盖MUI默认的定位逻辑,将Tooltip绑定到目标坐标
  4. 开启interactive属性,确保Tooltip内部元素可正常交互

完整代码示例

跟随光标移动的Tooltip(支持内部交互)

import { useState, useEffect } from 'react';
import Tooltip from '@mui/material/Tooltip';
import Slider from '@mui/material/Slider';
import Box from '@mui/material/Box';

function CursorFollowerTooltip() {
  const [isOpen, setIsOpen] = useState(false);
  const [cursorPos, setCursorPos] = useState({ x: 0, y: 0 });

  // 仅在Tooltip打开时监听鼠标移动,优化性能
  useEffect(() => {
    const handleMouseMove = (e) => {
      setCursorPos({ x: e.clientX, y: e.clientY });
    };

    if (isOpen) {
      window.addEventListener('mousemove', handleMouseMove);
    }

    return () => window.removeEventListener('mousemove', handleMouseMove);
  }, [isOpen]);

  return (
    <div>
      {/* 触发按钮 */}
      <button 
        onMouseEnter={() => setIsOpen(true)}
        onMouseLeave={() => setIsOpen(false)}
      >
        Hover显示跟随光标Tooltip
      </button>

      <Tooltip
        open={isOpen}
        interactive={true} // 允许内部元素交互
        disableHoverListener // 禁用默认hover监听,手动控制显示
        PopperProps={{
          style: {
            position: 'fixed',
            top: `${cursorPos.y + 10}px`, // 偏移10px避免挡住光标
            left: `${cursorPos.x + 10}px`,
            transform: 'none', // 覆盖MUI默认的transform定位
          },
          popperOptions: {
            modifiers: [
              { name: 'preventOverflow', enabled: false }, // 禁用自动位置调整
              { name: 'flip', enabled: false }, // 禁用方向翻转
            ],
          },
        }}
      >
        {/* Tooltip内部交互内容 */}
        <Box sx={{ p: 2, bgcolor: '#fff', border: '1px solid #e0e0e0', borderRadius: 1 }}>
          <img 
            src="https://picsum.photos/120/120" 
            alt="示例图片" 
            style={{ borderRadius: 4 }} 
          />
          <Slider 
            defaultValue={50} 
            sx={{ mt: 2, width: 120 }}
            marks={[{value: 0}, {value: 50}, {value: 100}]}
          />
        </Box>
      </Tooltip>
    </div>
  );
}

export default CursorFollowerTooltip;

固定到点击位置的Tooltip

如果需要Tooltip固定在点击瞬间的光标位置(而非跟随移动),只需修改坐标获取逻辑:

// 替换原useEffect和触发事件
const handleTriggerClick = (e) => {
  setCursorPos({ x: e.clientX, y: e.clientY });
  setIsOpen(!isOpen);
};

// 触发按钮改为:
<button onClick={handleTriggerClick}>点击打开固定位置Tooltip</button>

关键细节说明

  • interactive={true}:必须设置此属性,否则鼠标移入Tooltip内部时会自动关闭,无法操作内部元素
  • disableHoverListener:禁用MUI默认的hover显示逻辑,改为手动控制open状态,避免与自定义定位冲突
  • position: fixed + transform: none:覆盖Popper默认的绝对定位和transform偏移,确保Tooltip严格按照光标坐标渲染
  • 禁用preventOverflow和flip:关闭MUI自动调整Tooltip位置的逻辑,允许Tooltip显示在屏幕任意区域

内容的提问来源于stack exchange,提问作者Алексей Мухин

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:05:26