fix(stage): 只有当组件不在视窗内才自动滚动,新增scrollIntoView配置

This commit is contained in:
roymondchen 2022-05-25 13:03:50 +08:00 committed by jia000
parent e7b9123fd5
commit dbcd4201ea
6 changed files with 36 additions and 4 deletions

View File

@ -14,6 +14,7 @@
<slot name="workspace">
<workspace
:runtime-url="runtimeUrl"
:auto-scroll-into-view="autoScrollIntoView"
:render="render"
:moveable-options="moveableOptions"
:can-select="canSelect"
@ -101,6 +102,9 @@ export default defineComponent({
/** 中间工作区域中画布通过iframe渲染时的页面url */
runtimeUrl: String,
/** 选中时是否自动滚动到可视区域 */
autoScrollIntoView: Boolean,
/** 组件的属性配置表单的dsl */
propsConfigs: {
type: Object as PropType<Record<string, FormConfig>>,

View File

@ -59,6 +59,7 @@ export default defineComponent({
},
runtimeUrl: String,
autoScrollIntoView: Boolean,
canSelect: {
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
@ -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

View File

@ -3,6 +3,7 @@
<magic-stage
:key="page?.id"
:runtime-url="runtimeUrl"
:auto-scroll-into-view="autoScrollIntoView"
:render="render"
:moveable-options="moveableOptions"
:can-select="canSelect"
@ -41,6 +42,7 @@ export default defineComponent({
props: {
runtimeUrl: String,
autoScrollIntoView: Boolean,
render: {
type: Function as PropType<() => HTMLDivElement>,

View File

@ -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;

View File

@ -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;

View File

@ -37,6 +37,7 @@ export type StageCoreConfig = {
/** runtime 的HTML地址可以是一个HTTP地址如果和编辑器不同域需要设置跨域也可以是一个相对或绝对路径 */
runtimeUrl?: string;
render?: (renderer: StageCore) => Promise<HTMLElement> | HTMLElement;
autoScrollIntoView?: boolean;
};
export interface StageRenderConfig {