feat: 裁剪组裁剪跟随选择组移动
This commit is contained in:
@@ -1,16 +1,13 @@
|
||||
import { Command } from "./Command";
|
||||
import {
|
||||
createLayer,
|
||||
findLayerRecursively,
|
||||
LayerType,
|
||||
OperationType,
|
||||
} from "../utils/layerHelper";
|
||||
import { createLayer, findLayerRecursively, LayerType, OperationType } from "../utils/layerHelper";
|
||||
import { createStaticCanvas } from "../utils/canvasFactory";
|
||||
import { AddObjectToLayerCommand } from "./ObjectLayerCommands";
|
||||
import { ToolCommand } from "./ToolCommands";
|
||||
import {
|
||||
findObjectById,
|
||||
generateId,
|
||||
getObjectZIndex,
|
||||
insertObjectAtZIndex,
|
||||
objectIsInCanvas,
|
||||
optimizeCanvasRendering,
|
||||
removeCanvasObjectByObject,
|
||||
@@ -112,15 +109,11 @@ export class AddLayerCommand extends Command {
|
||||
parentLayer.children = parentLayer.children || [];
|
||||
parentLayer.children.splice(insertIndex, 0, newLayer);
|
||||
|
||||
console.log(
|
||||
`新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})`
|
||||
);
|
||||
console.log(`新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})`);
|
||||
} else {
|
||||
// 当前激活图层是一级图层
|
||||
// 在一级图层中,插入到激活图层之上
|
||||
const activeLayerIndex = layers.findIndex(
|
||||
(layer) => layer.id === currentActiveLayerId
|
||||
);
|
||||
const activeLayerIndex = layers.findIndex((layer) => layer.id === currentActiveLayerId);
|
||||
insertIndex = Math.max(0, activeLayerIndex);
|
||||
layers.splice(insertIndex, 0, newLayer);
|
||||
|
||||
@@ -273,9 +266,7 @@ export class PasteLayerCommand extends Command {
|
||||
try {
|
||||
objects.forEach((obj) => {
|
||||
// 生成新的对象ID
|
||||
const newObjId = `obj_${Date.now()}_${Math.floor(
|
||||
Math.random() * 1000
|
||||
)}`;
|
||||
const newObjId = `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
obj.id = newObjId;
|
||||
obj.layerId = this.newLayerId;
|
||||
obj.layerName = this.newLayer.name;
|
||||
@@ -337,9 +328,7 @@ export class PasteLayerCommand extends Command {
|
||||
if (!this.newLayer || !this.newLayerId) return;
|
||||
|
||||
// 从图层列表删除该图层
|
||||
const index = this.layers.value.findIndex(
|
||||
(layer) => layer.id === this.newLayerId
|
||||
);
|
||||
const index = this.layers.value.findIndex((layer) => layer.id === this.newLayerId);
|
||||
if (index !== -1) {
|
||||
this.layers.value.splice(index, 1);
|
||||
}
|
||||
@@ -405,9 +394,7 @@ export class RemoveLayerCommand extends Command {
|
||||
this.activeLayerId = options.activeLayerId;
|
||||
|
||||
// 查找要删除的图层
|
||||
this.layerIndex = this.layers.value.findIndex(
|
||||
(layer) => layer.id === this.layerId
|
||||
);
|
||||
this.layerIndex = this.layers.value.findIndex((layer) => layer.id === this.layerId);
|
||||
this.removedLayer = this.layers.value[this.layerIndex];
|
||||
this.isActiveLayer = this.layerId === this.activeLayerId.value;
|
||||
|
||||
@@ -474,9 +461,7 @@ export class RemoveLayerCommand extends Command {
|
||||
// 如果删除的是当前活动图层,需要更新活动图层
|
||||
if (this.isActiveLayer) {
|
||||
// 查找最近的非背景层作为新的活动图层
|
||||
const newActiveLayer = this.layers.value.find(
|
||||
(layer) => !layer.isBackground
|
||||
);
|
||||
const newActiveLayer = this.layers.value.find((layer) => !layer.isBackground);
|
||||
if (newActiveLayer) {
|
||||
this.activeLayerId.value = newActiveLayer.id;
|
||||
} else {
|
||||
@@ -554,30 +539,22 @@ export class MoveLayerCommand extends Command {
|
||||
|
||||
this.parentLayer = null; // 父图层
|
||||
|
||||
const { layer, parent } = findLayerRecursively(
|
||||
this.layers.value,
|
||||
this.layerId
|
||||
);
|
||||
const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId);
|
||||
|
||||
// 如果parent 有值 或者 layer 上有parentId 则视为子图层的置顶
|
||||
if (parent?.id) {
|
||||
// 查找子图层索引
|
||||
this.layerIndex = parent?.children?.findIndex(
|
||||
(layer) => layer.id === this.layerId
|
||||
);
|
||||
this.layerIndex = parent?.children?.findIndex((layer) => layer.id === this.layerId);
|
||||
this.parentLayer = parent;
|
||||
} else {
|
||||
// 查找图层索引
|
||||
this.layerIndex = this.layers.value.findIndex(
|
||||
(layer) => layer.id === this.layerId
|
||||
);
|
||||
this.layerIndex = this.layers.value.findIndex((layer) => layer.id === this.layerId);
|
||||
}
|
||||
|
||||
this.layer = layer;
|
||||
this.originalIndex = this.layerIndex;
|
||||
// 目标位置
|
||||
this.targetIndex =
|
||||
options.direction === "up" ? this.layerIndex - 1 : this.layerIndex + 1;
|
||||
this.targetIndex = options.direction === "up" ? this.layerIndex - 1 : this.layerIndex + 1;
|
||||
}
|
||||
|
||||
async execute() {
|
||||
@@ -668,9 +645,7 @@ export class ToggleLayerVisibilityCommand extends Command {
|
||||
|
||||
// 更新画布上图层对象的可见性
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.visible = this.layer.visible;
|
||||
});
|
||||
@@ -711,10 +686,7 @@ export class ToggleChildLayerVisibilityCommand extends Command {
|
||||
this.layerManager = options.layerManager;
|
||||
|
||||
// 查找父图层和子图层
|
||||
const { layer, parent } = findLayerRecursively(
|
||||
this.layers.value,
|
||||
this.layerId
|
||||
);
|
||||
const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId);
|
||||
this.parentLayer = parent;
|
||||
this.childLayer = layer;
|
||||
|
||||
@@ -731,9 +703,7 @@ export class ToggleChildLayerVisibilityCommand extends Command {
|
||||
|
||||
// 更新画布上图层对象的可见性
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.visible = this.childLayer.visible;
|
||||
@@ -792,9 +762,7 @@ export class RenameLayerCommand extends Command {
|
||||
|
||||
// 更新图层对象上的图层名称
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.layerName = this.newName;
|
||||
@@ -811,9 +779,7 @@ export class RenameLayerCommand extends Command {
|
||||
|
||||
// 恢复图层对象上的图层名称
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.layerName = this.oldName;
|
||||
@@ -848,10 +814,7 @@ export class LayerLockCommand extends Command {
|
||||
|
||||
// 查找图层(包括子图层)
|
||||
// 查找图层
|
||||
const { layer, parent } = findLayerRecursively(
|
||||
this.layers.value,
|
||||
this.layerId
|
||||
);
|
||||
const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId);
|
||||
this.layer = layer;
|
||||
this.parentLayer = parent || null; // 父图层
|
||||
this.oldLocked = this.layer ? this.layer.locked : null;
|
||||
@@ -869,11 +832,7 @@ export class LayerLockCommand extends Command {
|
||||
layer.locked = locked;
|
||||
|
||||
// 如果是组图层,递归更新所有子图层
|
||||
if (
|
||||
layer.type === "group" &&
|
||||
layer.children &&
|
||||
Array.isArray(layer.children)
|
||||
) {
|
||||
if (layer.type === "group" && layer.children && Array.isArray(layer.children)) {
|
||||
layer.children.forEach((child) => {
|
||||
this._updateLayerLockState(child, locked);
|
||||
});
|
||||
@@ -895,11 +854,7 @@ export class LayerLockCommand extends Command {
|
||||
// 更新画布上对象的可选择状态
|
||||
await this.layerManager?.updateLayersObjectsInteractivity();
|
||||
|
||||
console.log(
|
||||
`${newLocked ? "锁定" : "解锁"}图层: ${this.layer.name} (ID: ${
|
||||
this.layerId
|
||||
})`
|
||||
);
|
||||
console.log(`${newLocked ? "锁定" : "解锁"}图层: ${this.layer.name} (ID: ${this.layerId})`);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -911,9 +866,7 @@ export class LayerLockCommand extends Command {
|
||||
// 更新画布上对象的可选择状态
|
||||
await this.layerManager?.updateLayersObjectsInteractivity();
|
||||
|
||||
console.log(
|
||||
`恢复图层锁定状态: ${this.layer.name} (锁定: ${this.oldLocked})`
|
||||
);
|
||||
console.log(`恢复图层锁定状态: ${this.layer.name} (锁定: ${this.oldLocked})`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -961,9 +914,7 @@ export class SetLayerOpacityCommand extends Command {
|
||||
|
||||
// 更新画布上对象的不透明度
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.opacity = this.opacity;
|
||||
@@ -982,9 +933,7 @@ export class SetLayerOpacityCommand extends Command {
|
||||
|
||||
// 更新画布上对象的不透明度
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.opacity = this.oldOpacity;
|
||||
@@ -1038,9 +987,7 @@ export class SetLayerBlendModeCommand extends Command {
|
||||
|
||||
// 更新画布上对象的混合模式
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.globalCompositeOperation = this.blendMode;
|
||||
@@ -1059,9 +1006,7 @@ export class SetLayerBlendModeCommand extends Command {
|
||||
|
||||
// 更新画布上对象的混合模式
|
||||
if (this.canvas) {
|
||||
const layerObjects = this.canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.layerId === this.layerId);
|
||||
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||
|
||||
layerObjects.forEach((obj) => {
|
||||
obj.globalCompositeOperation = this.oldBlendMode;
|
||||
@@ -1101,17 +1046,11 @@ export class MergeLayersCommand extends Command {
|
||||
// 备份原图层
|
||||
this.originalLayers = [...this.layers.value];
|
||||
// 新图层ID
|
||||
this.newLayerId = `merged_layer_${Date.now()}_${Math.floor(
|
||||
Math.random() * 1000
|
||||
)}`;
|
||||
this.newLayerId = `merged_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
}
|
||||
|
||||
execute() {
|
||||
if (
|
||||
!this.layerIds ||
|
||||
!Array.isArray(this.layerIds) ||
|
||||
this.layerIds.length < 2
|
||||
) {
|
||||
if (!this.layerIds || !Array.isArray(this.layerIds) || this.layerIds.length < 2) {
|
||||
console.error("合并图层至少需要两个图层");
|
||||
return null;
|
||||
}
|
||||
@@ -1132,6 +1071,14 @@ export class MergeLayersCommand extends Command {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 查找所有要组合的图层
|
||||
const layersToGroup = this.layerIds
|
||||
.map((id) => {
|
||||
const tempLayer = this.layers.value.find((layer) => layer.id === id); // 需要给子图层加上parentId
|
||||
return tempLayer ? { ...tempLayer, parentId: this.groupId } : false;
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
const topLayerIndex = Math.min(
|
||||
...layersToGroup.map((layer) =>
|
||||
this.layers.value.findIndex((fLayer) => fLayer.id === layer.id)
|
||||
@@ -1164,9 +1111,7 @@ export class MergeLayersCommand extends Command {
|
||||
});
|
||||
|
||||
// 移除原图层
|
||||
this.layers.value = this.layers.value.filter(
|
||||
(layer) => !this.layerIds.includes(layer.id)
|
||||
);
|
||||
this.layers.value = this.layers.value.filter((layer) => !this.layerIds.includes(layer.id));
|
||||
|
||||
// 插入新图层
|
||||
this.layers.value.splice(topLayerIndex, 0, mergedLayer);
|
||||
@@ -1227,18 +1172,13 @@ export class GroupLayersCommand extends Command {
|
||||
this.originalLayers = [...this.layers.value];
|
||||
// 新组ID
|
||||
this.groupId =
|
||||
generateId("group_layer_") ||
|
||||
`group_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
generateId("group_layer_") || `group_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
|
||||
this.originalActiveLayerId = this.activeLayerId.value; // 备份原活动图层ID
|
||||
}
|
||||
|
||||
async execute() {
|
||||
if (
|
||||
!this.layerIds ||
|
||||
!Array.isArray(this.layerIds) ||
|
||||
this.layerIds.length < 2
|
||||
) {
|
||||
if (!this.layerIds || !Array.isArray(this.layerIds) || this.layerIds.length < 2) {
|
||||
console.error("组合图层至少需要两个图层");
|
||||
return null;
|
||||
}
|
||||
@@ -1282,9 +1222,7 @@ export class GroupLayersCommand extends Command {
|
||||
});
|
||||
|
||||
// 移除原图层
|
||||
this.layers.value = this.layers.value.filter(
|
||||
(layer) => !this.layerIds.includes(layer.id)
|
||||
);
|
||||
this.layers.value = this.layers.value.filter((layer) => !this.layerIds.includes(layer.id));
|
||||
|
||||
// 插入新组图层
|
||||
this.layers.value.splice(topLayerIndex, 0, groupLayer);
|
||||
@@ -1338,9 +1276,7 @@ export class UngroupLayersCommand extends Command {
|
||||
|
||||
async execute() {
|
||||
// 查找组图层
|
||||
const groupIndex = this.layers.value.findIndex(
|
||||
(layer) => layer.id === this.groupId
|
||||
);
|
||||
const groupIndex = this.layers.value.findIndex((layer) => layer.id === this.groupId);
|
||||
|
||||
if (groupIndex === -1) {
|
||||
console.error(`找不到组图层 ${this.groupId}`);
|
||||
@@ -1361,11 +1297,11 @@ export class UngroupLayersCommand extends Command {
|
||||
this.layers.value.splice(
|
||||
groupIndex,
|
||||
1,
|
||||
...groupLayer.children?.map((child) => {
|
||||
...(groupLayer?.children?.map((child) => {
|
||||
// 为子图层添加parentId
|
||||
delete child.parentId; // 删除parentId属性
|
||||
return { ...child };
|
||||
})
|
||||
}) || {})
|
||||
);
|
||||
// 更新当前活动图层为第一个子图层
|
||||
if (this.childLayerIds.length > 0 && this.activeLayerId) {
|
||||
@@ -1411,18 +1347,14 @@ export class MergeLayerObjectsCommand extends Command {
|
||||
// 备份原始对象,用于撤销
|
||||
if (this.activeLayer && Array.isArray(this.activeLayer.fabricObjects)) {
|
||||
this.originalObjects =
|
||||
this.canvas
|
||||
?.getObjects()
|
||||
?.filter((fItem) => fItem.layerId === this.activeLayer.id) || [];
|
||||
this.canvas?.getObjects()?.filter((fItem) => fItem.layerId === this.activeLayer.id) || [];
|
||||
} else {
|
||||
this.originalObjects = [];
|
||||
}
|
||||
|
||||
// 新合并图像对象
|
||||
this.mergedImage = null;
|
||||
this.newImageId = `merged_image_${Date.now()}_${Math.floor(
|
||||
Math.random() * 1000
|
||||
)}`;
|
||||
this.newImageId = `merged_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
}
|
||||
|
||||
async execute() {
|
||||
@@ -1458,10 +1390,7 @@ export class MergeLayerObjectsCommand extends Command {
|
||||
|
||||
// 异步处理图像合并
|
||||
try {
|
||||
const mergedImage = await this._createMergedImageAsync(
|
||||
objectsToMerge,
|
||||
bounds
|
||||
);
|
||||
const mergedImage = await this._createMergedImageAsync(objectsToMerge, bounds);
|
||||
this._setupMergedImage(mergedImage, bounds);
|
||||
this._replaceObjects(mergedImage);
|
||||
|
||||
@@ -1611,9 +1540,7 @@ export class MergeLayerObjectsCommand extends Command {
|
||||
});
|
||||
|
||||
tempCanvas.add(clonedObj);
|
||||
console.log(
|
||||
`添加对象 ${index + 1}/${objects.length}: ${obj.type || "unknown"}`
|
||||
);
|
||||
console.log(`添加对象 ${index + 1}/${objects.length}: ${obj.type || "unknown"}`);
|
||||
} catch (error) {
|
||||
console.error(`添加对象到临时画布时发生错误:`, error);
|
||||
}
|
||||
@@ -1672,10 +1599,7 @@ export class MergeLayerObjectsCommand extends Command {
|
||||
});
|
||||
|
||||
// 如果有新的图像对象,也要移除
|
||||
if (
|
||||
this.fabricImage &&
|
||||
this.canvas.getObjects().includes(this.fabricImage)
|
||||
) {
|
||||
if (this.fabricImage && this.canvas.getObjects().includes(this.fabricImage)) {
|
||||
this.canvas.remove(this.fabricImage);
|
||||
}
|
||||
|
||||
@@ -1691,9 +1615,7 @@ export class MergeLayerObjectsCommand extends Command {
|
||||
// 更新缩略图
|
||||
if (this.canvas.thumbnailManager) {
|
||||
setTimeout(() => {
|
||||
this.canvas.thumbnailManager.generateLayerThumbnail(
|
||||
this.activeLayer.id
|
||||
);
|
||||
this.canvas.thumbnailManager.generateLayerThumbnail(this.activeLayer.id);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
@@ -1737,9 +1659,7 @@ export class MergeLayerObjectsCommand extends Command {
|
||||
// 更新缩略图
|
||||
if (this.canvas.thumbnailManager) {
|
||||
setTimeout(() => {
|
||||
this.canvas.thumbnailManager.generateLayerThumbnail(
|
||||
this.activeLayer.id
|
||||
);
|
||||
this.canvas.thumbnailManager.generateLayerThumbnail(this.activeLayer.id);
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
@@ -1827,8 +1747,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
this.existingGroupId = null;
|
||||
this.groupObjectId = null;
|
||||
this.newGroupId =
|
||||
generateId("group") ||
|
||||
`group_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
generateId("group") || `group_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
this.wasGroupCreated = false;
|
||||
|
||||
// 保存原始位置信息
|
||||
@@ -1889,10 +1808,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
const newObjectsToAdd = [];
|
||||
if (this.fabricImage) {
|
||||
// 如果是重做,恢复新对象的原始位置
|
||||
if (
|
||||
!this.isFirstExecution &&
|
||||
this.newObjectPositions.has(this.fabricImage.id)
|
||||
) {
|
||||
if (!this.isFirstExecution && this.newObjectPositions.has(this.fabricImage.id)) {
|
||||
const savedPosition = this.newObjectPositions.get(this.fabricImage.id);
|
||||
this.fabricImage.set({
|
||||
left: savedPosition.left,
|
||||
@@ -1905,9 +1821,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
flipX: savedPosition.flipX,
|
||||
flipY: savedPosition.flipY,
|
||||
});
|
||||
console.log(
|
||||
`🔄 重做时恢复新对象位置: (${savedPosition.left}, ${savedPosition.top})`
|
||||
);
|
||||
console.log(`🔄 重做时恢复新对象位置: (${savedPosition.left}, ${savedPosition.top})`);
|
||||
}
|
||||
|
||||
newObjectsToAdd.push(this.fabricImage);
|
||||
@@ -1960,9 +1874,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
|
||||
if (!this.existingGroupId) {
|
||||
const groupObjects =
|
||||
this.activeLayer.fabricObjects.find(
|
||||
(obj) => obj && obj.type === "group"
|
||||
) || null;
|
||||
this.activeLayer.fabricObjects.find((obj) => obj && obj.type === "group") || null;
|
||||
|
||||
this.existingGroupId = groupObjects?.id || null;
|
||||
}
|
||||
@@ -2062,9 +1974,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
|
||||
// 更新图层的对象列表
|
||||
// this.activeLayer.fabricObjects = [groupObject];
|
||||
this.activeLayer.fabricObjects = [
|
||||
groupObject.toObject(["id", "layerId", "layerName"]),
|
||||
];
|
||||
this.activeLayer.fabricObjects = [groupObject.toObject(["id", "layerId", "layerName"])];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2150,10 +2060,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
restorePosition = { ...originalPosition };
|
||||
} else {
|
||||
// 计算对象在画布中的当前绝对位置
|
||||
restorePosition = this._calculateObjectAbsolutePosition(
|
||||
obj,
|
||||
groupObject
|
||||
);
|
||||
restorePosition = this._calculateObjectAbsolutePosition(obj, groupObject);
|
||||
}
|
||||
|
||||
objectsToRestore.push({
|
||||
@@ -2208,9 +2115,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
restoredObjects.push(obj);
|
||||
|
||||
console.log(
|
||||
`✅ 恢复原始对象 ${obj.id || obj.type} 到位置 (${position.left}, ${
|
||||
position.top
|
||||
})`
|
||||
`✅ 恢复原始对象 ${obj.id || obj.type} 到位置 (${position.left}, ${position.top})`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`恢复对象 ${obj.id || obj.type} 时发生错误:`, error);
|
||||
@@ -2270,10 +2175,7 @@ export class LayerObjectsToGroupCommand extends Command {
|
||||
const objectPoint = new fabric.Point(obj.left || 0, obj.top || 0);
|
||||
|
||||
// 应用组的变换矩阵计算绝对位置
|
||||
const absolutePoint = fabric.util.transformPoint(
|
||||
objectPoint,
|
||||
groupTransform
|
||||
);
|
||||
const absolutePoint = fabric.util.transformPoint(objectPoint, groupTransform);
|
||||
|
||||
// 计算缩放比例
|
||||
const totalScaleX = (group.scaleX || 1) * (obj.scaleX || 1);
|
||||
@@ -2441,8 +2343,7 @@ export class CreateImageLayerCommand extends Command {
|
||||
|
||||
// 存储执行过程中的结果
|
||||
this.newLayerId =
|
||||
generateId("layer_image_") ||
|
||||
`layer_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
generateId("layer_image_") || `layer_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
this.commands = [];
|
||||
this.executedCommands = [];
|
||||
}
|
||||
@@ -2457,8 +2358,7 @@ export class CreateImageLayerCommand extends Command {
|
||||
this.executedCommands = [];
|
||||
|
||||
// 生成图层名称
|
||||
const fileName =
|
||||
this.layerName || `图片 ${new Date().toLocaleTimeString()}`;
|
||||
const fileName = this.layerName || `图片 ${new Date().toLocaleTimeString()}`;
|
||||
|
||||
this.fabricImage.set({
|
||||
id: this.imageId,
|
||||
@@ -2529,9 +2429,7 @@ export class CreateImageLayerCommand extends Command {
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`↩️ 开始撤销创建图片图层操作,共 ${this.executedCommands.length} 个子命令`
|
||||
);
|
||||
console.log(`↩️ 开始撤销创建图片图层操作,共 ${this.executedCommands.length} 个子命令`);
|
||||
|
||||
try {
|
||||
// 逆序撤销已执行的命令
|
||||
@@ -2547,10 +2445,7 @@ export class CreateImageLayerCommand extends Command {
|
||||
}
|
||||
console.log(`✅ 子命令撤销成功: ${command.constructor.name}`);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`❌ 子命令撤销失败: ${command.constructor.name}`,
|
||||
error
|
||||
);
|
||||
console.error(`❌ 子命令撤销失败: ${command.constructor.name}`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2583,10 +2478,7 @@ export class CreateImageLayerCommand extends Command {
|
||||
}
|
||||
console.log(`✅ 子命令回滚成功: ${command.constructor.name}`);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`❌ 子命令回滚失败: ${command.constructor.name}`,
|
||||
error
|
||||
);
|
||||
console.error(`❌ 子命令回滚失败: ${command.constructor.name}`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2721,9 +2613,7 @@ export class ReorderChildLayersCommand extends Command {
|
||||
|
||||
async execute() {
|
||||
// 查找父图层
|
||||
const parentLayer = this.layers.value.find(
|
||||
(layer) => layer.id === this.parentId
|
||||
);
|
||||
const parentLayer = this.layers.value.find((layer) => layer.id === this.parentId);
|
||||
if (!parentLayer) return false;
|
||||
|
||||
// 获取子图层
|
||||
@@ -2873,15 +2763,11 @@ export class CutLayerCommand extends Command {
|
||||
|
||||
// 生成新图层ID和名称
|
||||
this.newLayerId =
|
||||
generateId("layer_") ||
|
||||
`layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
generateId("layer_") || `layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
}
|
||||
|
||||
async execute() {
|
||||
const { layer, parent } = findLayerRecursively(
|
||||
this.layers.value,
|
||||
this.layerId
|
||||
);
|
||||
const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId);
|
||||
const sourceLayer = layer;
|
||||
const parentLayer = parent;
|
||||
|
||||
@@ -2908,9 +2794,7 @@ export class CutLayerCommand extends Command {
|
||||
blendMode: sourceLayer.blendMode,
|
||||
fabricObjects: [],
|
||||
children: sourceLayer.children ? [...sourceLayer.children] : [],
|
||||
layerProperties: sourceLayer.layerProperties
|
||||
? { ...sourceLayer.layerProperties }
|
||||
: {},
|
||||
layerProperties: sourceLayer.layerProperties ? { ...sourceLayer.layerProperties } : {},
|
||||
metadata: sourceLayer.metadata ? { ...sourceLayer.metadata } : {},
|
||||
parentId: parentLayer ? parentLayer.id : undefined, // 保持父图层关系
|
||||
});
|
||||
@@ -2920,11 +2804,8 @@ export class CutLayerCommand extends Command {
|
||||
|
||||
if (parentLayer) {
|
||||
// 处理子图层:在父图层的children数组中插入
|
||||
const sourceChildIndex = parentLayer.children.findIndex(
|
||||
(child) => child.id === this.layerId
|
||||
);
|
||||
insertIndex =
|
||||
this.insertIndex !== null ? this.insertIndex : sourceChildIndex + 1;
|
||||
const sourceChildIndex = parentLayer.children.findIndex((child) => child.id === this.layerId);
|
||||
insertIndex = this.insertIndex !== null ? this.insertIndex : sourceChildIndex + 1;
|
||||
|
||||
// 插入到父图层的children数组中
|
||||
parentLayer.children.splice(insertIndex, 0, this.newLayer);
|
||||
@@ -2933,11 +2814,8 @@ export class CutLayerCommand extends Command {
|
||||
this.childInsertIndex = insertIndex;
|
||||
} else {
|
||||
// 处理主图层:在主图层数组中插入
|
||||
const sourceIndex = this.layers.value.findIndex(
|
||||
(l) => l.id === this.layerId
|
||||
);
|
||||
insertIndex =
|
||||
this.insertIndex !== null ? this.insertIndex : sourceIndex + 1;
|
||||
const sourceIndex = this.layers.value.findIndex((l) => l.id === this.layerId);
|
||||
insertIndex = this.insertIndex !== null ? this.insertIndex : sourceIndex + 1;
|
||||
|
||||
// 插入到主图层数组中
|
||||
this.layers.value.splice(insertIndex, 0, this.newLayer);
|
||||
@@ -2956,9 +2834,7 @@ export class CutLayerCommand extends Command {
|
||||
// 重新渲染画布
|
||||
await this.layerManager?.updateLayersObjectsInteractivity(false);
|
||||
|
||||
console.log(
|
||||
`已复制图层:${newName} ${this.isChildLayer ? "(子图层)" : "(主图层)"}`
|
||||
);
|
||||
console.log(`已复制图层:${newName} ${this.isChildLayer ? "(子图层)" : "(主图层)"}`);
|
||||
return this.newLayerId;
|
||||
}
|
||||
|
||||
@@ -2975,9 +2851,7 @@ export class CutLayerCommand extends Command {
|
||||
}
|
||||
} else {
|
||||
// 撤销主图层:从主图层数组中删除
|
||||
const index = this.layers.value.findIndex(
|
||||
(l) => l.id === this.newLayerId
|
||||
);
|
||||
const index = this.layers.value.findIndex((l) => l.id === this.newLayerId);
|
||||
if (index !== -1) {
|
||||
this.layers.value.splice(index, 1);
|
||||
}
|
||||
@@ -3007,9 +2881,7 @@ export class CutLayerCommand extends Command {
|
||||
fabric.util.enlivenObjects(serializedObjects, (objects) => {
|
||||
objects.forEach((obj) => {
|
||||
// 生成新的对象ID
|
||||
const newObjId = `obj_${Date.now()}_${Math.floor(
|
||||
Math.random() * 1000
|
||||
)}`;
|
||||
const newObjId = `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
obj.id = newObjId;
|
||||
obj.layerId = this.newLayerId;
|
||||
obj.layerName = this.newLayer.name;
|
||||
@@ -3066,8 +2938,7 @@ export class CreateAdjustmentLayerCommand extends Command {
|
||||
this.newLayer = null;
|
||||
// 生成新图层ID
|
||||
this.newLayerId =
|
||||
generateId("adj_layer_") ||
|
||||
`adj_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
generateId("adj_layer_") || `adj_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
||||
}
|
||||
|
||||
execute() {
|
||||
@@ -3089,9 +2960,7 @@ export class CreateAdjustmentLayerCommand extends Command {
|
||||
|
||||
// 计算插入位置
|
||||
const insertIndex =
|
||||
this.insertIndex !== null
|
||||
? this.insertIndex
|
||||
: this._getInsertIndexAboveActiveLayer();
|
||||
this.insertIndex !== null ? this.insertIndex : this._getInsertIndexAboveActiveLayer();
|
||||
|
||||
// 插入新图层
|
||||
this.layers.value.splice(insertIndex, 0, this.newLayer);
|
||||
@@ -3155,9 +3024,7 @@ export class ApplyLayerStyleCommand extends Command {
|
||||
return;
|
||||
}
|
||||
this.layer = layer;
|
||||
this.oldStyles = this.layer
|
||||
? { ...(this.layer.layerProperties?.styles || {}) }
|
||||
: {};
|
||||
this.oldStyles = this.layer ? { ...(this.layer.layerProperties?.styles || {}) } : {};
|
||||
}
|
||||
|
||||
execute() {
|
||||
@@ -3296,9 +3163,7 @@ export class LayerClippingMaskCommand extends Command {
|
||||
|
||||
if (this.maskLayerId) {
|
||||
// 创建剪贴蒙版
|
||||
const maskLayer = this.layers.value.find(
|
||||
(l) => l.id === this.maskLayerId
|
||||
);
|
||||
const maskLayer = this.layers.value.find((l) => l.id === this.maskLayerId);
|
||||
if (!maskLayer) {
|
||||
console.error(`蒙版图层 ${this.maskLayerId} 不存在`);
|
||||
return false;
|
||||
@@ -3525,19 +3390,14 @@ export class ChangeFixedImageCommand extends Command {
|
||||
this.retryCount = attempt;
|
||||
|
||||
if (attempt === this.maxRetries) {
|
||||
throw new Error(
|
||||
`图像加载失败,已重试${this.maxRetries}次: ${error.message}`
|
||||
);
|
||||
throw new Error(`图像加载失败,已重试${this.maxRetries}次: ${error.message}`);
|
||||
}
|
||||
|
||||
// 指数退避重试
|
||||
const delay = Math.pow(2, attempt) * 1000;
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
|
||||
console.warn(
|
||||
`图像加载重试 ${attempt + 1}/${this.maxRetries}:`,
|
||||
error.message
|
||||
);
|
||||
console.warn(`图像加载重试 ${attempt + 1}/${this.maxRetries}:`, error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3545,9 +3405,7 @@ export class ChangeFixedImageCommand extends Command {
|
||||
loadImage() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject(
|
||||
new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)
|
||||
);
|
||||
reject(new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`));
|
||||
}, this.timeoutMs);
|
||||
|
||||
fabric.Image.fromURL(
|
||||
@@ -3585,15 +3443,9 @@ export class ChangeFixedImageCommand extends Command {
|
||||
|
||||
// 移除旧对象(如果存在)
|
||||
if (this.previousObjectId) {
|
||||
const { object: oldObject } = findObjectById(
|
||||
this.canvas,
|
||||
this.previousObjectId
|
||||
);
|
||||
const { object: oldObject } = findObjectById(this.canvas, this.previousObjectId);
|
||||
if (oldObject) {
|
||||
const removeSuccess = removeCanvasObjectByObject(
|
||||
this.canvas,
|
||||
oldObject
|
||||
);
|
||||
const removeSuccess = removeCanvasObjectByObject(this.canvas, oldObject);
|
||||
if (!removeSuccess) {
|
||||
console.warn("移除旧对象失败,但继续执行");
|
||||
}
|
||||
@@ -3650,97 +3502,75 @@ export class ChangeFixedImageCommand extends Command {
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fabric.util.enlivenObjects(
|
||||
[this.previousImage.objectData],
|
||||
async (objects) => {
|
||||
try {
|
||||
const restoredImage = objects[0];
|
||||
fabric.util.enlivenObjects([this.previousImage.objectData], async (objects) => {
|
||||
try {
|
||||
const restoredImage = objects[0];
|
||||
|
||||
await optimizeCanvasRendering(this.canvas, async () => {
|
||||
// 移除当前对象
|
||||
if (this.newObjectId) {
|
||||
const { object: currentObject } = findObjectById(
|
||||
this.canvas,
|
||||
this.newObjectId
|
||||
);
|
||||
if (currentObject) {
|
||||
removeCanvasObjectByObject(this.canvas, currentObject);
|
||||
}
|
||||
await optimizeCanvasRendering(this.canvas, async () => {
|
||||
// 移除当前对象
|
||||
if (this.newObjectId) {
|
||||
const { object: currentObject } = findObjectById(this.canvas, this.newObjectId);
|
||||
if (currentObject) {
|
||||
removeCanvasObjectByObject(this.canvas, currentObject);
|
||||
}
|
||||
}
|
||||
|
||||
// 恢复之前的变换
|
||||
if (this.previousTransform) {
|
||||
restoredImage.set(this.previousTransform);
|
||||
}
|
||||
// 恢复之前的变换
|
||||
if (this.previousTransform) {
|
||||
restoredImage.set(this.previousTransform);
|
||||
}
|
||||
|
||||
// 设置图层属性
|
||||
restoredImage.set({
|
||||
id: this.previousObjectId,
|
||||
layerId: this.targetLayer.id,
|
||||
layerName: this.targetLayer.name,
|
||||
isBackground: this.targetLayer.isBackground,
|
||||
isFixed: this.targetLayer.isFixed,
|
||||
});
|
||||
|
||||
// 使用帮助函数在正确的z-index位置恢复对象
|
||||
if (
|
||||
this.previousZIndex !== undefined &&
|
||||
this.previousZIndex >= 0
|
||||
) {
|
||||
const insertSuccess = insertObjectAtZIndex(
|
||||
this.canvas,
|
||||
restoredImage,
|
||||
this.previousZIndex,
|
||||
false
|
||||
);
|
||||
if (insertSuccess) {
|
||||
console.log(`恢复图像到z-index位置: ${this.previousZIndex}`);
|
||||
} else {
|
||||
// 如果插入失败,回退到普通添加
|
||||
this.canvas.add(restoredImage);
|
||||
console.log("z-index恢复失败,恢复图像添加到顶层");
|
||||
}
|
||||
} else {
|
||||
// 如果没有保存的z-index,添加到顶层
|
||||
this.canvas.add(restoredImage);
|
||||
console.log("恢复图像添加到顶层");
|
||||
}
|
||||
|
||||
restoredImage.setCoords();
|
||||
|
||||
// 更新引用
|
||||
this.targetLayer.fabricObject = restoredImage.toObject([
|
||||
"id",
|
||||
"layerId",
|
||||
"type",
|
||||
]);
|
||||
this.layerManager.updateLayerObject(
|
||||
this.targetLayer.id,
|
||||
restoredImage
|
||||
);
|
||||
// 设置图层属性
|
||||
restoredImage.set({
|
||||
id: this.previousObjectId,
|
||||
layerId: this.targetLayer.id,
|
||||
layerName: this.targetLayer.name,
|
||||
isBackground: this.targetLayer.isBackground,
|
||||
isFixed: this.targetLayer.isFixed,
|
||||
});
|
||||
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
// 使用帮助函数在正确的z-index位置恢复对象
|
||||
if (this.previousZIndex !== undefined && this.previousZIndex >= 0) {
|
||||
const insertSuccess = insertObjectAtZIndex(
|
||||
this.canvas,
|
||||
restoredImage,
|
||||
this.previousZIndex,
|
||||
false
|
||||
);
|
||||
if (insertSuccess) {
|
||||
console.log(`恢复图像到z-index位置: ${this.previousZIndex}`);
|
||||
} else {
|
||||
// 如果插入失败,回退到普通添加
|
||||
this.canvas.add(restoredImage);
|
||||
console.log("z-index恢复失败,恢复图像添加到顶层");
|
||||
}
|
||||
} else {
|
||||
// 如果没有保存的z-index,添加到顶层
|
||||
this.canvas.add(restoredImage);
|
||||
console.log("恢复图像添加到顶层");
|
||||
}
|
||||
|
||||
restoredImage.setCoords();
|
||||
|
||||
// 更新引用
|
||||
this.targetLayer.fabricObject = restoredImage.toObject(["id", "layerId", "type"]);
|
||||
this.layerManager.updateLayerObject(this.targetLayer.id, restoredImage);
|
||||
});
|
||||
|
||||
resolve();
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async removeCurrentImage() {
|
||||
await optimizeCanvasRendering(this.canvas, async () => {
|
||||
if (this.newObjectId) {
|
||||
const { object: currentObject } = findObjectById(
|
||||
this.canvas,
|
||||
this.newObjectId
|
||||
);
|
||||
const { object: currentObject } = findObjectById(this.canvas, this.newObjectId);
|
||||
if (currentObject) {
|
||||
const removeSuccess = removeCanvasObjectByObject(
|
||||
this.canvas,
|
||||
currentObject
|
||||
);
|
||||
const removeSuccess = removeCanvasObjectByObject(this.canvas, currentObject);
|
||||
if (removeSuccess) {
|
||||
this.targetLayer.fabricObject = null;
|
||||
this.layerManager.updateLayerObject(this.targetLayer.id, null);
|
||||
@@ -3797,10 +3627,7 @@ export class AddImageToLayerCommand extends Command {
|
||||
this.validateInputs();
|
||||
|
||||
// 查找目标图层
|
||||
const { layer } = findLayerRecursively(
|
||||
this.layerManager?.layers?.value || [],
|
||||
this.layerId
|
||||
);
|
||||
const { layer } = findLayerRecursively(this.layerManager?.layers?.value || [], this.layerId);
|
||||
|
||||
this.targetLayer = layer;
|
||||
|
||||
@@ -3859,10 +3686,7 @@ export class AddImageToLayerCommand extends Command {
|
||||
this.canvas.remove(this.addedObject);
|
||||
|
||||
// 从图层管理器中移除
|
||||
this.layerManager.removeObjectFromLayer(
|
||||
this.addedObject.id,
|
||||
this.layerId
|
||||
);
|
||||
this.layerManager.removeObjectFromLayer(this.addedObject.id, this.layerId);
|
||||
|
||||
this.isExecuted = false;
|
||||
|
||||
@@ -3925,19 +3749,14 @@ export class AddImageToLayerCommand extends Command {
|
||||
this.retryCount = attempt;
|
||||
|
||||
if (attempt === this.maxRetries) {
|
||||
throw new Error(
|
||||
`图像加载失败,已重试${this.maxRetries}次: ${error.message}`
|
||||
);
|
||||
throw new Error(`图像加载失败,已重试${this.maxRetries}次: ${error.message}`);
|
||||
}
|
||||
|
||||
// 指数退避重试
|
||||
const delay = Math.pow(2, attempt) * 1000;
|
||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||
|
||||
console.warn(
|
||||
`图像加载重试 ${attempt + 1}/${this.maxRetries}:`,
|
||||
error.message
|
||||
);
|
||||
console.warn(`图像加载重试 ${attempt + 1}/${this.maxRetries}:`, error.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3945,9 +3764,7 @@ export class AddImageToLayerCommand extends Command {
|
||||
loadImage() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeout = setTimeout(() => {
|
||||
reject(
|
||||
new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)
|
||||
);
|
||||
reject(new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`));
|
||||
}, this.timeoutMs);
|
||||
|
||||
fabric.Image.fromURL(
|
||||
@@ -4057,9 +3874,7 @@ export class RemoveChildLayerCommand extends Command {
|
||||
this.parentLayer = parent;
|
||||
|
||||
this.childIndex =
|
||||
this.parentLayer?.children?.findIndex(
|
||||
(child) => child.id === this.layerId
|
||||
) ?? -1;
|
||||
this.parentLayer?.children?.findIndex((child) => child.id === this.layerId) ?? -1;
|
||||
this.removedChild = this.parentLayer?.children?.[this.childIndex];
|
||||
this.isActiveLayer = this.layerId === this.activeLayerId.value;
|
||||
|
||||
@@ -4074,10 +3889,7 @@ export class RemoveChildLayerCommand extends Command {
|
||||
}
|
||||
|
||||
// 从画布中移除子图层中的所有对象
|
||||
if (
|
||||
this.removedChild.fabricObjects &&
|
||||
this.removedChild.fabricObjects.length > 0
|
||||
) {
|
||||
if (this.removedChild.fabricObjects && this.removedChild.fabricObjects.length > 0) {
|
||||
this.removedChild.fabricObjects.forEach((obj) => {
|
||||
const { object } = findObjectById(this.canvas, obj.id);
|
||||
if (object) {
|
||||
@@ -4096,9 +3908,7 @@ export class RemoveChildLayerCommand extends Command {
|
||||
this.activeLayerId.value = this.parentLayer.children[0].id;
|
||||
} else {
|
||||
this.activeLayerId.value =
|
||||
this.layers.value.find(
|
||||
(layer) => !layer.isBackground || !layer.isFixed
|
||||
)?.[0]?.id || null;
|
||||
this.layers.value.find((layer) => !layer.isBackground || !layer.isFixed)?.[0]?.id || null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4233,10 +4043,7 @@ export class ChildLayerLockCommand extends Command {
|
||||
this.layerManager = options.layerManager;
|
||||
|
||||
// 查找父图层和子图层
|
||||
const { layer, parent } = findLayerRecursively(
|
||||
this.layers.value,
|
||||
this.layerId
|
||||
);
|
||||
const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId);
|
||||
this.parentLayer = parent;
|
||||
this.childLayer = layer;
|
||||
this.oldLocked = this.childLayer ? this.childLayer.locked : null;
|
||||
|
||||
Reference in New Issue
Block a user