Files
FiDA_Front/src/components/Canvas/DepthCanvas/manager/AISelectboxToolManager.ts

150 lines
4.0 KiB
TypeScript
Raw Normal View History

2026-03-13 11:18:36 +08:00
import { fabric } from 'fabric-with-all'
2026-03-24 11:49:53 +08:00
import { OperationType, AI_SELECTBOX_TYPE } from '../tools/layerHelper'
2026-03-23 16:43:08 +08:00
import { getObjectAlphaToCanvas, traceImageContour } from '../tools/canvasMethod'
2026-03-20 13:23:00 +08:00
2026-03-13 11:18:36 +08:00
/** 智能框选工具管理器 */
export class AISelectboxToolManager {
// 管理器
canvasManager: any
stateManager: any
layerManager: any
2026-03-23 16:43:08 +08:00
toolManager: any
2026-03-13 11:18:36 +08:00
isDragging: boolean = false
startX: number = 0
startY: number = 0
demoObject: any
constructor(options) {
this.canvasManager = options.canvasManager
this.stateManager = options.stateManager
this.layerManager = options.layerManager
2026-03-23 16:43:08 +08:00
this.toolManager = options.toolManager
2026-03-13 11:18:36 +08:00
}
2026-03-24 11:49:53 +08:00
/** 处理切换工具 */
handleToolChange(oldTool: string, newTool: string) {
if (newTool === OperationType.SELECTBOX) {
// 切换到智能框选工具
} else {
// 切换到普通框选工具
}
}
2026-03-13 11:18:36 +08:00
mouseDownEvent(e) {
this.isDragging = true
this.startX = e.absolutePointer.x
this.startY = e.absolutePointer.y
const rect = new fabric.Rect({
left: this.startX,
top: this.startY,
width: 0,
height: 0,
fill: 'transparent',
stroke: '#000',
strokeWidth: 1,
evented: false,
})
this.demoObject = rect
this.canvasManager.canvas.add(rect)
this.canvasManager.canvas.renderAll()
}
mouseMoveEvent(e) {
if (!this.isDragging) return;
var width = e.absolutePointer.x - this.startX
var height = e.absolutePointer.y - this.startY
var left = this.startX
var top = this.startY
2026-03-20 13:23:00 +08:00
if (width < 0) {
2026-03-13 11:18:36 +08:00
left += width
width = -width
}
2026-03-20 13:23:00 +08:00
if (height < 0) {
2026-03-13 11:18:36 +08:00
top += height
height = -height
}
this.demoObject.set({ width, height, left, top })
this.canvasManager.canvas.renderAll()
}
mouseUpEvent(e) {
if (!this.isDragging) return;
this.isDragging = false;
const object = this.demoObject.toJSON("evented")
if (object.width === 0) object.width = 100
if (object.height === 0) object.height = 100
// console.log(object)
this.canvasManager.canvas.remove(this.demoObject)
this.canvasManager.canvas.renderAll()
2026-03-24 11:49:53 +08:00
// this.createSelectbox()
2026-03-20 13:23:00 +08:00
}
loadImageToObject(url) {
return new Promise((resolve, reject) => {
fabric.Image.fromURL(url, (img) => {
resolve(img);
}, { crossOrigin: "anonymous" });// 防止污染
});
}
rgba = { r: 0, g: 255, b: 0, a: 200 };
selectionStyle = {
stroke: "rgba(255, 77, 71, 1)",
strokeWidth: 1.5,
strokeDashArray: [4, 4],
2026-03-23 16:43:08 +08:00
fill: "transparent",
2026-03-20 13:23:00 +08:00
strokeUniform: true, // 保持描边宽度不随缩放改变
2026-03-23 16:43:08 +08:00
selectable: false,
evented: false,
absolutePositioned: true,
2026-03-20 13:23:00 +08:00
};
async createSelectbox() {
const url = "http://118.31.39.42:3000/falls/1a48ed3a-1faa-4fcd-bf07-765dba1702c5.png"
const image = await this.loadImageToObject(url)
const canvas = getObjectAlphaToCanvas(image, null, 0, this.rgba);
const fobject = this.canvasManager.canvas.clipPath
// const top = fobject.top - fobject.height * scaleY / 2;
// const left = fobject.left - fobject.width * scaleX / 2;
const scaleY = fobject.scaleY
const scaleX = fobject.scaleX
const top = fobject.top
const left = fobject.left
const arr = traceImageContour(canvas);
let minX = fobject.width;
let minY = fobject.height;
const str = arr.map((v) => {
if (v.x < minX) minX = v.x;
if (v.y < minY) minY = v.y;
return `${v.x} ${v.y}`
}).join(" L ");
const path = new fabric.Path(`M ${str} z`);
path.set({
2026-03-23 16:43:08 +08:00
left: left + minX,
top: top + minY,
2026-03-20 13:23:00 +08:00
scaleX: scaleX,
scaleY: scaleY,
...this.selectionStyle,
});
2026-03-23 16:43:08 +08:00
const group = await this.layerManager.createGroupLayer({
clipPath: path,
}, false, false)
const rect = await this.layerManager.createRectLayer({
width: path.width,
height: path.height,
left: left + minX,
top: top + minY,
fill: "rgba(255, 186, 186, 0.5)",
info: { parentId: group.info.id },
}, false, true)
await this.canvasManager.updateSubLayerClipPath()
await this.layerManager.updateLayerThumbnailsById(rect.info.id, "", false)
await this.layerManager.updateLayerThumbnailsById(group.info.id, rect.thumbnail)
this.stateManager.recordState()
this.toolManager.setTool(OperationType.SELECT)
2026-03-13 11:18:36 +08:00
}
2026-03-20 13:23:00 +08:00
2026-03-13 11:18:36 +08:00
dispose() { }
}