diff --git a/packages/lb-annotation/src/core/toolOperation/Selection.ts b/packages/lb-annotation/src/core/toolOperation/Selection.ts index a2cad6bea..f796da507 100644 --- a/packages/lb-annotation/src/core/toolOperation/Selection.ts +++ b/packages/lb-annotation/src/core/toolOperation/Selection.ts @@ -58,9 +58,15 @@ class Selection { * Update selectedIDs: * Remove selectedID when selectedIDs includes * Append selectedID when selectedIDs not includes + * SelectedID is * @param selectedID */ - public updateSelectedIDs(selectedID: SelectedID) { + public updateSelectedIDs(selectedID?: SelectedID) { + if (!selectedID) { + this._selectedIDs = []; + return; + } + if (this.selectedIDs.includes(selectedID)) { this.selectedIDs = this.selectedIDs.filter((id) => id !== selectedID); } else { @@ -81,6 +87,17 @@ class Selection { this.setResultAndRender(updatedDataList); } + public updateSelectedGraphWithOffsetProps(offset: { x: number; num }) { + // this.dataList.map(i => { + // if (this.isIdSelected(i.id)) { + // return { + // ...i, + // i: i.x += + // } + // } + // }) + } + public selectAll() { this.selectedIDs = this.visibleDataList.map((i) => i.id); this.toolInstance.render(); @@ -118,7 +135,7 @@ class Selection { // todo: Update tool instance and render } - public isSelectedID(id: string) { + public isIdSelected(id: string) { return this.selectedIDs.includes(id); } } diff --git a/packages/lb-annotation/src/core/toolOperation/rectOperation.ts b/packages/lb-annotation/src/core/toolOperation/rectOperation.ts index 7c1e40d7a..70bb61716 100644 --- a/packages/lb-annotation/src/core/toolOperation/rectOperation.ts +++ b/packages/lb-annotation/src/core/toolOperation/rectOperation.ts @@ -1,3 +1,4 @@ +import _ from 'lodash'; import MathUtils from '@/utils/MathUtils'; import AxisUtils from '@/utils/tool/AxisUtils'; import RectUtils from '@/utils/tool/RectUtils'; @@ -15,6 +16,7 @@ import { getPolygonPointUnderZoom } from '../../utils/tool/polygonTool'; import uuid from '../../utils/uuid'; import { BasicToolOperation, IBasicToolOperationProps } from './basicToolOperation'; import TextAttributeClass from './textAttributeClass'; +import Selection from './Selection'; interface IRectOperationProps extends IBasicToolOperationProps { drawOutSideTarget: boolean; // 是否可以在边界外进行标注 @@ -41,8 +43,6 @@ class RectOperation extends BasicToolOperation { public hoverRectEdgeIndex: number; // 当前 hover 的边 - public selectedRectID?: string; // - public isFlow: boolean; // 是否进行流动 public config: IRectConfig; @@ -51,6 +51,8 @@ class RectOperation extends BasicToolOperation { private _textAttributInstance?: TextAttributeClass; + private selection: Selection; + private dragInfo?: { dragStartCoord: ICoordinate; dragTarget: EDragTarget; @@ -77,6 +79,7 @@ class RectOperation extends BasicToolOperation { this.getCurrentSelectedData = this.getCurrentSelectedData.bind(this); this.updateSelectedRectTextAttribute = this.updateSelectedRectTextAttribute.bind(this); this.setSelectedID = this.setSelectedID.bind(this); + this.selection = new Selection(this); } public setResult(rectList: IRect[]) { @@ -127,12 +130,20 @@ class RectOperation extends BasicToolOperation { } } + get selectedRectID() { + return this.selectedIDs.length === 1 ? this.selectedIDs[0] : undefined; + } + public get selectedRect() { - return this.rectList.find((v) => v.id === this.selectedRectID); + return this.selectedRects.length === 1 ? this.selectedRects[0] : undefined; + } + + public get selectedIDs() { + return this.selection.selectedIDs; } - public get selectedID() { - return this.selectedRectID; + public get selectedRects() { + return this.rectList.filter((i) => this.selectedIDs.includes(i.id)); } public get selectedText() { @@ -152,7 +163,7 @@ class RectOperation extends BasicToolOperation { this.rectList, CommonToolUtils.getSourceID(this.basicResult), this.attributeLockList, - this.selectedID, + this.selectedIDs, ); rect = showingRect; @@ -161,7 +172,7 @@ class RectOperation extends BasicToolOperation { } if (selectedRect) { - rect.push(selectedRect); + rect.push(...selectedRect); } return rect; } @@ -200,7 +211,7 @@ class RectOperation extends BasicToolOperation { this.setSelectedRectID(newID); } - public setSelectedRectID(newID?: string) { + public updateTextAttributeWhileSelectedIdChanged(newID?: string) { const oldID = this.selectedRectID; if (newID !== oldID && oldID) { // 触发文本切换的操作 @@ -211,8 +222,16 @@ class RectOperation extends BasicToolOperation { if (!newID) { this._textAttributInstance?.clearTextAttribute(); } + } - this.selectedRectID = newID; + public setSelectedRectID(newID?: string, isAppend = false) { + this.updateTextAttributeWhileSelectedIdChanged(newID); + + if (isAppend) { + this.selection.updateSelectedIDs(newID); + } else { + this.selection.selectedIDs = newID ? [newID] : []; + } this.render(); this.emit('selectedChange'); @@ -251,7 +270,7 @@ class RectOperation extends BasicToolOperation { const currentRect = this.currentPageResult.find((rect) => rect.label === markerValue); if (currentRect) { - this.setSelectedID(currentRect.id); + this.setSelectedRectID(currentRect.id); if (this.config.attributeConfigurable === true) { this.setDefaultAttribute(currentRect.attribute); } @@ -261,7 +280,7 @@ class RectOperation extends BasicToolOperation { /** 更新文本输入,并且进行关闭 */ public updateSelectedRectTextAttribute(newTextAttribute?: string) { - if (this._textAttributInstance && newTextAttribute) { + if (this._textAttributInstance && newTextAttribute && this.selectedRectID) { // 切换的时候如果存在 let textAttribute = newTextAttribute; @@ -377,52 +396,31 @@ class RectOperation extends BasicToolOperation { ); } - public multiMoveMouseDown(e: MouseEvent) { - const dragStartCoord = this.getCoordinateUnderZoom(e); - const hoverRectID = this.getHoverRectID(e); - - if (this.isMultiMoveMode && hoverRectID && e.button === 0) { - this.dragInfo = { - dragStartCoord, - dragTarget: EDragTarget.Plane, - startTime: +new Date(), - originRectList: this.rectList, - }; - this.dragStatus = EDragStatus.Start; - - return true; - } - - return false; - } - public onMouseDown(e: MouseEvent) { if (super.onMouseDown(e) || this.forbidMouseOperation || e.ctrlKey === true) { return; } - if (this.multiMoveMouseDown(e)) { - return; - } - // e.stopPropagation(); // 仅有在选中模式才能进行拖动 const dragStartCoord = this.getCoordinateUnderZoom(e); const hoverRectID = this.getHoverRectID(e); - const firstRect = this.currentShowList.find((v) => v.id === this.selectedRectID); - /** * 拖拽基础判断,如果包含以下行为则直接禁止操作 - * 1. 不存在框体 - * 2. 拖拽行为下禁止操作 - 右键 - * 3. 拖拽行为下禁止操作 - 左键 + space + * 1. 拖拽行为下禁止操作 - 右键 + * 2. 拖拽行为下禁止操作 - 左键 + space */ - if (!firstRect || e.button === 2 || (e.button === 0 && this.isSpaceKey === true)) { + if (e.button === 2 || (e.button === 0 && this.isSpaceKey === true)) { return; } if (this.selectedRectID) { + const firstRect = this.currentShowList.find((v) => v.id === this.selectedRectID); + if (!firstRect) { + return; + } + if (this.getHoverRectPointIndex(e) > -1) { // 点的拖拽 const dragTarget = EDragTarget.Point; @@ -452,14 +450,15 @@ class RectOperation extends BasicToolOperation { } } - if (hoverRectID === this.selectedRectID && !this.drawingRect) { + if (this.selection.isIdSelected(hoverRectID) && !this.drawingRect) { const dragTarget = EDragTarget.Plane; this.dragInfo = { dragStartCoord, dragTarget, - firstRect, + firstRect: this.selectedRect, startTime: +new Date(), + originRectList: this.selectedRects, }; this.dragStatus = EDragStatus.Start; } @@ -467,6 +466,31 @@ class RectOperation extends BasicToolOperation { return undefined; } + public moveRects(offset: ICoordinate) { + if (this.dragInfo?.originRectList) { + let selectedRects = _.cloneDeep(this.dragInfo.originRectList); + + if (this.dragInfo.dragTarget === EDragTarget.Plane) { + selectedRects = this.dragInfo.originRectList!.map((i) => ({ + ...i, + x: i.x + offset.x / this.zoom, + y: i.y + offset.y / this.zoom, + })); + } + + this.setRectList( + this.rectList.map((v) => { + const updatedRect = selectedRects.find((i) => i.id === v.id); + if (updatedRect) { + return updatedRect; + } + + return v; + }), + ); + } + } + /** * Offset is under zooming. * @param offset @@ -494,6 +518,7 @@ class RectOperation extends BasicToolOperation { if (!this.dragInfo) { return; } + const offset = { x: coordinate.x - this.dragInfo.dragStartCoord.x, y: coordinate.y - this.dragInfo.dragStartCoord.y, @@ -501,8 +526,8 @@ class RectOperation extends BasicToolOperation { this.dragStatus = EDragStatus.Move; - if (this.isMultiMoveMode) { - this.onDragMoveAll(offset); + if (this.dragInfo.dragTarget === EDragTarget.Plane) { + this.moveRects(offset); return; } @@ -519,17 +544,6 @@ class RectOperation extends BasicToolOperation { switch (this.dragInfo.dragTarget) { // 仅处理翻转的偏移 - case EDragTarget.Plane: - selectedRect = { - ...selectedRect, - x: x + offset.x, - y: y + offset.y, - width, - height, - }; - - break; - case EDragTarget.Point: { let newX = x; @@ -769,7 +783,7 @@ class RectOperation extends BasicToolOperation { this.zoom, ); - if ((this.selectedRectID || this.isMultiMoveMode) && this.dragInfo) { + if (this.selectedIDs.length > 0 && this.dragInfo) { this.onDragMove(coordinate); return; } @@ -1088,8 +1102,6 @@ class RectOperation extends BasicToolOperation { const hoverRectID = this.getHoverRectID(e); const hoverRect = this.rectList.find((v) => v.id === hoverRectID); - const { selectedRectID } = this; - this.setSelectedRectID(undefined); if (hoverRect) { this.setDefaultAttribute(hoverRect.attribute); } @@ -1101,11 +1113,11 @@ class RectOperation extends BasicToolOperation { this.firstClickCoord = undefined; } else { // 选中操作 - if (selectedRectID !== hoverRectID) { + if (this.selectedRectID !== hoverRectID) { this.dblClickListener.clearRightDblClick(); } - this.setSelectedRectID(hoverRectID); + this.setSelectedRectID(hoverRectID, e.ctrlKey); this.hoverRectID = ''; if (hoverRect?.label && this.hasMarkerConfig) { @@ -1142,13 +1154,6 @@ class RectOperation extends BasicToolOperation { return; } - /** - * If the code reach here, needs to update to general mode - */ - if (this.isMultiMoveMode) { - this.setOperationMode(EOperationMode.General); - } - // shift + 右键操作 if (e.button === 2 && e.shiftKey === true) { this.shiftRightMouseUp(e); @@ -1246,12 +1251,12 @@ class RectOperation extends BasicToolOperation { this.rectList, CommonToolUtils.getSourceID(this.basicResult), this.attributeLockList, - this.selectedRectID, + this.selectedIDs, ); let rectList = [...showingRect]; if (selectedRect) { - rectList = [...rectList, selectedRect]; + rectList = [...rectList, ...selectedRect]; } const viewPort = CanvasUtils.getViewPort(this.canvas, this.currentPos, this.zoom); @@ -1566,21 +1571,6 @@ class RectOperation extends BasicToolOperation { } } - /** - * Experiment. Render the multiSelected Rect - * - */ - public renderMultiSelectedRect() { - if (!this.isMultiMoveMode) { - return; - } - - this.rectList.forEach((rect) => { - this.renderDrawingRect(rect); - this.renderSelectedRect(rect); - }); - } - /** * 渲染静态框体 */ @@ -1591,11 +1581,11 @@ class RectOperation extends BasicToolOperation { const { renderEnhance = {} } = this; - const [showingRect, selectedRect] = CommonToolUtils.getRenderResultList( + const [showingRect, selectedRects] = CommonToolUtils.getRenderResultList( this.rectList, CommonToolUtils.getSourceID(this.basicResult), this.attributeLockList, - this.selectedRectID, + this.selectedIDs, ); // 静态矩形 if (!this.isHidden) { @@ -1614,17 +1604,19 @@ class RectOperation extends BasicToolOperation { } // 选中矩形熏染 - if (selectedRect) { - this.renderDrawingRect(selectedRect); - this.renderSelectedRect(selectedRect); + if (selectedRects) { + selectedRects.forEach((rect) => { + this.renderDrawingRect(rect); + this.renderSelectedRect(rect); - if (renderEnhance.selectedRender) { - renderEnhance.selectedRender( - this.canvas, - AxisUtils.changeRectByZoom(selectedRect, this.zoom, this.currentPos), - this.getRenderStyle(selectedRect), - ); - } + if (renderEnhance.selectedRender) { + renderEnhance.selectedRender( + this.canvas, + AxisUtils.changeRectByZoom(rect, this.zoom, this.currentPos), + this.getRenderStyle(rect), + ); + } + }); } } @@ -1654,16 +1646,8 @@ class RectOperation extends BasicToolOperation { * 渲染矩形框体 */ public renderRect() { - switch (this.operationMode) { - case EOperationMode.MultiMove: - this.renderMultiSelectedRect(); - break; - - default: { - this.renderStaticRect(); - this.renderCreatingRect(); - } - } + this.renderStaticRect(); + this.renderCreatingRect(); } public render() { @@ -1692,7 +1676,7 @@ class RectOperation extends BasicToolOperation { if (selectedRect) { this.setRectList( this.rectList.map((v) => { - if (v.id === this.selectedID) { + if (v.id === selectedRect.id) { return { ...v, attribute: this.defaultAttribute, diff --git a/packages/lb-annotation/src/utils/tool/CommonToolUtils.ts b/packages/lb-annotation/src/utils/tool/CommonToolUtils.ts index 23eba5453..020a9cee1 100644 --- a/packages/lb-annotation/src/utils/tool/CommonToolUtils.ts +++ b/packages/lb-annotation/src/utils/tool/CommonToolUtils.ts @@ -135,20 +135,20 @@ export default class CommonToolUtils { * @param T 当前图片的结果框 * @param sourceID 当前状态依赖的框体,若依赖原图则返回 '0' * @param attributeLockList 当前展示的属性 - * @param selectedID 是否含有选中逻辑 + * @param selectedIDs 是否含有选中逻辑 * @returns */ public static getRenderResultList( resultList: any[], sourceID: string, attributeLockList: string[] = [], - selectedID?: string, - ): [T[], T | undefined] { - let selectedRect; + selectedIDs?: string[], + ): [T[], T[]] { + const selectedRect: T[] = []; const showingRect = resultList.filter((result) => { - if (selectedID && selectedID === result?.id) { - selectedRect = result; + if (selectedIDs && selectedIDs.includes(result.id)) { + selectedRect.push(result); return false; }