mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
perf(editor): improve resize frame rate (#10967)
This PR improves panel toggling FPS by minimizing DOM and canvas updates during resizing. [Screen Recording 2025-03-18 at 11.57.45 PM.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/lEGcysB4lFTEbCwZ8jMv/d36beeab-a2e4-4fd6-923a-705ce7fbcdf7.mov" />](https://app.graphite.dev/media/video/lEGcysB4lFTEbCwZ8jMv/d36beeab-a2e4-4fd6-923a-705ce7fbcdf7.mov) ### What changed? - Added a debounced resize handling mechanism using RxJS's `debounceTime` operator - Implemented a new resize strategy that preserves the top-left corner position during resizing - Added state tracking for resize operations with `_isResizing` flag and `_initialTopLeft` coordinates
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
} from '@blocksuite/global/gfx';
|
||||
import { signal } from '@preact/signals-core';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
import { Subject } from 'rxjs';
|
||||
import { debounceTime, Subject } from 'rxjs';
|
||||
|
||||
import type { GfxViewportElement } from '.';
|
||||
|
||||
@@ -54,6 +54,16 @@ export class Viewport {
|
||||
|
||||
private _resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
private readonly _resizeSubject = new Subject<{
|
||||
width: number;
|
||||
height: number;
|
||||
left: number;
|
||||
top: number;
|
||||
}>();
|
||||
|
||||
private _isResizing = false;
|
||||
private _initialTopLeft: IVec | null = null;
|
||||
|
||||
protected _center: IPoint = { x: 0, y: 0 };
|
||||
|
||||
protected _shell: HTMLElement | null = null;
|
||||
@@ -110,6 +120,35 @@ export class Viewport {
|
||||
this._element = el;
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
|
||||
this._setupResizeObserver();
|
||||
}
|
||||
|
||||
private _setupResizeObserver() {
|
||||
this._resizeSubject
|
||||
.pipe(debounceTime(200))
|
||||
.subscribe(({ width, height, left, top }) => {
|
||||
if (!this._shell || !this._initialTopLeft) return;
|
||||
|
||||
const [initialTopLeftX, initialTopLeftY] = this._initialTopLeft;
|
||||
const newCenterX = initialTopLeftX + width / (2 * this.zoom);
|
||||
const newCenterY = initialTopLeftY + height / (2 * this.zoom);
|
||||
|
||||
this.setCenter(newCenterX, newCenterY);
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._left = left;
|
||||
this._top = top;
|
||||
this._isResizing = false;
|
||||
this._initialTopLeft = null;
|
||||
|
||||
this.sizeUpdated.next({
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get boundingClientRect() {
|
||||
@@ -239,6 +278,8 @@ export class Viewport {
|
||||
this.sizeUpdated.complete();
|
||||
this.viewportMoved.complete();
|
||||
this.viewportUpdated.complete();
|
||||
this._resizeSubject.complete();
|
||||
|
||||
this.zooming$.value = false;
|
||||
this.panning$.value = false;
|
||||
}
|
||||
@@ -281,18 +322,23 @@ export class Viewport {
|
||||
|
||||
onResize() {
|
||||
if (!this._shell) return;
|
||||
const { centerX, centerY, zoom, width: oldWidth, height: oldHeight } = this;
|
||||
|
||||
if (!this._isResizing) {
|
||||
this._isResizing = true;
|
||||
this._initialTopLeft = this.toModelCoord(0, 0);
|
||||
}
|
||||
|
||||
const { left, top, width, height } = this.boundingClientRect;
|
||||
this._cachedOffsetWidth = this._shell.offsetWidth;
|
||||
|
||||
this.setRect(left, top, width, height);
|
||||
this.setCenter(
|
||||
centerX - (oldWidth - width) / zoom / 2,
|
||||
centerY - (oldHeight - height) / zoom / 2
|
||||
);
|
||||
|
||||
this._width = width;
|
||||
this._height = height;
|
||||
this._left = left;
|
||||
this._top = top;
|
||||
this._resizeSubject.next({
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}
|
||||
|
||||
setCenter(centerX: number, centerY: number) {
|
||||
@@ -307,6 +353,12 @@ export class Viewport {
|
||||
}
|
||||
|
||||
setRect(left: number, top: number, width: number, height: number) {
|
||||
if (this._isResizing) {
|
||||
this._left = left;
|
||||
this._top = top;
|
||||
return;
|
||||
}
|
||||
|
||||
this._left = left;
|
||||
this._top = top;
|
||||
this.sizeUpdated.next({
|
||||
|
||||
Reference in New Issue
Block a user