Improve tooltip (#13326)
* 减少元素更新 * 改进悬浮提示元素位置计算 messageElement.innerHTML = message; 会更新元素的内容,元素此时的 left 属性会对元素的宽度产生影响,导致更新后的元素(比如元素内的文本意外换行了)与直接新建的元素(元素内的文本不会换行)宽度不一致。messageElement.clientWidth 会获取到不符合预期的宽度,进而导致 left 计算错误。 * fix https://github.com/siyuan-note/siyuan/issues/12680 * 隐藏悬浮提示增加少许延迟,避免在相邻的元素间移动时悬浮提示频繁闪烁 * 频率高的放前面
This commit is contained in:
parent
ded16deb13
commit
eac2902d9b
1 changed files with 47 additions and 19 deletions
|
@ -1,5 +1,7 @@
|
|||
import {isMobile} from "../util/functions";
|
||||
|
||||
let hideTooltipTimeout: NodeJS.Timeout | null = null;
|
||||
|
||||
export const showTooltip = (message: string, target: Element, tooltipClass?: string) => {
|
||||
if (isMobile()) {
|
||||
return;
|
||||
|
@ -9,17 +11,33 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
|
|||
hideTooltip();
|
||||
return;
|
||||
}
|
||||
let messageElement = document.getElementById("tooltip");
|
||||
if (!messageElement) {
|
||||
document.body.insertAdjacentHTML("beforeend", `<div class="tooltip" id="tooltip">${message}</div>`);
|
||||
messageElement = document.getElementById("tooltip");
|
||||
} else {
|
||||
messageElement.className = "tooltip";
|
||||
messageElement.innerHTML = message;
|
||||
|
||||
// 清除 hideTooltip 的定时器
|
||||
if (hideTooltipTimeout) {
|
||||
clearTimeout(hideTooltipTimeout);
|
||||
hideTooltipTimeout = null;
|
||||
}
|
||||
|
||||
if (tooltipClass) {
|
||||
messageElement.classList.add("tooltip--" + tooltipClass);
|
||||
let messageElement = document.getElementById("tooltip");
|
||||
if (!messageElement) {
|
||||
document.body.insertAdjacentHTML("beforeend", `<div class="tooltip${!tooltipClass ? "" : " tooltip--" + tooltipClass}" id="tooltip">${message}</div>`);
|
||||
messageElement = document.getElementById("tooltip");
|
||||
} else {
|
||||
const currentClassName = messageElement.className;
|
||||
const currentMessage = messageElement.textContent;
|
||||
|
||||
let newClassName = "tooltip";
|
||||
if (tooltipClass) {
|
||||
newClassName += " tooltip--" + tooltipClass;
|
||||
}
|
||||
// 避免不必要的更新
|
||||
if (currentClassName !== newClassName) {
|
||||
messageElement.className = newClassName;
|
||||
}
|
||||
if (currentMessage !== message) {
|
||||
// 鼠标在按钮等多层结构的元素上小幅移动时会频繁更新
|
||||
messageElement.innerHTML = message;
|
||||
}
|
||||
}
|
||||
|
||||
let left = targetRect.left;
|
||||
|
@ -32,12 +50,7 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
|
|||
left = targetRect.right - messageElement.clientWidth;
|
||||
}
|
||||
|
||||
if (position?.endsWith("bottom")) {
|
||||
top += parseInt(position.replace("right", "").replace("left", ""));
|
||||
} else if (position?.endsWith("top")) {
|
||||
// 编辑器动态滚动条
|
||||
top = targetRect.top - messageElement.clientHeight;
|
||||
} else if (position === "parentE") {
|
||||
if (position === "parentE") {
|
||||
// file tree and outline、backlink
|
||||
top = parentRect.top;
|
||||
left = parentRect.right + 8;
|
||||
|
@ -45,6 +58,11 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
|
|||
// 数据库属性视图
|
||||
top = parentRect.top + (parseInt(position) || 8);
|
||||
left = parentRect.left - messageElement.clientWidth;
|
||||
} else if (position?.endsWith("bottom")) {
|
||||
top += parseInt(position.replace("right", "").replace("left", ""));
|
||||
} else if (position?.endsWith("top")) {
|
||||
// 编辑器动态滚动条
|
||||
top = targetRect.top - messageElement.clientHeight;
|
||||
}
|
||||
|
||||
const topHeight = position === "parentE" ? top : targetRect.top;
|
||||
|
@ -52,6 +70,10 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
|
|||
|
||||
messageElement.style.maxHeight = Math.max(topHeight, bottomHeight) + "px";
|
||||
|
||||
// 避免原本的 top 和 left 影响计算
|
||||
messageElement.style.top = "0px";
|
||||
messageElement.style.left = "0px";
|
||||
|
||||
if (top + messageElement.clientHeight > window.innerHeight && topHeight > bottomHeight) {
|
||||
messageElement.style.top = ((position === "parentE" ? parentRect.bottom : targetRect.top) - messageElement.clientHeight) + "px";
|
||||
} else {
|
||||
|
@ -62,7 +84,7 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
|
|||
if (position === "parentE") {
|
||||
messageElement.style.left = (parentRect.left - 8 - messageElement.clientWidth) + "px";
|
||||
} else {
|
||||
messageElement.style.left = (window.innerWidth - messageElement.clientWidth) + "px";
|
||||
messageElement.style.left = (window.innerWidth - 1 - messageElement.clientWidth) + "px";
|
||||
}
|
||||
} else {
|
||||
messageElement.style.left = Math.max(0, left) + "px";
|
||||
|
@ -70,8 +92,14 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
|
|||
};
|
||||
|
||||
export const hideTooltip = () => {
|
||||
const messageElement = document.getElementById("tooltip");
|
||||
if (messageElement) {
|
||||
messageElement.remove();
|
||||
if (hideTooltipTimeout) {
|
||||
clearTimeout(hideTooltipTimeout);
|
||||
}
|
||||
hideTooltipTimeout = setTimeout(() => {
|
||||
const messageElement = document.getElementById("tooltip");
|
||||
if (messageElement) {
|
||||
messageElement.remove();
|
||||
}
|
||||
hideTooltipTimeout = null;
|
||||
}, 50);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue