From 963cc2e40e79868b967e37cfd11820f264550ffc Mon Sep 17 00:00:00 2001 From: Yifeng Wang Date: Sat, 22 Feb 2025 21:58:13 +0800 Subject: [PATCH] refactor(editor): reduce redundant canvas refresh on init (#10364) --- .../src/edgeless/edgeless-root-block.ts | 2 + .../shared/src/viewport-renderer/dom-utils.ts | 2 +- .../viewport-renderer/viewport-renderer.ts | 25 +++++++------ .../framework/block-std/src/gfx/controller.ts | 2 +- .../framework/block-std/src/gfx/viewport.ts | 37 +++++++++++++------ 5 files changed, 43 insertions(+), 25 deletions(-) diff --git a/blocksuite/affine/block-root/src/edgeless/edgeless-root-block.ts b/blocksuite/affine/block-root/src/edgeless/edgeless-root-block.ts index 871ba4dd12..fe1162f3dc 100644 --- a/blocksuite/affine/block-root/src/edgeless/edgeless-root-block.ts +++ b/blocksuite/affine/block-root/src/edgeless/edgeless-root-block.ts @@ -553,6 +553,8 @@ export class EdgelessRootBlockComponent extends BlockComponent< this.gfx.tool.setTool('default'); } + this.gfx.viewport.elementReady.emit(this.gfxViewportElm); + requestConnectedFrame(() => { this.requestUpdate(); }, this); diff --git a/blocksuite/affine/shared/src/viewport-renderer/dom-utils.ts b/blocksuite/affine/shared/src/viewport-renderer/dom-utils.ts index d443e4e4f5..fb15f9fb69 100644 --- a/blocksuite/affine/shared/src/viewport-renderer/dom-utils.ts +++ b/blocksuite/affine/shared/src/viewport-renderer/dom-utils.ts @@ -103,7 +103,7 @@ export function initTweakpane( debugPane.title = 'Viewport Turbo Renderer'; debugPane - .addBinding({ paused: true }, 'paused', { + .addBinding({ paused: false }, 'paused', { label: 'Paused', }) .on('change', ({ value }) => { diff --git a/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts b/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts index 8746e9774d..5f97e8e6e7 100644 --- a/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts +++ b/blocksuite/affine/shared/src/viewport-renderer/viewport-renderer.ts @@ -50,14 +50,20 @@ export class ViewportTurboRendererExtension extends LifeCycleWatcher { } override mounted() { - const viewportElement = document.querySelector('.affine-edgeless-viewport'); - if (viewportElement) { - viewportElement.append(this.canvas); - initTweakpane(this, viewportElement as HTMLElement); + const mountPoint = document.querySelector('.affine-edgeless-viewport'); + if (mountPoint) { + mountPoint.append(this.canvas); + initTweakpane(this, mountPoint as HTMLElement); } - syncCanvasSize(this.canvas, this.std.host); - this.viewport.viewportUpdated.on(() => { - this.refresh().catch(console.error); + + this.viewport.elementReady.once(() => { + syncCanvasSize(this.canvas, this.std.host); + this.state = 'monitoring'; + this.disposables.add( + this.viewport.viewportUpdated.on(() => { + this.refresh().catch(console.error); + }) + ); }); const debounceOptions = { leading: false, trailing: true }; @@ -72,11 +78,6 @@ export class ViewportTurboRendererExtension extends LifeCycleWatcher { debouncedLayoutUpdate(); }) ); - - document.fonts.load('15px Inter').then(() => { - // this.state = 'monitoring'; - this.refresh().catch(console.error); - }); } override unmounted() { diff --git a/blocksuite/framework/block-std/src/gfx/controller.ts b/blocksuite/framework/block-std/src/gfx/controller.ts index f2b8dcb6d7..25b7ead368 100644 --- a/blocksuite/framework/block-std/src/gfx/controller.ts +++ b/blocksuite/framework/block-std/src/gfx/controller.ts @@ -274,7 +274,7 @@ export class GfxController extends LifeCycleWatcher { } override mounted() { - this.viewport.setViewportElement(this.std.host); + this.viewport.setShellElement(this.std.host); this.std.provider.getAll(GfxExtensionIdentifier).forEach(ext => { ext.mounted(); }); diff --git a/blocksuite/framework/block-std/src/gfx/viewport.ts b/blocksuite/framework/block-std/src/gfx/viewport.ts index 187b2eaf3a..36bc9e9096 100644 --- a/blocksuite/framework/block-std/src/gfx/viewport.ts +++ b/blocksuite/framework/block-std/src/gfx/viewport.ts @@ -7,6 +7,8 @@ import { Vec, } from '@blocksuite/global/utils'; +import type { GfxViewportElement } from '.'; + function cutoff(value: number, ref: number, sign: number) { if (sign > 0 && value > ref) return ref; if (sign < 0 && value < ref) return ref; @@ -29,7 +31,9 @@ export class Viewport { protected _center: IPoint = { x: 0, y: 0 }; - protected _el: HTMLElement | null = null; + protected _shell: HTMLElement | null = null; + + protected _element: GfxViewportElement | null = null; protected _height = 0; @@ -45,6 +49,8 @@ export class Viewport { protected _zoom: number = 1.0; + elementReady = new Slot(); + sizeUpdated = new Slot<{ width: number; height: number; @@ -60,14 +66,22 @@ export class Viewport { ZOOM_MIN = ZOOM_MIN; + constructor() { + this.elementReady.once(el => (this._element = el)); + } + get boundingClientRect() { - if (!this._el) return new DOMRect(0, 0, 0, 0); + if (!this._shell) return new DOMRect(0, 0, 0, 0); if (!this._cachedBoundingClientRect) { - this._cachedBoundingClientRect = this._el.getBoundingClientRect(); + this._cachedBoundingClientRect = this._shell.getBoundingClientRect(); } return this._cachedBoundingClientRect; } + get element() { + return this._element; + } + get center() { return this._center; } @@ -103,7 +117,7 @@ export class Viewport { * This property is used to calculate the scale of the editor. */ get viewScale() { - if (!this._el || this._cachedOffsetWidth === null) return 1; + if (!this._shell || this._cachedOffsetWidth === null) return 1; return this.boundingClientRect.width / this._cachedOffsetWidth; } @@ -168,12 +182,12 @@ export class Viewport { } clearViewportElement() { - if (this._resizeObserver && this._el) { - this._resizeObserver.unobserve(this._el); + if (this._resizeObserver && this._shell) { + this._resizeObserver.unobserve(this._shell); this._resizeObserver.disconnect(); } this._resizeObserver = null; - this._el = null; + this._shell = null; this._cachedBoundingClientRect = null; this._cachedOffsetWidth = null; } @@ -222,10 +236,10 @@ export class Viewport { } onResize() { - if (!this._el) return; + if (!this._shell) return; const { centerX, centerY, zoom, width: oldWidth, height: oldHeight } = this; const { left, top, width, height } = this.boundingClientRect; - this._cachedOffsetWidth = this._el.offsetWidth; + this._cachedOffsetWidth = this._shell.offsetWidth; this.setRect(left, top, width, height); this.setCenter( @@ -331,8 +345,9 @@ export class Viewport { this.setViewport(zoom, center, smooth); } - setViewportElement(el: HTMLElement) { - this._el = el; + /** This is the outer container of the viewport, which is the host of the viewport element */ + setShellElement(el: HTMLElement) { + this._shell = el; this._cachedBoundingClientRect = el.getBoundingClientRect(); this._cachedOffsetWidth = el.offsetWidth;