mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-04-20 19:38:05 +00:00
fix(editor): 优化 StageOverlay 双击行为,仅在元素被滚动容器裁剪时打开 overlay
双击页面片容器时直接选中对应页面片;新增 isClippedByScrollContainer 判断元素是否被非页面级滚动容器裁剪,避免不必要的 overlay 弹出。 Made-with: Cursor
This commit is contained in:
parent
0c2f2fd2b5
commit
df2d635682
@ -22,6 +22,7 @@ import { computed, inject, onBeforeUnmount, useTemplateRef, watch } from 'vue';
|
||||
import { CloseBold } from '@element-plus/icons-vue';
|
||||
|
||||
import { TMagicIcon } from '@tmagic/design';
|
||||
import { getIdFromEl } from '@tmagic/utils';
|
||||
|
||||
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
||||
import { useServices } from '@editor/hooks/use-services';
|
||||
@ -49,7 +50,20 @@ watch(stage, (stage) => {
|
||||
if (stage) {
|
||||
stage.on('dblclick', async (event: MouseEvent) => {
|
||||
const el = (await stage.actionManager?.getElementFromPoint(event)) || null;
|
||||
stageOverlayService.openOverlay(el);
|
||||
if (!el) return;
|
||||
|
||||
const id = getIdFromEl()(el);
|
||||
if (id) {
|
||||
const node = editorService.getNodeById(id);
|
||||
if (node?.type === 'page-fragment-container' && node.pageFragmentId) {
|
||||
await editorService.select(node.pageFragmentId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isClippedByScrollContainer(el)) {
|
||||
stageOverlayService.openOverlay(el);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
stageOverlayService.closeOverlay();
|
||||
@ -85,6 +99,60 @@ onBeforeUnmount(() => {
|
||||
stageOverlayService.set('stage', null);
|
||||
});
|
||||
|
||||
/**
|
||||
* 判断元素是否被非页面级的滚动容器裁剪(未完整显示)
|
||||
*
|
||||
* 从元素向上遍历祖先节点,跳过页面/页面片容器,
|
||||
* 检查是否存在设置了 overflow 的滚动容器将该元素裁剪,
|
||||
* 只有元素未被完整显示时才需要打开 overlay 以展示完整内容
|
||||
*/
|
||||
const isClippedByScrollContainer = (el: HTMLElement): boolean => {
|
||||
const win = el.ownerDocument.defaultView;
|
||||
if (!win) return false;
|
||||
|
||||
// 收集所有页面和页面片的 id
|
||||
const root = editorService.get('root');
|
||||
const pageIds = new Set(root?.items?.map((item) => `${item.id}`) ?? []);
|
||||
|
||||
// el 本身就是页面或页面片,无需判断
|
||||
const elId = getIdFromEl()(el);
|
||||
if (elId && pageIds.has(elId)) return false;
|
||||
|
||||
let parent = el.parentElement;
|
||||
|
||||
while (parent && parent !== el.ownerDocument.documentElement) {
|
||||
const parentId = getIdFromEl()(parent);
|
||||
|
||||
// 到达页面或页面片层级,不再继续向上查找
|
||||
if (parentId && pageIds.has(parentId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const { overflowX, overflowY } = win.getComputedStyle(parent);
|
||||
|
||||
if (
|
||||
['auto', 'scroll', 'hidden'].includes(overflowX) ||
|
||||
['auto', 'scroll', 'hidden'].includes(overflowY) ||
|
||||
parent.scrollWidth > parent.clientWidth ||
|
||||
parent.scrollHeight > parent.clientHeight
|
||||
) {
|
||||
// 比较元素与容器的可视区域,判断元素是否被裁剪
|
||||
const elRect = el.getBoundingClientRect();
|
||||
const containerRect = parent.getBoundingClientRect();
|
||||
if (
|
||||
elRect.top < containerRect.top ||
|
||||
elRect.left < containerRect.left ||
|
||||
elRect.bottom > containerRect.bottom ||
|
||||
elRect.right > containerRect.right
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
parent = parent.parentElement;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const closeOverlayHandler = () => {
|
||||
stageOverlayService.closeOverlay();
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user