feat: 裁剪组裁剪跟随选择组移动

This commit is contained in:
bighuixiang
2025-07-14 01:00:23 +08:00
parent 96e13cb22a
commit 24e9ba8ae5
80 changed files with 2052 additions and 4292 deletions

View File

@@ -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;