From dbcd4201eaf90a688321f4ccd33ae7545bb578c2 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Wed, 25 May 2022 13:03:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(stage):=20=E5=8F=AA=E6=9C=89=E5=BD=93?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E4=B8=8D=E5=9C=A8=E8=A7=86=E7=AA=97=E5=86=85?= =?UTF-8?q?=E6=89=8D=E8=87=AA=E5=8A=A8=E6=BB=9A=E5=8A=A8=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9EscrollIntoView=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/src/Editor.vue | 4 +++ .../editor/src/layouts/workspace/Stage.vue | 2 ++ .../src/layouts/workspace/Workspace.vue | 2 ++ packages/stage/src/StageCore.ts | 5 +++- packages/stage/src/StageMask.ts | 26 ++++++++++++++++--- packages/stage/src/types.ts | 1 + 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/Editor.vue b/packages/editor/src/Editor.vue index 32d66205..8418df5f 100644 --- a/packages/editor/src/Editor.vue +++ b/packages/editor/src/Editor.vue @@ -14,6 +14,7 @@ >, diff --git a/packages/editor/src/layouts/workspace/Stage.vue b/packages/editor/src/layouts/workspace/Stage.vue index e2934ba1..a5d65e81 100644 --- a/packages/editor/src/layouts/workspace/Stage.vue +++ b/packages/editor/src/layouts/workspace/Stage.vue @@ -59,6 +59,7 @@ export default defineComponent({ }, runtimeUrl: String, + autoScrollIntoView: Boolean, canSelect: { type: Function as PropType<(el: HTMLElement) => boolean | Promise>, @@ -100,6 +101,7 @@ export default defineComponent({ render: props.render, runtimeUrl: props.runtimeUrl, zoom: zoom.value, + autoScrollIntoView: props.autoScrollIntoView, canSelect: (el, event, stop) => { const elCanSelect = props.canSelect(el); // 在组件联动过程中不能再往下选择,返回并触发 ui-select diff --git a/packages/editor/src/layouts/workspace/Workspace.vue b/packages/editor/src/layouts/workspace/Workspace.vue index 9094f8cb..f47cd036 100644 --- a/packages/editor/src/layouts/workspace/Workspace.vue +++ b/packages/editor/src/layouts/workspace/Workspace.vue @@ -3,6 +3,7 @@ HTMLDivElement>, diff --git a/packages/stage/src/StageCore.ts b/packages/stage/src/StageCore.ts index 4f97780e..c371600f 100644 --- a/packages/stage/src/StageCore.ts +++ b/packages/stage/src/StageCore.ts @@ -155,7 +155,10 @@ export default class StageCore extends EventEmitter { this.mask.setLayout(el); this.dr.select(el, event); - this.mask.scrollIntoView(el); + + if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) { + this.mask.intersectionObserver?.observe(el); + } this.selectedDom = el; diff --git a/packages/stage/src/StageMask.ts b/packages/stage/src/StageMask.ts index 333920d7..bd7c8cae 100644 --- a/packages/stage/src/StageMask.ts +++ b/packages/stage/src/StageMask.ts @@ -83,6 +83,7 @@ export default class StageMask extends Rule { public wrapperWidth = 0; public maxScrollTop = 0; public maxScrollLeft = 0; + public intersectionObserver: IntersectionObserver | null = null; private mode: Mode = Mode.ABSOLUTE; private pageResizeObserver: ResizeObserver | null = null; @@ -132,6 +133,27 @@ export default class StageMask extends Rule { this.page = page; this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null; this.pageResizeObserver?.disconnect(); + this.wrapperResizeObserver?.disconnect(); + this.intersectionObserver?.disconnect(); + + if (typeof IntersectionObserver !== 'undefined') { + this.intersectionObserver = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + const { target, intersectionRatio } = entry; + if (intersectionRatio <= 0) { + this.scrollIntoView(target); + } + this.intersectionObserver?.unobserve(target); + }); + }, + { + root: this.pageScrollParent, + rootMargin: '0px', + threshold: 1.0, + }, + ); + } if (typeof ResizeObserver !== 'undefined') { this.pageResizeObserver = new ResizeObserver((entries) => { @@ -173,9 +195,7 @@ export default class StageMask extends Rule { this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE); } - public scrollIntoView(el: HTMLElement): void { - if (this.mode === Mode.FIXED) return; - + public scrollIntoView(el: Element): void { el.scrollIntoView(); if (!this.pageScrollParent) return; this.scrollLeft = this.pageScrollParent.scrollLeft; diff --git a/packages/stage/src/types.ts b/packages/stage/src/types.ts index 6c50ed24..50b7edaf 100644 --- a/packages/stage/src/types.ts +++ b/packages/stage/src/types.ts @@ -37,6 +37,7 @@ export type StageCoreConfig = { /** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */ runtimeUrl?: string; render?: (renderer: StageCore) => Promise | HTMLElement; + autoScrollIntoView?: boolean; }; export interface StageRenderConfig {