feat(docs-drawing-ui): optimize float-dom on doc canvas (#4824)

This commit is contained in:
ZhangWei
2025-03-12 21:29:16 +08:00
committed by GitHub
parent 9cfefaf4de
commit e8332bcf0d
9 changed files with 54 additions and 63 deletions
@@ -115,6 +115,7 @@ export interface IDrawingParam extends IDrawingSearch {
// The default value is BooleanNumber.FALSE. if it's true, Please use transforms.
isMultiTransform?: BooleanNumber;
groupId?: string;
allowTransform?: boolean;
}
// #endregion
@@ -130,7 +130,10 @@ export class DocDrawingTransformerController extends Disposable {
const drawingData = documentDataModel?.getSnapshot().drawings?.[drawing.drawingId];
if (drawingData?.layoutType === PositionedObjectLayoutType.INLINE) {
(object as Image).setOpacity(0.2);
try {
(object as Image).setOpacity(0.2);
} catch (e) {
}
}
if (drawingData != null) {
@@ -202,7 +205,10 @@ export class DocDrawingTransformerController extends Disposable {
const drawingCache = this._transformerCache.get(drawing?.drawingId);
if (drawingCache?.drawing.layoutType === PositionedObjectLayoutType.INLINE) {
(object as Image).setOpacity(1);
try {
(object as Image).setOpacity(1);
} catch (e) {
}
}
}
@@ -18,13 +18,13 @@ import type { DocumentDataModel, IDisposable, IDrawingSearch, Nullable } from '@
import type { IDocFloatDom } from '@univerjs/docs-drawing';
import type { ISetDocZoomRatioOperationParams } from '@univerjs/docs-ui';
import type { IDocFloatDomDataBase } from '@univerjs/drawing';
import type { BaseObject, IRender, Rect } from '@univerjs/engine-render';
import type { IRender, Rect } from '@univerjs/engine-render';
import type { IFloatDomLayout } from '@univerjs/ui';
import type { IInsertDrawingCommandParams } from '../commands/commands/interfaces';
import { Disposable, DisposableCollection, DrawingTypeEnum, fromEventSubject, generateRandomId, ICommandService, Inject, IUniverInstanceService, ObjectRelativeFromH, ObjectRelativeFromV, PositionedObjectLayoutType, toDisposable, UniverInstanceType } from '@univerjs/core';
import { DocSkeletonManagerService } from '@univerjs/docs';
import { docDrawingPositionToTransform, SetDocZoomRatioOperation, VIEWPORT_KEY } from '@univerjs/docs-ui';
import { getDrawingShapeKeyByDrawingSearch, IDrawingManagerService } from '@univerjs/drawing';
import { IDrawingManagerService } from '@univerjs/drawing';
import { DrawingRenderService } from '@univerjs/drawing-ui';
import { CURSOR_TYPE, IRenderManagerService } from '@univerjs/engine-render';
import { CanvasFloatDomService } from '@univerjs/ui';
@@ -32,10 +32,10 @@ import { BehaviorSubject, map, of, switchMap } from 'rxjs';
import { InsertDocDrawingCommand } from '../commands/commands/insert-doc-drawing.command';
function calcDocFloatDomPosition(
object: BaseObject,
object: Rect,
renderUnit: IRender
): IFloatDomLayout {
const { top, left, width, height, angle } = object;
const { top, left, width, height, angle, opacity } = object;
// const
const scene = renderUnit.scene;
const viewMain = scene.getViewport(VIEWPORT_KEY.VIEW_MAIN)!;
@@ -49,11 +49,12 @@ function calcDocFloatDomPosition(
endY: (top + height - viewportScrollY) * scaleY,
width,
height,
rotate: 0,
rotate: angle,
absolute: {
left: false,
top: false,
},
opacity: opacity ?? 1,
};
}
@@ -64,6 +65,9 @@ interface ICanvasFloatDomInfo {
unitId: string;
}
interface IDocFloatDomParams extends IDocFloatDomDataBase {
}
export class DocFloatDomController extends Disposable {
private _domLayerInfoMap = new Map<string, ICanvasFloatDomInfo>();
@@ -86,7 +90,6 @@ export class DocFloatDomController extends Disposable {
private _initialize() {
this._drawingAddRemoveListener();
this._imageUpdateListener();
this._initScrollAndZoomEvent();
}
@@ -194,47 +197,6 @@ export class DocFloatDomController extends Disposable {
});
}
private _imageUpdateListener() {
this.disposeWithMe(
this._drawingManagerService.update$.subscribe((params) => {
(params).forEach((param) => {
const { unitId, subUnitId, drawingId } = param;
const drawingParam = this._drawingManagerService.getDrawingByParam(param) as IDocFloatDom;
if (drawingParam == null) {
return;
}
const { transform, drawingType } = drawingParam;
if (drawingType !== DrawingTypeEnum.DRAWING_IMAGE) {
return;
}
const renderObject = this._getSceneAndTransformerByDrawingSearch(unitId);
if (renderObject == null) {
return;
}
const { scene } = renderObject;
if (transform == null) {
return true;
}
const drawingShapeKey = getDrawingShapeKeyByDrawingSearch({ unitId, subUnitId, drawingId });
const imageShape = scene.getObject(drawingShapeKey) as Rect;
if (imageShape == null) {
return true;
}
});
})
);
}
private _addHoverForRect(o: Rect) {
this.disposeWithMe(
toDisposable(
@@ -311,7 +273,7 @@ export class DocFloatDomController extends Disposable {
}));
}
insertFloatDom(floatDom: IDocFloatDomDataBase, opts: { width?: number; height: number; drawingId?: string }) {
insertFloatDom(floatDom: IDocFloatDomParams, opts: { width?: number; height: number; drawingId?: string }) {
const currentDoc = this._univerInstanceService.getCurrentUnitOfType(UniverInstanceType.UNIVER_DOC);
if (!currentDoc) return false;
const render = this._getSceneAndTransformerByDrawingSearch(currentDoc.getUnitId());
@@ -337,12 +299,12 @@ export class DocFloatDomController extends Disposable {
},
angle: 0,
};
const drawingId = opts.drawingId ?? generateRandomId();
const params: IInsertDrawingCommandParams = {
unitId: currentDoc.getUnitId(),
drawings: [
{
drawingId: opts.drawingId ?? generateRandomId(),
drawingId,
drawingType: DrawingTypeEnum.DRAWING_DOM,
subUnitId: currentDoc.getUnitId(),
unitId: currentDoc.getUnitId(),
@@ -355,6 +317,8 @@ export class DocFloatDomController extends Disposable {
},
],
};
this._commandService.executeCommand(InsertDocDrawingCommand.id, params);
this._commandService.syncExecuteCommand(InsertDocDrawingCommand.id, params);
return drawingId;
}
}
@@ -16,7 +16,7 @@
import type { DocumentDataModel, IDisposable, Nullable } from '@univerjs/core';
import type { BaseObject, Scene } from '@univerjs/engine-render';
import { FOCUSING_COMMON_DRAWINGS, IContextService, Inject, IUniverInstanceService, RxDisposable, SHEET_EDITOR_UNITS, toDisposable, UniverInstanceType } from '@univerjs/core';
import { DrawingTypeEnum, FOCUSING_COMMON_DRAWINGS, IContextService, Inject, IUniverInstanceService, RxDisposable, SHEET_EDITOR_UNITS, toDisposable, UniverInstanceType } from '@univerjs/core';
import { DocCanvasPopManagerService } from '@univerjs/docs-ui';
import { IDrawingManagerService } from '@univerjs/drawing';
import { COMPONENT_IMAGE_POPUP_MENU, ImageCropperObject, ImageResetSizeOperation, OpenImageCropOperation } from '@univerjs/drawing-ui';
@@ -114,7 +114,7 @@ export class DocDrawingPopupMenuController extends RxDisposable {
return;
}
const { unitId, subUnitId, drawingId } = drawingParam;
const { unitId, subUnitId, drawingId, drawingType } = drawingParam;
const popup = this._canvasPopManagerService.attachPopupToObject(
object,
{
@@ -122,7 +122,7 @@ export class DocDrawingPopupMenuController extends RxDisposable {
direction: 'horizontal',
offset: [2, 0],
extraProps: {
menuItems: this._getImageMenuItems(unitId, subUnitId, drawingId),
menuItems: this._getImageMenuItems(unitId, subUnitId, drawingId, drawingType),
},
},
unitId
@@ -176,14 +176,14 @@ export class DocDrawingPopupMenuController extends RxDisposable {
);
}
private _getImageMenuItems(unitId: string, subUnitId: string, drawingId: string) {
private _getImageMenuItems(unitId: string, subUnitId: string, drawingId: string, drawingType: number) {
return [
{
label: 'image-popup.edit',
index: 0,
commandId: EditDocDrawingOperation.id,
commandParams: { unitId, subUnitId, drawingId },
disable: !!SHEET_EDITOR_UNITS.includes(unitId),
disable: !!SHEET_EDITOR_UNITS.includes(unitId) || drawingType === DrawingTypeEnum.DRAWING_DOM,
},
{
label: 'image-popup.delete',
@@ -26,8 +26,8 @@ import { DocSelectionManagerService, DocSkeletonManagerService, RichTextEditingM
import { IDocDrawingService } from '@univerjs/docs-drawing';
import { docDrawingPositionToTransform, DocSelectionRenderService } from '@univerjs/docs-ui';
import { DRAWING_IMAGE_ALLOW_IMAGE_LIST, DRAWING_IMAGE_ALLOW_SIZE, DRAWING_IMAGE_COUNT_LIMIT, DRAWING_IMAGE_HEIGHT_LIMIT, DRAWING_IMAGE_WIDTH_LIMIT, getDrawingShapeKeyByDrawingSearch, getImageSize, IDrawingManagerService, IImageIoService, ImageUploadStatusType } from '@univerjs/drawing';
import { DocumentEditArea, IRenderManagerService } from '@univerjs/engine-render';
import { ILocalFileService, IMessageService } from '@univerjs/ui';
import { debounceTime } from 'rxjs';
import { GroupDocDrawingCommand } from '../../commands/commands/group-doc-drawing.command';
@@ -351,13 +351,22 @@ export class DocDrawingUpdateRenderController extends Disposable implements IRen
if (drawingShapes.length) {
for (const shape of drawingShapes) {
scene.detachTransformerFrom(shape);
(shape as Image).setOpacity(0.5);
try {
(shape as Image).setOpacity(0.5);
} catch (e) {
}
if (
(isEditBody && drawing.isMultiTransform !== BooleanNumber.TRUE)
|| (!isEditBody && drawing.isMultiTransform === BooleanNumber.TRUE)
) {
scene.attachTransformerTo(shape);
(shape as Image).setOpacity(1);
if (drawing.allowTransform !== false) {
scene.attachTransformerTo(shape);
}
try {
(shape as Image).setOpacity(1);
} catch (e) {
}
}
}
}
@@ -186,7 +186,7 @@ export class DrawingRenderService {
}
scene.addObject(rect, DRAWING_OBJECT_LAYER_INDEX);
if (this._drawingManagerService.getDrawingEditable()) {
if (this._drawingManagerService.getDrawingEditable() && param.allowTransform !== false) {
scene.attachTransformerTo(rect);
}
+9
View File
@@ -33,6 +33,7 @@ export class Rect<T extends IRectProps = IRectProps> extends Shape<T> {
override objectType = ObjectType.RECT;
private _radius: number = 0;
private _opacity: number = 1;
/**
* For rendering, in many case object size is bigger than visual size for better user interaction.
@@ -65,10 +66,18 @@ export class Rect<T extends IRectProps = IRectProps> extends Shape<T> {
return this._radius;
}
get opacity() {
return this._opacity;
}
setObjectType(type: ObjectType) {
this.objectType = type;
}
setOpacity(opacity: number) {
this._opacity = opacity;
}
static override drawWith(ctx: UniverRenderingContext, props: IRectProps) {
let { radius, width, height } = props;
@@ -26,6 +26,7 @@ export interface IFloatDomLayout extends IPosition {
left: boolean;
top: boolean;
};
opacity?: number;
}
export interface IFloatDom {
@@ -58,6 +58,7 @@ const FloatDomSingle = memo((props: { layer: IFloatDom; id: string }) => {
domRef.current.style.transform = transformRef.current;
domRef.current.style.top = `${topRef.current}px`;
domRef.current.style.left = `${leftRef.current}px`;
domRef.current.style.opacity = `${position.opacity ?? 1}`;
}
});