feat: 优化选区功能,修复部分bug
This commit is contained in:
@@ -14,7 +14,7 @@ import { generateId } from "../utils/helper.js";
|
||||
|
||||
/**
|
||||
* 套索抠图命令
|
||||
* 实现将选区内容抠图到新图层的功能
|
||||
* 实现将选区内容到新图层遮罩
|
||||
*/
|
||||
export class LassoCutoutCommand extends CompositeCommand {
|
||||
constructor(options = {}) {
|
||||
@@ -36,8 +36,11 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
this.highResolutionEnabled = options.highResolutionEnabled !== false; // 默认启用
|
||||
this.baseResolutionScale = options.baseResolutionScale || 2; // 基础分辨率倍数
|
||||
|
||||
this.groupId = options.groupId || `cutout-group-${Date.now()}`;
|
||||
this.groupId = options.groupId || generateId("lasso-group-");
|
||||
this.groupName = options.groupName || `选区组`;
|
||||
|
||||
this.clippingMaskId = generateId("clipping-mask-");
|
||||
|
||||
this.groupLayer = null; // 新增:保存组图层的引用
|
||||
this.originalLayersLength = 0; // 新增:保存原始图层数量
|
||||
|
||||
@@ -51,6 +54,8 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
this.originalFabricObjects = []; // 保存原图层的所有fabric对象(序列化)
|
||||
this.originalCanvasObjects = []; // 保存从画布中获取的真实fabric对象
|
||||
this._initializeOriginalLayerInfo();
|
||||
|
||||
this.oldActiveLayerId = this.layerManager.activeLayerId.value; // 保存旧的活动图层ID
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,14 +149,24 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
// 获取源图层的所有对象(包括子图层)
|
||||
const sourceObjects = this._getLayerObjects(sourceLayer);
|
||||
if (sourceObjects.length === 0) {
|
||||
console.error("无法执行套索抠图:源图层没有可见对象");
|
||||
return false;
|
||||
}
|
||||
// const sourceObjects = this._getLayerObjects(sourceLayer);
|
||||
// if (sourceObjects.length === 0) {
|
||||
// console.error("无法执行套索抠图:源图层没有可见对象");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
const clippingMask = fabric.util.object.clone(selectionObject);
|
||||
clippingMask.set({
|
||||
id: this.clippingMaskId,
|
||||
selectable: false,
|
||||
evented: false,
|
||||
hasControls: false,
|
||||
// layerId: this.groupId,
|
||||
visible: true,
|
||||
});
|
||||
|
||||
// 获取选区边界信息用于后续定位
|
||||
const selectionBounds = selectionObject.getBoundingRect(true, true);
|
||||
// const selectionBounds = selectionObject.getBoundingRect(true, true);
|
||||
|
||||
// 使用createRasterizedImage执行抠图操作
|
||||
// this.cutoutImageUrl = await this._performCutoutWithRasterized(
|
||||
@@ -164,46 +179,34 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
this.fabricImage = await this._performCutoutWithRasterized(
|
||||
sourceObjects,
|
||||
selectionObject,
|
||||
selectionBounds
|
||||
);
|
||||
// this.fabricImage = await this._performCutoutWithRasterized(
|
||||
// sourceObjects,
|
||||
// selectionObject,
|
||||
// selectionBounds
|
||||
// );
|
||||
|
||||
// // 创建fabric图像对象,传递选区边界信息
|
||||
// this.fabricImage = await this._createFabricImage(
|
||||
// this.cutoutImageUrl,
|
||||
// selectionBounds
|
||||
// );
|
||||
if (!this.fabricImage) {
|
||||
console.error("创建图像对象失败");
|
||||
return false;
|
||||
}
|
||||
// if (!this.fabricImage) {
|
||||
// console.error("创建图像对象失败");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// 1. 创建图像图层命令
|
||||
const createImageLayerCmd = new CreateImageLayerCommand({
|
||||
layerManager: this.layerManager,
|
||||
fabricImage: this.fabricImage,
|
||||
toolManager: this.toolManager,
|
||||
layerName: this.newLayerName,
|
||||
});
|
||||
// const createImageLayerCmd = new CreateImageLayerCommand({
|
||||
// layerManager: this.layerManager,
|
||||
// fabricImage: this.fabricImage,
|
||||
// toolManager: this.toolManager,
|
||||
// layerName: this.newLayerName,
|
||||
// });
|
||||
|
||||
// 执行创建图像图层命令
|
||||
const result = await createImageLayerCmd.execute();
|
||||
this.newLayerId = createImageLayerCmd.newLayerId;
|
||||
this.executedCommands.push(createImageLayerCmd);
|
||||
|
||||
// 2. 删除原图层命令
|
||||
const removeOriginalLayerCmd = new RemoveLayerCommand({
|
||||
canvas: this.canvas,
|
||||
layers: this.layerManager.layers,
|
||||
layerId: this.originalLayer.id,
|
||||
activeLayerId: this.layerManager.activeLayerId,
|
||||
});
|
||||
|
||||
// 执行删除原图层命令
|
||||
await removeOriginalLayerCmd.execute();
|
||||
this.executedCommands.push(removeOriginalLayerCmd);
|
||||
// // 执行创建图像图层命令
|
||||
// const result = await createImageLayerCmd.execute();
|
||||
// this.newLayerId = createImageLayerCmd.newLayerId;
|
||||
// this.executedCommands.push(createImageLayerCmd);
|
||||
|
||||
// 3. 清除选区命令
|
||||
const clearSelectionCmd = new ClearSelectionCommand({
|
||||
@@ -216,10 +219,10 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
this.executedCommands.push(clearSelectionCmd);
|
||||
|
||||
const topLayerIndex = this.layerManager.layers.value.findIndex(
|
||||
(layer) => layer.id === this.newLayerId
|
||||
(layer) => layer.id === this.originalLayer.id
|
||||
);
|
||||
|
||||
const selectLayer = this.layerManager.layers.value[topLayerIndex];
|
||||
// const selectLayer = this.layerManager.layers.value[topLayerIndex];
|
||||
|
||||
// 创建新的组图层
|
||||
this.groupLayer = createLayer({
|
||||
@@ -233,28 +236,47 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
children: [],
|
||||
});
|
||||
|
||||
this.fabricImage.set({
|
||||
selectable: true,
|
||||
evented: true,
|
||||
// this.fabricImage.set({
|
||||
// selectable: true,
|
||||
// evented: true,
|
||||
// });
|
||||
|
||||
const selectLayer = createLayer({
|
||||
name: `选区空图层`,
|
||||
type: LayerType.EMPTY,
|
||||
visible: true,
|
||||
locked: false,
|
||||
opacity: 1.0,
|
||||
fabricObjects: [],
|
||||
children: [],
|
||||
});
|
||||
|
||||
selectLayer.parentId = this.groupId; // 设置新图层的parentId为组图层ID
|
||||
selectLayer.fabricObjects = [
|
||||
this.fabricImage.toObject("id", "layerId", "layerName", "parentId"),
|
||||
];
|
||||
this.groupLayer.clippingMask = this.fabricImage.toObject(
|
||||
"id",
|
||||
"layerId",
|
||||
"layerName",
|
||||
"parentId"
|
||||
); // 设置组图层的fabricObject为遮罩图像
|
||||
// selectLayer.fabricObjects = [
|
||||
// this.fabricImage.toObject("id", "layerId", "layerName", "parentId"),
|
||||
// ];
|
||||
// 2. 删除原图层命令
|
||||
const removeOriginalLayerCmd = new RemoveLayerCommand({
|
||||
canvas: this.canvas,
|
||||
layers: this.layerManager.layers,
|
||||
layerId: this.originalLayer.id,
|
||||
activeLayerId: this.layerManager.activeLayerId,
|
||||
});
|
||||
|
||||
// 执行删除原图层命令
|
||||
await removeOriginalLayerCmd.execute();
|
||||
this.executedCommands.push(removeOriginalLayerCmd);
|
||||
|
||||
this.groupLayer.clippingMask = clippingMask.toObject(["id", "layerId"]); // 设置组图层的fabricObject为遮罩图像
|
||||
|
||||
this.groupLayer.children.push(selectLayer);
|
||||
// 插入新组图层
|
||||
this.layerManager.layers.value.splice(topLayerIndex, 1, this.groupLayer);
|
||||
this.layerManager.layers.value.splice(topLayerIndex, 0, this.groupLayer);
|
||||
|
||||
this.layerManager.activeLayerId.value = selectLayer.id; // 设置新组图层为活动图层
|
||||
|
||||
this.canvas.discardActiveObject();
|
||||
this.canvas.setActiveObject(this.fabricImage);
|
||||
// this.canvas.setActiveObject(this.fabricImage);
|
||||
await this.layerManager.updateLayersObjectsInteractivity(true);
|
||||
|
||||
console.log(`套索抠图完成,新图层ID: ${this.newLayerId}`);
|
||||
@@ -328,6 +350,8 @@ export class LassoCutoutCommand extends CompositeCommand {
|
||||
}
|
||||
}
|
||||
|
||||
this.layerManager.activeLayerId.value = this.oldActiveLayerId; // 恢复旧的活动图层ID
|
||||
|
||||
if (this.fabricImage) {
|
||||
console.log(`↩️ 移除抠图图像: ${this.fabricImage.id}`);
|
||||
// 从画布中移除抠图图像
|
||||
|
||||
Reference in New Issue
Block a user