mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-06-11 06:29:22 +08:00
fix(stage): 只有当组件不在视窗内才自动滚动,新增scrollIntoView配置
This commit is contained in:
parent
e7b9123fd5
commit
dbcd4201ea
@ -14,6 +14,7 @@
|
|||||||
<slot name="workspace">
|
<slot name="workspace">
|
||||||
<workspace
|
<workspace
|
||||||
:runtime-url="runtimeUrl"
|
:runtime-url="runtimeUrl"
|
||||||
|
:auto-scroll-into-view="autoScrollIntoView"
|
||||||
:render="render"
|
:render="render"
|
||||||
:moveable-options="moveableOptions"
|
:moveable-options="moveableOptions"
|
||||||
:can-select="canSelect"
|
:can-select="canSelect"
|
||||||
@ -101,6 +102,9 @@ export default defineComponent({
|
|||||||
/** 中间工作区域中画布通过iframe渲染时的页面url */
|
/** 中间工作区域中画布通过iframe渲染时的页面url */
|
||||||
runtimeUrl: String,
|
runtimeUrl: String,
|
||||||
|
|
||||||
|
/** 选中时是否自动滚动到可视区域 */
|
||||||
|
autoScrollIntoView: Boolean,
|
||||||
|
|
||||||
/** 组件的属性配置表单的dsl */
|
/** 组件的属性配置表单的dsl */
|
||||||
propsConfigs: {
|
propsConfigs: {
|
||||||
type: Object as PropType<Record<string, FormConfig>>,
|
type: Object as PropType<Record<string, FormConfig>>,
|
||||||
|
@ -59,6 +59,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
runtimeUrl: String,
|
runtimeUrl: String,
|
||||||
|
autoScrollIntoView: Boolean,
|
||||||
|
|
||||||
canSelect: {
|
canSelect: {
|
||||||
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
||||||
@ -100,6 +101,7 @@ export default defineComponent({
|
|||||||
render: props.render,
|
render: props.render,
|
||||||
runtimeUrl: props.runtimeUrl,
|
runtimeUrl: props.runtimeUrl,
|
||||||
zoom: zoom.value,
|
zoom: zoom.value,
|
||||||
|
autoScrollIntoView: props.autoScrollIntoView,
|
||||||
canSelect: (el, event, stop) => {
|
canSelect: (el, event, stop) => {
|
||||||
const elCanSelect = props.canSelect(el);
|
const elCanSelect = props.canSelect(el);
|
||||||
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<magic-stage
|
<magic-stage
|
||||||
:key="page?.id"
|
:key="page?.id"
|
||||||
:runtime-url="runtimeUrl"
|
:runtime-url="runtimeUrl"
|
||||||
|
:auto-scroll-into-view="autoScrollIntoView"
|
||||||
:render="render"
|
:render="render"
|
||||||
:moveable-options="moveableOptions"
|
:moveable-options="moveableOptions"
|
||||||
:can-select="canSelect"
|
:can-select="canSelect"
|
||||||
@ -41,6 +42,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
props: {
|
props: {
|
||||||
runtimeUrl: String,
|
runtimeUrl: String,
|
||||||
|
autoScrollIntoView: Boolean,
|
||||||
|
|
||||||
render: {
|
render: {
|
||||||
type: Function as PropType<() => HTMLDivElement>,
|
type: Function as PropType<() => HTMLDivElement>,
|
||||||
|
@ -155,7 +155,10 @@ export default class StageCore extends EventEmitter {
|
|||||||
|
|
||||||
this.mask.setLayout(el);
|
this.mask.setLayout(el);
|
||||||
this.dr.select(el, event);
|
this.dr.select(el, event);
|
||||||
this.mask.scrollIntoView(el);
|
|
||||||
|
if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
|
||||||
|
this.mask.intersectionObserver?.observe(el);
|
||||||
|
}
|
||||||
|
|
||||||
this.selectedDom = el;
|
this.selectedDom = el;
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ export default class StageMask extends Rule {
|
|||||||
public wrapperWidth = 0;
|
public wrapperWidth = 0;
|
||||||
public maxScrollTop = 0;
|
public maxScrollTop = 0;
|
||||||
public maxScrollLeft = 0;
|
public maxScrollLeft = 0;
|
||||||
|
public intersectionObserver: IntersectionObserver | null = null;
|
||||||
|
|
||||||
private mode: Mode = Mode.ABSOLUTE;
|
private mode: Mode = Mode.ABSOLUTE;
|
||||||
private pageResizeObserver: ResizeObserver | null = null;
|
private pageResizeObserver: ResizeObserver | null = null;
|
||||||
@ -132,6 +133,27 @@ export default class StageMask extends Rule {
|
|||||||
this.page = page;
|
this.page = page;
|
||||||
this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
|
this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
|
||||||
this.pageResizeObserver?.disconnect();
|
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') {
|
if (typeof ResizeObserver !== 'undefined') {
|
||||||
this.pageResizeObserver = new ResizeObserver((entries) => {
|
this.pageResizeObserver = new ResizeObserver((entries) => {
|
||||||
@ -173,9 +195,7 @@ export default class StageMask extends Rule {
|
|||||||
this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
|
this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public scrollIntoView(el: HTMLElement): void {
|
public scrollIntoView(el: Element): void {
|
||||||
if (this.mode === Mode.FIXED) return;
|
|
||||||
|
|
||||||
el.scrollIntoView();
|
el.scrollIntoView();
|
||||||
if (!this.pageScrollParent) return;
|
if (!this.pageScrollParent) return;
|
||||||
this.scrollLeft = this.pageScrollParent.scrollLeft;
|
this.scrollLeft = this.pageScrollParent.scrollLeft;
|
||||||
|
@ -37,6 +37,7 @@ export type StageCoreConfig = {
|
|||||||
/** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
|
/** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
|
||||||
runtimeUrl?: string;
|
runtimeUrl?: string;
|
||||||
render?: (renderer: StageCore) => Promise<HTMLElement> | HTMLElement;
|
render?: (renderer: StageCore) => Promise<HTMLElement> | HTMLElement;
|
||||||
|
autoScrollIntoView?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface StageRenderConfig {
|
export interface StageRenderConfig {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user