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

MUI Popover如何实现从鼠标按下位置启动打开过渡动画

MUI Popover 鼠标按下触发+点击位置启动过渡实现

核心实现逻辑分3步:

  • 替换触发事件:弃用默认的onClick(mouseup触发)逻辑,给触发元素绑定onMouseDown事件,在鼠标按下瞬间执行逻辑
  • 记录指针坐标:在mousedown回调中通过事件对象的clientX、clientY属性,保存当前鼠标按下的屏幕坐标
  • 自定义锚点:将Popover的锚点参考设置为坐标模式,传入保存的鼠标坐标作为锚点,组件的打开过渡会自动以锚点为起点播放

可直接运行的示例代码:

import * as React from 'react';
import Popover from '@mui/material/Popover';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';

export default function CustomPopover() {
  const [open, setOpen] = React.useState(false);
  const [anchorPosition, setAnchorPosition] = React.useState({ top: 0, left: 0 });

  const handleTriggerMouseDown = (e) => {
    // 保存鼠标按下位置
    setAnchorPosition({
      top: e.clientY,
      left: e.clientX,
    });
    // 切换弹出层开关状态
    setOpen(prev => !prev);
  };

  const handleClose = () => {
    setOpen(false);
  };

  return (
    <>
      <Button
        variant="contained"
        onMouseDown={handleTriggerMouseDown}
        onClick={(e) => e.preventDefault()}
      >
        按鼠标触发弹出层
      </Button>
      <Popover
        open={open}
        // 启用坐标锚点模式,不依赖DOM元素定位
        anchorReference="anchorPosition"
        anchorPosition={anchorPosition}
        // 对齐锚点与弹出层变换原点,保证过渡从鼠标位置启动
        anchorOrigin={{ vertical: 'top', horizontal: 'left' }}
        transformOrigin={{ vertical: 'top', horizontal: 'left' }}
        onClose={handleClose}
      >
        <Typography sx={{ p: 2 }}>弹出层内容区域</Typography>
      </Popover>
    </>
  );
}

按需调整项:

  1. 如果需要点击弹出层内部不触发关闭,给Popover添加onMouseDown={(e) => e.stopPropagation()}阻止事件冒泡即可
  2. 如果需要弹出层相对于鼠标位置有偏移,直接修改anchorPosition的top、left值,或者调整anchorOrigin/transformOrigin的配置即可
  3. 如果需要不同的过渡方向,修改transformOrigin的取值(比如设为center、bottom、right)就能改变过渡动画的启动方向

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:21:15