refactor(editor): add panning/zooming field in viewport event (#10373)

This commit is contained in:
doodlewind
2025-02-23 08:58:15 +00:00
parent 22f9db63bc
commit 542f759ffb
@@ -1,11 +1,13 @@
import { import {
Bound, Bound,
clamp, clamp,
debounce,
type IPoint, type IPoint,
type IVec, type IVec,
Slot, Slot,
Vec, Vec,
} from '@blocksuite/global/utils'; } from '@blocksuite/global/utils';
import { signal } from '@preact/signals-core';
import type { GfxViewportElement } from '.'; import type { GfxViewportElement } from '.';
@@ -60,12 +62,34 @@ export class Viewport {
viewportMoved = new Slot<IVec>(); viewportMoved = new Slot<IVec>();
viewportUpdated = new Slot<{ zoom: number; center: IVec }>(); viewportUpdated = new Slot<{
zoom: number;
center: IVec;
}>();
zooming$ = signal(false);
panning$ = signal(false);
ZOOM_MAX = ZOOM_MAX; ZOOM_MAX = ZOOM_MAX;
ZOOM_MIN = ZOOM_MIN; ZOOM_MIN = ZOOM_MIN;
private readonly _resetZooming = debounce(
() => {
this.zooming$.value = false;
},
100,
{ leading: false, trailing: true }
);
private readonly _resetPanning = debounce(
() => {
this.panning$.value = false;
},
100,
{ leading: false, trailing: true }
);
constructor() { constructor() {
this.elementReady.once(el => (this._element = el)); this.elementReady.once(el => (this._element = el));
} }
@@ -197,6 +221,8 @@ export class Viewport {
this.sizeUpdated.dispose(); this.sizeUpdated.dispose();
this.viewportMoved.dispose(); this.viewportMoved.dispose();
this.viewportUpdated.dispose(); this.viewportUpdated.dispose();
this.zooming$.value = false;
this.panning$.value = false;
} }
getFitToScreenData( getFitToScreenData(
@@ -254,10 +280,12 @@ export class Viewport {
setCenter(centerX: number, centerY: number) { setCenter(centerX: number, centerY: number) {
this._center.x = centerX; this._center.x = centerX;
this._center.y = centerY; this._center.y = centerY;
this.panning$.value = true;
this.viewportUpdated.emit({ this.viewportUpdated.emit({
zoom: this.zoom, zoom: this.zoom,
center: Vec.toVec(this.center) as IVec, center: Vec.toVec(this.center) as IVec,
}); });
this._resetPanning();
} }
setRect(left: number, top: number, width: number, height: number) { setRect(left: number, top: number, width: number, height: number) {
@@ -373,11 +401,13 @@ export class Viewport {
Vec.toVec(focusPoint), Vec.toVec(focusPoint),
Vec.mul(offset, prevZoom / newZoom) Vec.mul(offset, prevZoom / newZoom)
); );
this.zooming$.value = true;
this.setCenter(newCenter[0], newCenter[1]); this.setCenter(newCenter[0], newCenter[1]);
this.viewportUpdated.emit({ this.viewportUpdated.emit({
zoom: this.zoom, zoom: this.zoom,
center: Vec.toVec(this.center) as IVec, center: Vec.toVec(this.center) as IVec,
}); });
this._resetZooming();
} }
smoothTranslate(x: number, y: number, numSteps = 10) { smoothTranslate(x: number, y: number, numSteps = 10) {