From 439eb90e93506227bfe0b08b521c4cc4ed912903 Mon Sep 17 00:00:00 2001 From: qishaoxuan Date: Wed, 27 Jul 2022 19:06:59 +0800 Subject: [PATCH] feat: add frozen scroll method in editor.scrollManager, resolved #564 --- .../src/pages/workspace/docs/Page.tsx | 7 +- .../editor-core/src/editor/scroll/scroll.ts | 72 ++++++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx b/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx index 8b0e17f1d1..c756fa9ba5 100644 --- a/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx +++ b/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx @@ -62,12 +62,15 @@ export function Page(props: PageProps) { }, [user, props.workspace, page_id]); const onScroll = (event: UIEvent) => { - editorRef.current.scrollManager.scrollContainer = - scrollContainerRef.current; editorRef.current.getHooks().onRootNodeScroll(event); editorRef.current.scrollManager.emitScrollEvent(event); }; + useEffect(() => { + editorRef.current.scrollManager.scrollContainer = + scrollContainerRef.current; + }, []); + return ( diff --git a/libs/components/editor-core/src/editor/scroll/scroll.ts b/libs/components/editor-core/src/editor/scroll/scroll.ts index a9967b54c3..104fc187fe 100644 --- a/libs/components/editor-core/src/editor/scroll/scroll.ts +++ b/libs/components/editor-core/src/editor/scroll/scroll.ts @@ -1,4 +1,4 @@ -import { type UIEvent } from 'react'; +import { CSSProperties, type UIEvent } from 'react'; import EventEmitter from 'eventemitter3'; import { domToRect, Rect } from '@toeverything/utils'; @@ -9,6 +9,29 @@ import { AsyncBlock } from '../block'; type VerticalTypes = 'up' | 'down' | null; type HorizontalTypes = 'left' | 'right' | null; +const setStyle = (dom: HTMLElement, style: CSSProperties) => { + const styleStr = Object.entries(style).reduce( + (styleStr, [styleName, styleValue]) => { + return `${styleStr} ${styleName}: ${styleValue};`; + }, + '' + ); + + dom.setAttribute('style', styleStr); +}; + +// 这里只获取 style 里设置过的属性 +// 在恢复 body 后重新设置,不需要获取计算属性 +const getStyle = (dom: HTMLElement, styleName: any) => { + return dom.style[styleName]; +}; +const getStyles = (dom: HTMLElement, styleNames: any[]) => { + return styleNames.reduce((style, styleName) => { + style[styleName] = getStyle(dom, styleName); + return style; + }, {}); +}; + export class ScrollManager { private _editor: Block_editor; private _scrollContainer: HTMLElement; @@ -21,9 +44,13 @@ export class ScrollManager { private _scrollMoveOffset = 8; private _autoScrollMoveOffset = 8; private _scrollingEvent = new EventEmitter(); + private _isFrozen = false; + private _scrollContainerStyle: CSSProperties = {}; constructor(editor: BlockEditor) { this._editor = editor; + + (window as any).scrollManager = this; } private _updateScrollInfo(left: number, top: number) { @@ -280,4 +307,47 @@ export class ScrollManager { this._animationFrame = null; } } + + public frozen() { + if (this._isFrozen) { + return; + } + + this._scrollContainerStyle = getStyles(this._scrollContainer, [ + // 'position', + // 'top', + // 'left', + 'overflow', + 'height', + ]); + + // const [recordScrollLeft, recordScrollTop] = this._scrollRecord; + + setStyle(this._scrollContainer, { + // Position style maybe should set in mobile + + // position: 'fixed', + // top: `-${recordScrollTop}px`, + // left: `-${recordScrollLeft}px`, + overflow: 'hidden', + height: '100%', + }); + + this._isFrozen = true; + } + + public thaw() { + if (!this._isFrozen) { + return; + } + + setStyle(this._scrollContainer, this._scrollContainerStyle); + + const [recordScrollLeft, recordScrollTop] = this._scrollRecord; + this._scrollContainer.scrollTo(recordScrollLeft, recordScrollTop); + + this._scrollContainerStyle = {}; + + this._isFrozen = false; + } }