feat: 裁剪组裁剪跟随选择组移动
This commit is contained in:
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
createLayer,
|
||||
findInChildLayers,
|
||||
LayerType,
|
||||
} from "../utils/layerHelper.js";
|
||||
import { createLayer, findInChildLayers, LayerType } from "../utils/layerHelper.js";
|
||||
import { createRasterizedImage } from "../utils/selectionToImage.js";
|
||||
import { CompositeCommand, Command } from "./Command.js";
|
||||
import { CreateImageLayerCommand } from "./LayerCommands.js";
|
||||
@@ -59,9 +55,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
const selectionObject = this.selectionManager.getSelectionObject();
|
||||
if (selectionObject) {
|
||||
try {
|
||||
this._clonedSelectionObject = await this._cloneObject(
|
||||
selectionObject
|
||||
);
|
||||
this._clonedSelectionObject = await this._cloneObject(selectionObject);
|
||||
console.log("剪切选区:选区对象已克隆保存");
|
||||
} catch (error) {
|
||||
console.error("剪切选区:克隆选区对象失败:", error);
|
||||
@@ -132,11 +126,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
}
|
||||
|
||||
// 步骤2: 对原图层进行栅格化处理,移除选区内容
|
||||
await this._rasterizeOriginalLayerWithCutout(
|
||||
sourceLayer,
|
||||
sourceObjects,
|
||||
selectionObject
|
||||
);
|
||||
await this._rasterizeOriginalLayerWithCutout(sourceLayer, sourceObjects, selectionObject);
|
||||
|
||||
// 步骤3: 创建图像图层命令
|
||||
const createImageLayerCmd = new CreateImageLayerCommand({
|
||||
@@ -246,10 +236,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
console.log(`✅ 子命令撤销成功: ${command.constructor.name}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`❌ 子命令撤销失败: ${command.constructor.name}`,
|
||||
error
|
||||
);
|
||||
console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error);
|
||||
// 子命令撤销失败不中断整个撤销过程
|
||||
}
|
||||
}
|
||||
@@ -313,17 +300,14 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
await this._restoreObjectsFromBackup(sourceLayer);
|
||||
} else {
|
||||
// 备用方案:恢复原始的fabricObjects数组
|
||||
sourceLayer.fabricObjects =
|
||||
this.originalLayerBackup.fabricObjects || [];
|
||||
sourceLayer.fabricObjects = this.originalLayerBackup.fabricObjects || [];
|
||||
|
||||
if (sourceLayer.fabricObjects.length > 0) {
|
||||
await this._restoreLayerObjects(sourceLayer);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`✅ 原图层状态恢复完成,恢复了 ${sourceLayer.fabricObjects.length} 个对象`
|
||||
);
|
||||
console.log(`✅ 原图层状态恢复完成,恢复了 ${sourceLayer.fabricObjects.length} 个对象`);
|
||||
} catch (error) {
|
||||
console.error("恢复原图层状态失败:", error);
|
||||
throw error;
|
||||
@@ -337,78 +321,68 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
*/
|
||||
async _restoreObjectsFromBackup(layer) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (
|
||||
!this.originalLayerObjectsData ||
|
||||
this.originalLayerObjectsData.length === 0
|
||||
) {
|
||||
if (!this.originalLayerObjectsData || this.originalLayerObjectsData.length === 0) {
|
||||
console.warn("没有对象备份数据");
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(
|
||||
`开始从备份恢复 ${this.originalLayerObjectsData.length} 个对象...`
|
||||
);
|
||||
console.log(`开始从备份恢复 ${this.originalLayerObjectsData.length} 个对象...`);
|
||||
|
||||
// 使用fabric.util.enlivenObjects重建对象
|
||||
fabric.util.enlivenObjects(
|
||||
this.originalLayerObjectsData,
|
||||
(restoredObjects) => {
|
||||
try {
|
||||
let successCount = 0;
|
||||
fabric.util.enlivenObjects(this.originalLayerObjectsData, (restoredObjects) => {
|
||||
try {
|
||||
let successCount = 0;
|
||||
|
||||
restoredObjects.forEach((obj, index) => {
|
||||
if (obj) {
|
||||
// 确保对象有正确的属性
|
||||
obj.set({
|
||||
layerId: layer.id,
|
||||
layerName: layer.name,
|
||||
selectable: true,
|
||||
evented: true,
|
||||
visible: true,
|
||||
});
|
||||
restoredObjects.forEach((obj, index) => {
|
||||
if (obj) {
|
||||
// 确保对象有正确的属性
|
||||
obj.set({
|
||||
layerId: layer.id,
|
||||
layerName: layer.name,
|
||||
selectable: true,
|
||||
evented: true,
|
||||
visible: true,
|
||||
});
|
||||
|
||||
// 添加到画布
|
||||
this.canvas.add(obj);
|
||||
// 添加到画布
|
||||
this.canvas.add(obj);
|
||||
|
||||
// 添加到图层的fabricObjects数组
|
||||
layer.fabricObjects.push(
|
||||
obj.toObject([
|
||||
"id",
|
||||
"layerId",
|
||||
"layerName",
|
||||
"parentId",
|
||||
"selectable",
|
||||
"evented",
|
||||
"visible",
|
||||
])
|
||||
);
|
||||
// 添加到图层的fabricObjects数组
|
||||
layer.fabricObjects.push(
|
||||
obj.toObject([
|
||||
"id",
|
||||
"layerId",
|
||||
"layerName",
|
||||
"parentId",
|
||||
"selectable",
|
||||
"evented",
|
||||
"visible",
|
||||
])
|
||||
);
|
||||
|
||||
successCount++;
|
||||
console.log(
|
||||
`恢复对象 ${index + 1}/${restoredObjects.length}: ${
|
||||
obj.id || obj.type
|
||||
}`
|
||||
);
|
||||
} else {
|
||||
console.warn(`对象 ${index + 1} 恢复失败`);
|
||||
}
|
||||
});
|
||||
successCount++;
|
||||
console.log(
|
||||
`恢复对象 ${index + 1}/${restoredObjects.length}: ${obj.id || obj.type}`
|
||||
);
|
||||
} else {
|
||||
console.warn(`对象 ${index + 1} 恢复失败`);
|
||||
}
|
||||
});
|
||||
|
||||
// 重新渲染画布
|
||||
this.canvas.renderAll();
|
||||
// 重新渲染画布
|
||||
this.canvas.renderAll();
|
||||
|
||||
console.log(
|
||||
`✅ 成功恢复了 ${successCount}/${this.originalLayerObjectsData.length} 个对象`
|
||||
);
|
||||
resolve();
|
||||
} catch (error) {
|
||||
console.error("处理恢复的对象时出错:", error);
|
||||
reject(error);
|
||||
}
|
||||
console.log(
|
||||
`✅ 成功恢复了 ${successCount}/${this.originalLayerObjectsData.length} 个对象`
|
||||
);
|
||||
resolve();
|
||||
} catch (error) {
|
||||
console.error("处理恢复的对象时出错:", error);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("恢复对象时出错:", error);
|
||||
reject(error);
|
||||
@@ -474,11 +448,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
* @returns {fabric.Image} 抠图结果的fabric图像对象
|
||||
* @private
|
||||
*/
|
||||
async _performCutoutWithRasterized(
|
||||
sourceObjects,
|
||||
selectionObject,
|
||||
selectionBounds
|
||||
) {
|
||||
async _performCutoutWithRasterized(sourceObjects, selectionObject, selectionBounds) {
|
||||
try {
|
||||
console.log("=== 开始使用createRasterizedImage执行剪切抠图 ===");
|
||||
console.log(`源对象数量: ${sourceObjects.length}`);
|
||||
@@ -488,10 +458,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
let scaleFactor = this.baseResolutionScale;
|
||||
if (this.highResolutionEnabled) {
|
||||
const currentZoom = this.canvas.getZoom?.() || 1;
|
||||
scaleFactor = Math.max(
|
||||
scaleFactor || this.canvas?.getRetinaScaling?.(),
|
||||
currentZoom
|
||||
);
|
||||
scaleFactor = Math.max(scaleFactor || this.canvas?.getRetinaScaling?.(), currentZoom);
|
||||
scaleFactor = Math.min(scaleFactor, 3);
|
||||
}
|
||||
|
||||
@@ -535,15 +502,10 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
// 递归获取图层及其子图层的所有对象
|
||||
const collectLayerObjects = (currentLayer) => {
|
||||
// 处理图层的fabricObjects
|
||||
if (
|
||||
currentLayer.fabricObjects &&
|
||||
Array.isArray(currentLayer.fabricObjects)
|
||||
) {
|
||||
if (currentLayer.fabricObjects && Array.isArray(currentLayer.fabricObjects)) {
|
||||
currentLayer.fabricObjects.forEach((fabricObj) => {
|
||||
if (fabricObj && fabricObj.id) {
|
||||
const realObject = canvasObjects.find(
|
||||
(canvasObj) => canvasObj.id === fabricObj.id
|
||||
);
|
||||
const realObject = canvasObjects.find((canvasObj) => canvasObj.id === fabricObj.id);
|
||||
if (realObject && realObject.visible !== false) {
|
||||
objects.push(realObject);
|
||||
}
|
||||
@@ -649,17 +611,14 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
}
|
||||
});
|
||||
} else if (objectType === "polygon") {
|
||||
fabric.Polygon.fromObject(
|
||||
this.serializedSelectionObject,
|
||||
(polygon) => {
|
||||
if (polygon) {
|
||||
console.log("多边形选区对象反序列化成功");
|
||||
resolve(polygon);
|
||||
} else {
|
||||
reject(new Error("多边形选区对象反序列化失败"));
|
||||
}
|
||||
fabric.Polygon.fromObject(this.serializedSelectionObject, (polygon) => {
|
||||
if (polygon) {
|
||||
console.log("多边形选区对象反序列化成功");
|
||||
resolve(polygon);
|
||||
} else {
|
||||
reject(new Error("多边形选区对象反序列化失败"));
|
||||
}
|
||||
);
|
||||
});
|
||||
} else if (objectType === "rect") {
|
||||
fabric.Rect.fromObject(this.serializedSelectionObject, (rect) => {
|
||||
if (rect) {
|
||||
@@ -670,30 +629,24 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
}
|
||||
});
|
||||
} else if (objectType === "ellipse" || objectType === "circle") {
|
||||
fabric.Ellipse.fromObject(
|
||||
this.serializedSelectionObject,
|
||||
(ellipse) => {
|
||||
if (ellipse) {
|
||||
console.log("椭圆选区对象反序列化成功");
|
||||
resolve(ellipse);
|
||||
} else {
|
||||
reject(new Error("椭圆选区对象反序列化失败"));
|
||||
}
|
||||
fabric.Ellipse.fromObject(this.serializedSelectionObject, (ellipse) => {
|
||||
if (ellipse) {
|
||||
console.log("椭圆选区对象反序列化成功");
|
||||
resolve(ellipse);
|
||||
} else {
|
||||
reject(new Error("椭圆选区对象反序列化失败"));
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// 通用对象反序列化
|
||||
fabric.util.enlivenObjects(
|
||||
[this.serializedSelectionObject],
|
||||
(objects) => {
|
||||
if (objects && objects.length > 0) {
|
||||
console.log("通用选区对象反序列化成功");
|
||||
resolve(objects[0]);
|
||||
} else {
|
||||
reject(new Error("通用选区对象反序列化失败"));
|
||||
}
|
||||
fabric.util.enlivenObjects([this.serializedSelectionObject], (objects) => {
|
||||
if (objects && objects.length > 0) {
|
||||
console.log("通用选区对象反序列化成功");
|
||||
resolve(objects[0]);
|
||||
} else {
|
||||
reject(new Error("通用选区对象反序列化失败"));
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -761,9 +714,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
|
||||
this.originalLayerRasterized = false; // 标记原图层是否已栅格化
|
||||
|
||||
console.log(
|
||||
`✅ 原图层状态已备份,对象数量: ${this.originalLayerObjectsData.length}`
|
||||
);
|
||||
console.log(`✅ 原图层状态已备份,对象数量: ${this.originalLayerObjectsData.length}`);
|
||||
} catch (error) {
|
||||
console.error("备份原图层状态失败:", error);
|
||||
throw error;
|
||||
@@ -777,11 +728,7 @@ export class CutSelectionToNewLayerCommand extends CompositeCommand {
|
||||
* @param {Object} selectionObject 选区对象
|
||||
* @private
|
||||
*/
|
||||
async _rasterizeOriginalLayerWithCutout(
|
||||
sourceLayer,
|
||||
sourceObjects,
|
||||
selectionObject
|
||||
) {
|
||||
async _rasterizeOriginalLayerWithCutout(sourceLayer, sourceObjects, selectionObject) {
|
||||
try {
|
||||
console.log("=== 开始对原图层进行栅格化处理,移除选区内容 ===");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user