mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 18:26:05 +08:00
refactor(editor): extract image block (#9309)
This commit is contained in:
100
blocksuite/affine/block-image/src/image-resize-manager.ts
Normal file
100
blocksuite/affine/block-image/src/image-resize-manager.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
||||
import {
|
||||
getClosestBlockComponentByElement,
|
||||
getModelByElement,
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import type { BlockComponent, PointerEventState } from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
|
||||
export class ImageResizeManager {
|
||||
private _activeComponent: BlockComponent | null = null;
|
||||
|
||||
private _dragMoveTarget = 'right';
|
||||
|
||||
private _imageCenterX = 0;
|
||||
|
||||
private _imageContainer: HTMLElement | null = null;
|
||||
|
||||
private _zoom = 1;
|
||||
|
||||
onEnd() {
|
||||
assertExists(this._activeComponent);
|
||||
assertExists(this._imageContainer);
|
||||
|
||||
const dragModel = getModelByElement(this._activeComponent);
|
||||
dragModel?.page.captureSync();
|
||||
const { width, height } = this._imageContainer.getBoundingClientRect();
|
||||
dragModel?.page.updateBlock(dragModel, {
|
||||
width: width / this._zoom,
|
||||
height: height / this._zoom,
|
||||
});
|
||||
}
|
||||
|
||||
onMove(e: PointerEventState) {
|
||||
assertExists(this._activeComponent);
|
||||
const activeComponent = this._activeComponent;
|
||||
const activeImgContainer = this._imageContainer;
|
||||
assertExists(activeImgContainer);
|
||||
const activeImg = activeComponent.querySelector('img');
|
||||
assertExists(activeImg);
|
||||
|
||||
let width = 0;
|
||||
if (this._dragMoveTarget === 'right') {
|
||||
width = (e.raw.pageX - this._imageCenterX) * 2;
|
||||
} else {
|
||||
width = (this._imageCenterX - e.raw.pageX) * 2;
|
||||
}
|
||||
|
||||
const MIN_WIDTH = 50;
|
||||
if (width < MIN_WIDTH) {
|
||||
width = MIN_WIDTH;
|
||||
}
|
||||
if (width > activeComponent.getBoundingClientRect().width) {
|
||||
width = activeComponent.getBoundingClientRect().width;
|
||||
}
|
||||
|
||||
const height = width * (activeImg.naturalHeight / activeImg.naturalWidth);
|
||||
|
||||
const containerRect = activeImgContainer.getBoundingClientRect();
|
||||
if (containerRect.width === width && containerRect.height === height)
|
||||
return;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
activeImgContainer.style.width = (width / this._zoom).toFixed(2) + 'px';
|
||||
});
|
||||
}
|
||||
|
||||
onStart(e: PointerEventState) {
|
||||
const eventTarget = e.raw.target as HTMLElement;
|
||||
this._activeComponent = getClosestBlockComponentByElement(
|
||||
eventTarget
|
||||
) as BlockComponent;
|
||||
|
||||
const rootComponent = getClosestRootBlockComponent(this._activeComponent);
|
||||
if (
|
||||
rootComponent &&
|
||||
rootComponent.service.std.get(DocModeProvider).getEditorMode() ===
|
||||
'edgeless'
|
||||
) {
|
||||
const viewport = rootComponent.std.get(GfxControllerIdentifier).viewport;
|
||||
this._zoom = viewport.zoom;
|
||||
} else {
|
||||
this._zoom = 1;
|
||||
}
|
||||
|
||||
this._imageContainer = eventTarget.closest('.resizable-img');
|
||||
assertExists(this._imageContainer);
|
||||
const rect = this._imageContainer.getBoundingClientRect() as DOMRect;
|
||||
this._imageCenterX = rect.left + rect.width / 2;
|
||||
if (eventTarget.className.includes('right')) {
|
||||
this._dragMoveTarget = 'right';
|
||||
} else {
|
||||
this._dragMoveTarget = 'left';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getClosestRootBlockComponent(el: HTMLElement): BlockComponent | null {
|
||||
return el.closest('affine-edgeless-root, affine-page-root');
|
||||
}
|
||||
Reference in New Issue
Block a user