refactor: 优化代码格式,调整对象添加和移除逻辑,确保更好的可读性和维护性

This commit is contained in:
bighuixiang
2025-07-21 23:07:47 +08:00
parent 2eab67d09f
commit bcd232c81b

View File

@@ -11,6 +11,7 @@ import {
} from "../utils/helper"; } from "../utils/helper";
import { fabric } from "fabric-with-all"; import { fabric } from "fabric-with-all";
import { imageModeHandler } from "../utils/imageHelper"; import { imageModeHandler } from "../utils/imageHelper";
import { restoreFabricObject } from "../utils/objectHelper";
/** /**
* 设置活动图层命令 * 设置活动图层命令
@@ -34,7 +35,11 @@ export class SetActiveLayerCommand extends Command {
} }
execute() { execute() {
const { layer } = findLayerRecursively(this.layers.value, this.layerId, this.parentId); const { layer } = findLayerRecursively(
this.layers.value,
this.layerId,
this.parentId
);
this.newLayer = layer; this.newLayer = layer;
if (!this.newLayer) { if (!this.newLayer) {
@@ -64,7 +69,10 @@ export class SetActiveLayerCommand extends Command {
this.canvas.discardActiveObject(); this.canvas.discardActiveObject();
// 设置为新的图层下的对象为激活,但需要确保对象存在于画布上 // 设置为新的图层下的对象为激活,但需要确保对象存在于画布上
if (this.newLayer.fabricObjects && this.newLayer.fabricObjects.length > 0) { if (
this.newLayer.fabricObjects &&
this.newLayer.fabricObjects.length > 0
) {
const canvasObjects = this.canvas.getObjects(); const canvasObjects = this.canvas.getObjects();
const validObjects = this.newLayer.fabricObjects.filter( const validObjects = this.newLayer.fabricObjects.filter(
(obj) => obj && canvasObjects.includes(obj) (obj) => obj && canvasObjects.includes(obj)
@@ -146,7 +154,9 @@ export class AddObjectToLayerCommand extends Command {
this.layerManager = options.layerManager; this.layerManager = options.layerManager;
// 保存对象原始状态和ID // 保存对象原始状态和ID
this.objectId = this.fabricObject.id || `obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`; this.objectId =
this.fabricObject.id ||
`obj_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
this.fabricObject.set({ this.fabricObject.set({
id: this.objectId, id: this.objectId,
layerId: options.layerId, layerId: options.layerId,
@@ -154,7 +164,11 @@ export class AddObjectToLayerCommand extends Command {
}); });
// 保存完整的对象状态,包括位置和变换信息 // 保存完整的对象状态,包括位置和变换信息
this.originalObjectState = this.fabricObject.toObject(["id", "layerId", "layerName"]); this.originalObjectState = this.fabricObject.toObject([
"id",
"layerId",
"layerName",
]);
// // 新增:保存详细的位置和变换信息,用于重做时恢复 // // 新增:保存详细的位置和变换信息,用于重做时恢复
// this.originalPosition = { // this.originalPosition = {
@@ -176,7 +190,10 @@ export class AddObjectToLayerCommand extends Command {
async execute() { async execute() {
// 查找目标图层 // 查找目标图层
const { layer } = findLayerRecursively(this.layers.value, this.layerId); const { layer, parent } = findLayerRecursively(
this.layers.value,
this.layerId
);
if (!layer) { if (!layer) {
console.error(`图层 ${this.layerId} 不存在`); console.error(`图层 ${this.layerId} 不存在`);
@@ -193,83 +210,49 @@ export class AddObjectToLayerCommand extends Command {
// 优化渲染 - 统一批处理 支持异步回调 // 优化渲染 - 统一批处理 支持异步回调
await optimizeCanvasRendering(this.canvas, async () => { await optimizeCanvasRendering(this.canvas, async () => {
// const positionToUse = this.isFirstExecution fabric.util.enlivenObjects(
// ? { [this.originalObjectState],
// left: this.fabricObject.left || 0, async (objects) => {
// top: this.fabricObject.top || 0, this.fabricObject = objects[0];
// scaleX: this.fabricObject.scaleX || 1, // 将对象添加到画布
// scaleY: this.fabricObject.scaleY || 1, this.fabricObject.set({
// angle: this.fabricObject.angle || 0, id: this.objectId, // 确保对象有唯一ID
// flipX: this.fabricObject.flipX || false, layerId: this.layerId, // 设置图层ID
// flipY: this.fabricObject.flipY || false, layerName: layer.name, // 设置图层名称
// opacity: this.fabricObject.opacity || 1, isBackground: layer.isBackground || false, // 是否为背景层
// originX: this.fabricObject.originX || "left", isFixed: layer.isFixed || false, // 是否为固定层
// originY: this.fabricObject.originY || "top", isLocked: layer.locked || false, // 是否锁定
// } isVisible: layer.visible !== false, // 是否可见
// : this.originalPosition; eraser: layer.eraser || false, // 是否为橡皮擦
type: this.fabricObject.type || "object", // 对象类型
// if (!this.isFirstExecution) { selectable: true, // 设置对象可选择
// fabric.util.enlivenObjects([this.originalObjectState], (objects) => { evented: true, // 设置对象可事件
// this.fabricObject = objects[0]; });
// // 将对象添加到画布 // 如果对象父图层有 裁剪 则更新裁剪
// this.fabricObject.set({ if (parent.clippingMask) {
// id: this.objectId, // 确保对象有唯一ID const clippingMaskFabricObject = await restoreFabricObject(
// layerId: this.layerId, // 设置图层ID parent.clippingMask,
// layerName: layer.name, // 设置图层名称 this.canvas
// isBackground: layer.isBackground || false, // 是否为背景层 );
// isFixed: layer.isFixed || false, // 是否为固定层 clippingMaskFabricObject.clipPath = null;
// isLocked: layer.locked || false, // 是否锁定 clippingMaskFabricObject.set({ absolutePositioned: true });
// isVisible: layer.visible !== false, // 是否可见 this.fabricObject.clipPath = clippingMaskFabricObject;
// eraser: layer.eraser || false, // 是否为橡皮擦 // 标记为脏对象
// type: this.fabricObject.type || "object", // 对象类型 this.fabricObject.dirty = true;
// selectable: true, // 设置对象可选择 this.fabricObject.setCoords();
// evented: true, // 设置对象可事件 }
// }); }
// }); );
// } else {
// // 将对象添加到画布
// this.fabricObject.set({
// ...positionToUse,
// id: this.objectId, // 确保对象有唯一ID
// layerId: this.layerId, // 设置图层ID
// layerName: layer.name, // 设置图层名称
// isBackground: layer.isBackground || false, // 是否为背景层
// isFixed: layer.isFixed || false, // 是否为固定层
// isLocked: layer.locked || false, // 是否锁定
// isVisible: layer.visible !== false, // 是否可见
// eraser: layer.eraser || false, // 是否为橡皮擦
// type: this.fabricObject.type || "object", // 对象类型
// selectable: true, // 设置对象可选择
// evented: true, // 设置对象可事件
// });
// }
fabric.util.enlivenObjects([this.originalObjectState], (objects) => {
this.fabricObject = objects[0];
// 将对象添加到画布
this.fabricObject.set({
id: this.objectId, // 确保对象有唯一ID
layerId: this.layerId, // 设置图层ID
layerName: layer.name, // 设置图层名称
isBackground: layer.isBackground || false, // 是否为背景层
isFixed: layer.isFixed || false, // 是否为固定层
isLocked: layer.locked || false, // 是否锁定
isVisible: layer.visible !== false, // 是否可见
eraser: layer.eraser || false, // 是否为橡皮擦
type: this.fabricObject.type || "object", // 对象类型
selectable: true, // 设置对象可选择
evented: true, // 设置对象可事件
});
});
// this.canvas.renderAll();
this.canvas.add(this.fabricObject); this.canvas.add(this.fabricObject);
// this.canvas.setActiveObject(this.fabricObject);
// 将对象添加到图层的fabricObjects数组 // 将对象添加到图层的fabricObjects数组
layer.fabricObjects = layer.fabricObjects || []; layer.fabricObjects = layer.fabricObjects || [];
layer.fabricObjects.push( layer.fabricObjects.push(
this.fabricObject?.toObject?.(["id", "layerId", "layerName"]) || this.fabricObject this.fabricObject?.toObject?.(["id", "layerId", "layerName"]) ||
this.fabricObject
); );
await this.layerManager?.updateLayersObjectsInteractivity?.(false);
// 标记为非首次执行 // 标记为非首次执行
this.isFirstExecution = false; this.isFirstExecution = false;
console.log( console.log(
@@ -277,6 +260,8 @@ export class AddObjectToLayerCommand extends Command {
); );
}); });
await this.layerManager?.updateLayersObjectsInteractivity?.();
this.layerManager?.updateLayersObjectsInteractivity?.();
// 如果是重做,使用保存的原始位置 // 如果是重做,使用保存的原始位置
// this.canvas.discardActiveObject(); // this.canvas.discardActiveObject();
@@ -313,12 +298,16 @@ export class AddObjectToLayerCommand extends Command {
// 从图层的fabricObjects数组中移除对象 // 从图层的fabricObjects数组中移除对象
if (layer.fabricObjects) { if (layer.fabricObjects) {
layer.fabricObjects = layer.fabricObjects.filter((obj) => obj.id !== this.objectId); layer.fabricObjects = layer.fabricObjects.filter(
(obj) => obj.id !== this.objectId
);
} }
// 优化渲染 - 统一批处理 支持异步回调 // 优化渲染 - 统一批处理 支持异步回调
optimizeCanvasRendering(this.canvas, async () => { optimizeCanvasRendering(this.canvas, async () => {
// 从画布移除对象 // 从画布移除对象
const object = this.canvas.getObjects().find((obj) => obj.id === this.objectId); const object = this.canvas
.getObjects()
.find((obj) => obj.id === this.objectId);
if (object) { if (object) {
// 先丢弃活动对象,避免控制点渲染错误 // 先丢弃活动对象,避免控制点渲染错误
this.canvas.discardActiveObject(); this.canvas.discardActiveObject();
@@ -392,7 +381,9 @@ export class RemoveObjectFromLayerCommand extends Command {
// 从图层的fabricObjects数组移除对象 // 从图层的fabricObjects数组移除对象
if (layer.fabricObjects) { if (layer.fabricObjects) {
layer.fabricObjects = layer.fabricObjects.filter((obj) => obj.id !== this.objectId); layer.fabricObjects = layer.fabricObjects.filter(
(obj) => obj.id !== this.objectId
);
} }
// 更新画布 // 更新画布
@@ -619,14 +610,19 @@ export class ChangeFixedImageCommand extends Command {
this.retryCount = attempt; this.retryCount = attempt;
if (attempt === this.maxRetries) { 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; const delay = Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, delay)); await new Promise((resolve) => setTimeout(resolve, delay));
console.warn(`图像加载重试 ${attempt + 1}/${this.maxRetries}:`, error.message); console.warn(
`图像加载重试 ${attempt + 1}/${this.maxRetries}:`,
error.message
);
} }
} }
} }
@@ -634,7 +630,9 @@ export class ChangeFixedImageCommand extends Command {
loadImage() { loadImage() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
reject(new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)); reject(
new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)
);
}, this.timeoutMs); }, this.timeoutMs);
fabric.Image.fromURL( fabric.Image.fromURL(
@@ -670,9 +668,15 @@ export class ChangeFixedImageCommand extends Command {
// 移除旧对象(如果存在) // 移除旧对象(如果存在)
if (this.previousObjectId) { if (this.previousObjectId) {
const { object: oldObject } = findObjectById(this.canvas, this.previousObjectId); const { object: oldObject } = findObjectById(
this.canvas,
this.previousObjectId
);
if (oldObject) { if (oldObject) {
const removeSuccess = removeCanvasObjectByObject(this.canvas, oldObject); const removeSuccess = removeCanvasObjectByObject(
this.canvas,
oldObject
);
if (!removeSuccess) { if (!removeSuccess) {
console.warn("移除旧对象失败,但继续执行"); console.warn("移除旧对象失败,但继续执行");
} }
@@ -738,75 +742,93 @@ export class ChangeFixedImageCommand extends Command {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fabric.util.enlivenObjects([this.previousImage.objectData], async (objects) => { fabric.util.enlivenObjects(
try { [this.previousImage.objectData],
const restoredImage = objects[0]; async (objects) => {
try {
const restoredImage = objects[0];
await optimizeCanvasRendering(this.canvas, async () => { await optimizeCanvasRendering(this.canvas, async () => {
// 移除当前对象 // 移除当前对象
if (this.newObjectId) { if (this.newObjectId) {
const { object: currentObject } = findObjectById(this.canvas, this.newObjectId); const { object: currentObject } = findObjectById(
if (currentObject) { this.canvas,
removeCanvasObjectByObject(this.canvas, currentObject); this.newObjectId
);
if (currentObject) {
removeCanvasObjectByObject(this.canvas, currentObject);
}
} }
}
// 恢复之前的变换 // 恢复之前的变换
if (this.previousTransform) { if (this.previousTransform) {
restoredImage.set(this.previousTransform); restoredImage.set(this.previousTransform);
} }
// 设置图层属性 // 设置图层属性
restoredImage.set({ restoredImage.set({
id: this.previousObjectId, id: this.previousObjectId,
layerId: this.targetLayer.id, layerId: this.targetLayer.id,
layerName: this.targetLayer.name, layerName: this.targetLayer.name,
isBackground: this.targetLayer.isBackground, isBackground: this.targetLayer.isBackground,
isFixed: this.targetLayer.isFixed, 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;
this.layerManager.updateLayerObject(
this.targetLayer.id,
restoredImage
);
}); });
// 使用帮助函数在正确的z-index位置恢复对象 resolve();
if (this.previousZIndex !== undefined && this.previousZIndex >= 0) { } catch (error) {
const insertSuccess = insertObjectAtZIndex( reject(error);
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;
this.layerManager.updateLayerObject(this.targetLayer.id, restoredImage);
});
resolve();
} catch (error) {
reject(error);
} }
}); );
}); });
} }
async removeCurrentImage() { async removeCurrentImage() {
await optimizeCanvasRendering(this.canvas, async () => { await optimizeCanvasRendering(this.canvas, async () => {
if (this.newObjectId) { if (this.newObjectId) {
const { object: currentObject } = findObjectById(this.canvas, this.newObjectId); const { object: currentObject } = findObjectById(
this.canvas,
this.newObjectId
);
if (currentObject) { if (currentObject) {
const removeSuccess = removeCanvasObjectByObject(this.canvas, currentObject); const removeSuccess = removeCanvasObjectByObject(
this.canvas,
currentObject
);
if (removeSuccess) { if (removeSuccess) {
this.targetLayer.fabricObject = null; this.targetLayer.fabricObject = null;
this.layerManager.updateLayerObject(this.targetLayer.id, null); this.layerManager.updateLayerObject(this.targetLayer.id, null);
@@ -925,7 +947,10 @@ export class AddImageToLayerCommand extends Command {
this.canvas.remove(this.addedObject); this.canvas.remove(this.addedObject);
// 从图层管理器中移除 // 从图层管理器中移除
this.layerManager.removeObjectFromLayer(this.addedObject.id, this.layerId); this.layerManager.removeObjectFromLayer(
this.addedObject.id,
this.layerId
);
this.isExecuted = false; this.isExecuted = false;
@@ -988,14 +1013,19 @@ export class AddImageToLayerCommand extends Command {
this.retryCount = attempt; this.retryCount = attempt;
if (attempt === this.maxRetries) { 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; const delay = Math.pow(2, attempt) * 1000;
await new Promise((resolve) => setTimeout(resolve, delay)); await new Promise((resolve) => setTimeout(resolve, delay));
console.warn(`图像加载重试 ${attempt + 1}/${this.maxRetries}:`, error.message); console.warn(
`图像加载重试 ${attempt + 1}/${this.maxRetries}:`,
error.message
);
} }
} }
} }
@@ -1003,7 +1033,9 @@ export class AddImageToLayerCommand extends Command {
loadImage() { loadImage() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
reject(new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)); reject(
new Error(`图像加载超时 (${this.timeoutMs}ms): ${this.imageUrl}`)
);
}, this.timeoutMs); }, this.timeoutMs);
fabric.Image.fromURL( fabric.Image.fromURL(
@@ -1257,16 +1289,23 @@ export class MoveLayerToTopCommand extends Command {
this.parentLayer = null; // 父图层 this.parentLayer = null; // 父图层
const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); const { layer, parent } = findLayerRecursively(
this.layers.value,
this.layerId
);
// 如果parent 有值 或者 layer 上有parentId 则视为子图层的置顶 // 如果parent 有值 或者 layer 上有parentId 则视为子图层的置顶
if (parent?.id) { 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; this.parentLayer = parent;
} else { } 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.layer = layer;
@@ -1348,16 +1387,23 @@ export class MoveLayerToBottomCommand extends Command {
this.parentLayer = null; // 父图层 this.parentLayer = null; // 父图层
const { layer, parent } = findLayerRecursively(this.layers.value, this.layerId); const { layer, parent } = findLayerRecursively(
this.layers.value,
this.layerId
);
// 如果parent 有值 或者 layer 上有parentId 则视为子图层的置顶 // 如果parent 有值 或者 layer 上有parentId 则视为子图层的置顶
if (parent?.id) { 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; this.parentLayer = parent;
} else { } 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.layer = layer;
@@ -1398,7 +1444,9 @@ export class MoveLayerToBottomCommand extends Command {
async undo() { async undo() {
if (this.originalIndex !== -1 && this.layer) { if (this.originalIndex !== -1 && this.layer) {
// 获取当前位置 // 获取当前位置
const currentIndex = this.layers.value.findIndex((layer) => layer.id === this.layerId); const currentIndex = this.layers.value.findIndex(
(layer) => layer.id === this.layerId
);
if (currentIndex !== -1) { if (currentIndex !== -1) {
// 移除当前位置 // 移除当前位置
@@ -1449,11 +1497,16 @@ export class MoveLayerToBottomCommand extends Command {
if (layer.isBackground && layer.fabricObject) { if (layer.isBackground && layer.fabricObject) {
// 背景图层 // 背景图层
const originalObj = canvasObjects.find((o) => o.id === layer.fabricObject.id); const originalObj = canvasObjects.find(
(o) => o.id === layer.fabricObject.id
);
if (originalObj) { if (originalObj) {
this.canvas.add(originalObj); this.canvas.add(originalObj);
} }
} else if (Array.isArray(layer.fabricObjects) && layer.fabricObjects.length > 0) { } else if (
Array.isArray(layer.fabricObjects) &&
layer.fabricObjects.length > 0
) {
// 普通图层和固定图层 // 普通图层和固定图层
layer.fabricObjects.forEach((obj) => { layer.fabricObjects.forEach((obj) => {
const originalObj = canvasObjects.find((o) => o.id === obj.id); const originalObj = canvasObjects.find((o) => o.id === obj.id);