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> </> ); }
按需调整项:
- 如果需要点击弹出层内部不触发关闭,给Popover添加
onMouseDown={(e) => e.stopPropagation()}阻止事件冒泡即可- 如果需要弹出层相对于鼠标位置有偏移,直接修改
anchorPosition的top、left值,或者调整anchorOrigin/transformOrigin的配置即可- 如果需要不同的过渡方向,修改
transformOrigin的取值(比如设为center、bottom、right)就能改变过渡动画的启动方向
内容的提问来源于stack exchange,提问作者Rylan Schaeffer
相关产品推荐
相关产品推荐

