1. 实现思路
首先,将 Tooltip 框固定在要悬浮的内容上面(这里仅做了悬浮在上面的效果,其他位置暂未实现),根据 getBoundingClientRect 获取当前元素的 top、left;然后,在页面滚动时,动态获取元素的位置,更新 Tooltip 的位置;最后,在点击空白区域时,关闭 Tooltip 框。
2. 具体步骤
2.1 获取悬浮位置
const [tooltipVisible, setTooltipVisible] = useState(false)
const [tooltipStyle, setTooltipStyle] = useState({})
const buttonRef = useRef<HTMLButtonElement | null>(null)
const handleButtonClick = () => {
if (!buttonRef.current) return
const buttonRect = buttonRef.current.getBoundingClientRect()
setTooltipStyle({
top: `${buttonRect.top + window.scrollY - 55}px`,
left: `${buttonRect.left + buttonRect.width / 2}px`,
transform: 'translateX(-50%)'
})
setTooltipVisible(!tooltipVisible)
}
return (
<>
<div className='content'>
<p>
Hello world!
</p>
<Button
ref={buttonRef}
type='link'
onClick={handleButtonClick}
>
Tooltip
</Button>
{
tooltipVisible && (
<div ref={tooltipRef} className="custom-tooltip" style={tooltipStyle}>
This is Tooltip hover content
</div>
)
}
</div>
</>
)
.content {
width: 200px;
height: 3000px;
background-color: grey;
padding: 20px;
}
.custom-tooltip {
position: absolute;
background: #fff;
border: 1px solid #ddd;
padding: 10px;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1000;
pointer-events: none;
}
.custom-tooltip::after {
content: '';
position: absolute;
bottom: -8px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-style: solid;
border-width: 8px 8px 0 8px;
border-color: #fff transparent transparent transparent;
z-index: 1001;
}
.custom-tooltip::before {
content: '';
position: absolute;
bottom: -9px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-style: solid;
border-width: 9px 9px 0 9px;
border-color: #ddd transparent transparent transparent;
z-index: 1000;
}
2.2 元素滚动更新位置
const handleScroll = () => {
if (tooltipVisible && buttonRef.current) {
const buttonRect = buttonRef.current.getBoundingClientRect()
setTooltipStyle({
top: `${buttonRect.top + window.scrollY - 55}px`,
left: `${buttonRect.left + buttonRect.width / 2}px`,
transform: 'translateX(-50%)',
});
}
}
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [tooltipVisible]);
2.3 点击空白区域关闭 Tooltip 框
// click the blank container to close tooltip
const handleClickOutside = (e: MouseEvent) => {
if (
tooltipRef.current && buttonRef.current &&
!tooltipRef.current.contains(e.target as Node) &&
!buttonRef.current.contains(e.target as Node)
) {
setTooltipVisible(false);
}
};
useEffect(() => {
document.addEventListener('click', handleClickOutside);
return () => {
document.removeEventListener('click', handleClickOutside);
};
}, [tooltipVisible]);