mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-16 22:50:13 +01:00
Improve toolbar position calculation (#15983)
* 🎨 Improve toolbar position calculation * 🎨 Improve toolbar position calculation * 🎨 Improve toolbar position calculation
This commit is contained in:
parent
67f3e527c1
commit
4aede9687e
3 changed files with 32 additions and 9 deletions
|
|
@ -6,7 +6,10 @@
|
||||||
box-shadow: var(--b3-point-shadow);
|
box-shadow: var(--b3-point-shadow);
|
||||||
border-radius: var(--b3-border-radius);
|
border-radius: var(--b3-border-radius);
|
||||||
display: flex;
|
display: flex;
|
||||||
transition: top .15s cubic-bezier(0, 0, .2, 1) 0ms;
|
|
||||||
|
&__transition {
|
||||||
|
transition: top .15s cubic-bezier(0, 0, .2, 1) 0ms;
|
||||||
|
}
|
||||||
|
|
||||||
&__item {
|
&__item {
|
||||||
color: var(--b3-theme-on-surface);
|
color: var(--b3-theme-on-surface);
|
||||||
|
|
|
||||||
|
|
@ -164,12 +164,17 @@ export class Toolbar {
|
||||||
this.element.classList.add("fn__none");
|
this.element.classList.add("fn__none");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const rangePosition = getSelectionPosition(nodeElement, range);
|
this.element.classList.remove("fn__none", "protyle-toolbar__transition");
|
||||||
this.element.classList.remove("fn__none");
|
|
||||||
this.toolbarHeight = this.element.clientHeight;
|
this.toolbarHeight = this.element.clientHeight;
|
||||||
const y = rangePosition.top - this.toolbarHeight - 4;
|
const rangePosition = getSelectionPosition(nodeElement, range, this.element.clientWidth);
|
||||||
|
const y = rangePosition.isToolbarAtBottom ?
|
||||||
|
Math.min(rangePosition.top + 4, protyle.element.getBoundingClientRect().bottom - this.toolbarHeight) :
|
||||||
|
Math.max(rangePosition.top - this.toolbarHeight - 4, protyle.element.getBoundingClientRect().top + 30);
|
||||||
this.element.setAttribute("data-inity", y + Constants.ZWSP + protyle.contentElement.scrollTop.toString());
|
this.element.setAttribute("data-inity", y + Constants.ZWSP + protyle.contentElement.scrollTop.toString());
|
||||||
setPosition(this.element, rangePosition.left - 52, Math.max(y, protyle.element.getBoundingClientRect().top + 30));
|
setPosition(this.element, rangePosition.left, y);
|
||||||
|
|
||||||
|
this.element.classList.add("protyle-toolbar__transition");
|
||||||
this.element.querySelectorAll(".protyle-toolbar__item--current").forEach(item => {
|
this.element.querySelectorAll(".protyle-toolbar__item--current").forEach(item => {
|
||||||
item.classList.remove("protyle-toolbar__item--current");
|
item.classList.remove("protyle-toolbar__item--current");
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ export const getEditorRange = (element: Element): Range => {
|
||||||
return range;
|
return range;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getSelectionPosition = (nodeElement: Element, range?: Range) => {
|
export const getSelectionPosition = (nodeElement: Element, range?: Range, toolbarWidth?: number) => {
|
||||||
if (!range) {
|
if (!range) {
|
||||||
range = getEditorRange(nodeElement);
|
range = getEditorRange(nodeElement);
|
||||||
}
|
}
|
||||||
|
|
@ -261,9 +261,24 @@ export const getSelectionPosition = (nodeElement: Element, range?: Range) => {
|
||||||
} else {
|
} else {
|
||||||
const rects = range.getClientRects(); // 由于长度过长折行,光标在行首时有多个 rects https://github.com/siyuan-note/siyuan/issues/6156
|
const rects = range.getClientRects(); // 由于长度过长折行,光标在行首时有多个 rects https://github.com/siyuan-note/siyuan/issues/6156
|
||||||
if (range.toString()) {
|
if (range.toString()) {
|
||||||
return { // 选中多行不应遮挡第一行 https://github.com/siyuan-note/siyuan/issues/7541
|
const selection = window.getSelection();
|
||||||
left: rects[rects.length - 1].left,
|
// 判断选择方向
|
||||||
top: rects[0].top
|
const isBackward = selection && "direction" in selection ?
|
||||||
|
(selection as { direction: "forward" | "backward" | "none" }).direction === "backward"
|
||||||
|
: range.startContainer === selection?.focusNode && range.startOffset === selection?.focusOffset;
|
||||||
|
let isToolbarAtBottom = false;
|
||||||
|
if (!isBackward) {
|
||||||
|
// 检查是否有多个垂直位置不同的矩形
|
||||||
|
isToolbarAtBottom = rects.length > 1 && Array.from(rects).some((rect: DOMRect) => rect.top !== rects[0].top);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
// 向左选择:使用第一个矩形的左边界;向右选择:使用最后一个矩形的右边界
|
||||||
|
// 减去工具栏宽度的1/4:将工具栏中不太常用的按钮往右偏一点
|
||||||
|
left: (isBackward ? rects[0].left : rects[rects.length - 1].right) - (toolbarWidth || 0) / 4,
|
||||||
|
// 如果向右选择时有多个垂直位置不同的矩形:使用最后一个矩形的下边界;否则使用第一个矩形的上边界
|
||||||
|
top: isToolbarAtBottom ? rects[rects.length - 1].bottom : rects[0].top,
|
||||||
|
isToolbarAtBottom: isToolbarAtBottom,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return { // 代码块首 https://github.com/siyuan-note/siyuan/issues/13113
|
return { // 代码块首 https://github.com/siyuan-note/siyuan/issues/13113
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue