fix: 修复多个已知问题

This commit is contained in:
bighuixiang
2025-06-29 23:29:47 +08:00
parent 6fc2a8fc57
commit 4a95f27966
41 changed files with 2266 additions and 351 deletions

View File

@@ -1,3 +1,4 @@
import { findObjectById } from "../utils/helper";
import { Command } from "./Command";
import { fabric } from "fabric-with-all";
@@ -129,14 +130,13 @@ export class UpdateBackgroundCommand extends Command {
});
this.canvas = options.canvas;
this.layers = options.layers;
this.backgroundColor = options.backgroundColor;
this.backgroundColorValue = options.backgroundColorValue; // 使用.value获取实际值
this.backgroundColor = options.backgroundColor; //
this.historyManager = options.historyManager;
// 查找背景图层
this.bgLayer = this.layers.value.find((layer) => layer.isBackground);
this.oldBackgroundColor = this.bgLayer
? this.bgLayer.backgroundColor
: "#ffffff";
this.oldBackgroundColor = this.bgLayer.backgroundColor;
}
execute() {
@@ -150,10 +150,14 @@ export class UpdateBackgroundCommand extends Command {
// 更新背景对象属性
if (this.bgLayer.fabricObject) {
this.bgLayer.fabricObject.set("fill", this.backgroundColor);
const { object } = findObjectById(
this.canvas,
this.bgLayer.fabricObject.id
);
object.set("fill", this.backgroundColor);
this.canvas.renderAll();
}
this.backgroundColorValue.value = this.backgroundColor; // 设置背景颜色
return true;
}
@@ -167,10 +171,14 @@ export class UpdateBackgroundCommand extends Command {
// 恢复背景对象属性
if (this.bgLayer.fabricObject) {
this.bgLayer.fabricObject.set("fill", this.oldBackgroundColor);
const { object } = findObjectById(
this.canvas,
this.bgLayer.fabricObject.id
);
object.set("fill", this.oldBackgroundColor);
this.canvas.renderAll();
}
this.backgroundColorValue.value = this.oldBackgroundColor; // 恢复背景颜色
return true;
}

View File

@@ -1,3 +1,8 @@
import {
createLayer,
findInChildLayers,
LayerType,
} from "../utils/layerHelper.js";
import { createRasterizedImage } from "../utils/selectionToImage.js";
import { CompositeCommand } from "./Command.js";
import { CreateImageLayerCommand } from "./LayerCommands.js";
@@ -27,6 +32,15 @@ export class LassoCutoutCommand extends CompositeCommand {
// 高清截图选项
this.highResolutionEnabled = options.highResolutionEnabled !== false; // 默认启用
this.baseResolutionScale = options.baseResolutionScale || 2; // 基础分辨率倍数
this.groupId = options.groupId || `cutout-group-${Date.now()}`;
this.groupName = options.groupName || `选区组`;
this.groupLayer = null; // 新增:保存组图层的引用
this.originalLayersLength = 0; // 新增:保存原始图层数量
// 序列化保存选区对象,用于重做时恢复
this.serializedSelectionObject = null;
this._serializeSelectionObject();
}
async execute() {
@@ -38,8 +52,11 @@ export class LassoCutoutCommand extends CompositeCommand {
try {
this.executedCommands = [];
// 保存原始图层数量,用于撤销时的验证
this.originalLayersLength = this.layerManager.layers.value.length;
// 获取选区
const selectionObject = this.selectionManager.getSelectionObject();
const selectionObject = await this._getSelectionObject();
if (!selectionObject) {
console.error("无法执行套索抠图:当前没有选区");
return false;
@@ -112,10 +129,47 @@ export class LassoCutoutCommand extends CompositeCommand {
await clearSelectionCmd.execute();
this.executedCommands.push(clearSelectionCmd);
const topLayerIndex = this.layerManager.layers.value.findIndex(
(layer) => layer.id === this.newLayerId
);
const selectLayer = this.layerManager.layers.value[topLayerIndex];
// 创建新的组图层
this.groupLayer = createLayer({
id: this.groupId,
name: this.groupName || `选区组`,
type: LayerType.GROUP,
visible: true,
locked: false,
opacity: 1.0,
fabricObjects: [],
children: [],
});
this.fabricImage.set({
selectable: true,
evented: true,
});
selectLayer.parentId = this.groupId; // 设置新图层的parentId为组图层ID
selectLayer.fabricObjects = [
this.fabricImage.toObject("id", "layerId", "layerName", "parentId"),
];
this.groupLayer.children.push(selectLayer);
// 插入新组图层
this.layerManager.layers.value.splice(topLayerIndex, 1, this.groupLayer);
this.layerManager.updateLayersObjectsInteractivity();
this.canvas.discardActiveObject();
this.canvas.setActiveObject(this.fabricImage);
this.canvas.renderAll();
console.log(`套索抠图完成新图层ID: ${this.newLayerId}`);
return {
newLayerId: this.newLayerId,
cutoutImageUrl: this.cutoutImageUrl,
guroupId: this.groupId,
groupName: this.groupName,
};
} catch (error) {
console.error("套索抠图过程中出错:", error);
@@ -129,32 +183,127 @@ export class LassoCutoutCommand extends CompositeCommand {
}
}
// 清理组图层(如果已创建)
if (this.groupLayer && this.groupId) {
try {
const groupIndex = this.layerManager.layers.value.findIndex(
(layer) => layer.id === this.groupId
);
if (groupIndex !== -1) {
this.layerManager.layers.value.splice(groupIndex, 1);
console.log(`清理了异常创建的组图层: ${this.groupId}`);
}
this.groupLayer = null;
} catch (cleanupError) {
console.warn("清理组图层失败:", cleanupError);
}
}
// 尝试回滚已执行的命令
if (this.executedCommands.length > 0) {
try {
for (let i = this.executedCommands.length - 1; i >= 0; i--) {
const command = this.executedCommands[i];
if (command && typeof command.undo === "function") {
await command.undo();
}
}
this.executedCommands = [];
} catch (rollbackError) {
console.warn("回滚已执行命令失败:", rollbackError);
}
}
throw error;
}
}
async undo() {
try {
// 逆序撤销所有已执行的命令
for (let i = this.executedCommands.length - 1; i >= 0; i--) {
const command = this.executedCommands[i];
if (command && typeof command.undo === "function") {
await command.undo();
console.log(`↩️ 开始撤销套索抠图操作`);
// 1. 首先移除组图层(如果存在)
if (this.groupId) {
const groupIndex = this.layerManager.layers.value.findIndex(
(layer) => layer.id === this.groupId
);
if (groupIndex !== -1) {
console.log(`↩️ 移除组图层: ${this.groupId}`);
// 从图层列表中移除组图层
this.layerManager.layers.value.splice(groupIndex, 1);
}
}
if (this.fabricImage) {
console.log(`↩️ 移除抠图图像: ${this.fabricImage.id}`);
// 从画布中移除抠图图像
this.canvas.remove(this.fabricImage);
}
// 2. 逆序撤销所有已执行的子命令
for (let i = this.executedCommands.length - 1; i >= 0; i--) {
const command = this.executedCommands[i];
if (command && typeof command.undo === "function") {
try {
console.log(`↩️ 撤销子命令: ${command.constructor.name}`);
await command.undo();
console.log(`✅ 子命令撤销成功: ${command.constructor.name}`);
} catch (error) {
console.error(
`❌ 子命令撤销失败: ${command.constructor.name}`,
error
);
// 子命令撤销失败不中断整个撤销过程
}
}
}
// 3. 清理状态
this.executedCommands = [];
this.newLayerId = null;
this.cutoutImageUrl = null;
this.fabricImage = null;
this.groupLayer = null; // 清理组图层引用
// 注意不重置groupId因为重做时可能需要使用相同的ID
// 4. 更新画布和图层交互性
await this.layerManager.updateLayersObjectsInteractivity();
console.log(`✅ 套索抠图撤销完成`);
return true;
} catch (error) {
console.error("撤销套索抠图失败:", error);
console.error("撤销套索抠图失败:", error);
return false;
}
}
/**
* 获取命令信息
* @returns {Object} 命令详细信息
*/
getInfo() {
return {
name: this.name,
description: this.description,
newLayerId: this.newLayerId,
newLayerName: this.newLayerName,
groupId: this.groupId,
groupName: this.groupName,
executedCommandsCount: this.executedCommands.length,
hasGroupLayer: !!this.groupLayer,
sourceLayerId: this.sourceLayerId,
highResolutionEnabled: this.highResolutionEnabled,
baseResolutionScale: this.baseResolutionScale,
hasSerializedSelection: !!this.serializedSelectionObject,
selectionType: this.serializedSelectionObject?.type || null,
subCommands: this.executedCommands.map((cmd) => ({
name: cmd.constructor.name,
info: cmd.getInfo ? cmd.getInfo() : {},
})),
};
}
/**
* 获取图层的所有对象(包括子图层,从画布中查找真实对象)
* @param {Object} layer 图层对象
@@ -249,6 +398,7 @@ export class LassoCutoutCommand extends CompositeCommand {
scaleFactor: scaleFactor,
// isReturenDataURL: true, // 返回DataURL
preserveOriginalQuality: true, // 启用高质量模式
selectionManager: this.selectionManager, // 传递选区管理器,用于获取羽化值
});
if (!rasterizedDataURL) {
@@ -500,4 +650,129 @@ export class LassoCutoutCommand extends CompositeCommand {
}
});
}
/**
* 序列化选区对象
* @private
*/
_serializeSelectionObject() {
try {
if (!this.selectionManager) {
console.warn("选区管理器不存在,无法序列化选区对象");
return;
}
const selectionObject = this.selectionManager.getSelectionObject();
if (!selectionObject) {
console.warn("当前没有选区对象,无法序列化");
return;
}
// 将选区对象转换为可序列化的对象
this.serializedSelectionObject = selectionObject.toObject([
"id",
"layerId",
"layerName",
"parentId",
]);
console.log("选区对象已序列化保存");
} catch (error) {
console.error("序列化选区对象失败:", error);
this.serializedSelectionObject = null;
}
}
/**
* 反序列化选区对象
* @returns {Promise<Object>} 选区对象
* @private
*/
async _getSelectionObject() {
try {
// 首先尝试从选区管理器获取当前选区
const currentSelection = this.selectionManager.getSelectionObject();
if (currentSelection) {
console.log("从选区管理器获取到当前选区");
return currentSelection;
}
// 如果当前没有选区,则从序列化数据恢复
if (!this.serializedSelectionObject) {
console.error("没有序列化的选区对象数据");
return null;
}
console.log("从序列化数据恢复选区对象");
// 根据选区对象类型进行反序列化
return new Promise((resolve, reject) => {
const objectType = this.serializedSelectionObject.type;
if (objectType === "path") {
// 如果是路径类型(套索选区)
fabric.Path.fromObject(this.serializedSelectionObject, (path) => {
if (path) {
console.log("路径选区对象反序列化成功");
resolve(path);
} else {
reject(new Error("路径选区对象反序列化失败"));
}
});
} else if (objectType === "polygon") {
// 如果是多边形类型
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) {
console.log("矩形选区对象反序列化成功");
resolve(rect);
} else {
reject(new Error("矩形选区对象反序列化失败"));
}
});
} else if (objectType === "ellipse" || objectType === "circle") {
// 如果是椭圆/圆形选区
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("通用选区对象反序列化失败"));
}
}
);
}
});
} catch (error) {
console.error("获取选区对象失败:", error);
return null;
}
}
}

View File

@@ -490,6 +490,7 @@ export class LiquifyStateCommand extends Command {
* @param {String} options.targetLayerId 目标图层ID
* @param {ImageData} options.initialImageData 初始图像数据
* @param {ImageData} options.finalImageData 最终图像数据
* @param {Object} options.liquifyManager 液化管理器实例
*/
constructor(options) {
super({
@@ -502,6 +503,7 @@ export class LiquifyStateCommand extends Command {
this.targetObject = options.targetObject;
this.targetLayerId = options.targetLayerId;
this.targetObjectId = options.targetObjectId;
this.liquifyManager = options.liquifyManager; // 添加液化管理器引用
// 获取引用管理器实例
this.refManager = getLiquifyReferenceManager();
@@ -520,6 +522,10 @@ export class LiquifyStateCommand extends Command {
this.initialImageData = options.initialImageData;
this.finalImageData = options.finalImageData;
// 保存液化管理器的操作记录状态
this.initialLiquifyState = null;
this.finalLiquifyState = null;
this.currentState = "initial";
// 创建初始快照
@@ -547,6 +553,19 @@ export class LiquifyStateCommand extends Command {
this.finalImageData
);
// 恢复液化管理器到最终状态
if (this.liquifyManager && this.finalLiquifyState) {
this._restoreLiquifyManagerState(this.finalLiquifyState);
} else if (this.liquifyManager) {
// 如果没有保存的最终状态,重新准备液化环境
const currentTarget = this.refManager.getObjectRef(this.objectRefId);
if (currentTarget) {
await this.liquifyManager.prepareForLiquify(currentTarget);
// 保存当前的液化管理器状态作为最终状态
this.finalLiquifyState = this._captureLiquifyManagerState();
}
}
this.currentState = "final";
this.canvas.renderAll();
@@ -568,6 +587,21 @@ export class LiquifyStateCommand extends Command {
this.initialSnapshotId
);
// 恢复液化管理器到初始状态
if (this.liquifyManager) {
if (this.initialLiquifyState) {
this._restoreLiquifyManagerState(this.initialLiquifyState);
} else {
// 如果没有初始状态,重置液化管理器
this.liquifyManager.reset();
// 重新准备液化环境
const currentTarget = this.refManager.getObjectRef(this.objectRefId);
if (currentTarget) {
await this.liquifyManager.prepareForLiquify(currentTarget);
}
}
}
this.currentState = "initial";
this.canvas.renderAll();
@@ -589,6 +623,11 @@ export class LiquifyStateCommand extends Command {
setFinalImageData(finalImageData) {
this.finalImageData = finalImageData;
this.finalSnapshotId = null; // 重置快照ID下次执行时重新创建
// 捕获当前液化管理器状态作为最终状态
if (this.liquifyManager) {
this.finalLiquifyState = this._captureLiquifyManagerState();
}
}
/**
@@ -672,6 +711,12 @@ export class LiquifyStateCommand extends Command {
};
this.refManager.stateSnapshots.set(this.initialSnapshotId, snapshot);
// 捕获初始液化管理器状态
if (this.liquifyManager) {
this.initialLiquifyState = this._captureLiquifyManagerState();
}
console.log(`📸 初始状态快照已创建: ${this.initialSnapshotId}`);
}
}
@@ -697,27 +742,180 @@ export class LiquifyStateCommand extends Command {
};
this.refManager.stateSnapshots.set(this.finalSnapshotId, snapshot);
// 捕获最终液化管理器状态
if (this.liquifyManager) {
this.finalLiquifyState = this._captureLiquifyManagerState();
}
console.log(`📸 最终状态快照已创建: ${this.finalSnapshotId}`);
}
}
/**
* 计算命令本身的内存使用量
* @returns {Number} 内存使用量(字节)
* 捕获液化管理器的当前状态
* @returns {Object} 液化管理器状态
* @private
*/
_calculateCommandMemory() {
let bytes = 0;
_captureLiquifyManagerState() {
if (!this.liquifyManager) return null;
// 计算ImageData内存使用
if (this.initialImageData) {
bytes += this.initialImageData.width * this.initialImageData.height * 4;
}
if (this.finalImageData) {
bytes += this.finalImageData.width * this.finalImageData.height * 4;
}
try {
const state = {
// 捕获增强管理器状态
enhancedManagerState: null,
// 捕获当前渲染器状态
activeRendererState: null,
// 捕获目标对象引用
targetObjectRef: this.liquifyManager.targetObject,
// 捕获初始化状态
initialized: this.liquifyManager.initialized || false,
};
return bytes;
// 如果有增强管理器,捕获其状态
if (this.liquifyManager.enhancedManager) {
const enhancedManager = this.liquifyManager.enhancedManager;
state.enhancedManagerState = {
initialized: enhancedManager.initialized,
renderMode: enhancedManager.renderMode,
targetObject: enhancedManager.targetObject,
originalImageData: enhancedManager.originalImageData,
currentImageData: enhancedManager.currentImageData,
params: { ...enhancedManager.params },
currentMode: enhancedManager.currentMode,
};
// 如果有激活的渲染器,捕获其状态
if (enhancedManager.activeRenderer) {
const renderer = enhancedManager.activeRenderer;
state.activeRendererState = {
initialized: renderer.initialized,
originalImageData: renderer.originalImageData,
currentImageData: renderer.currentImageData,
params: { ...renderer.params },
currentMode: renderer.currentMode,
// 对于CPU渲染器还需要保存网格状态
meshState: renderer.mesh
? this._captureMeshState(renderer.mesh)
: null,
// 保存变形历史
deformHistory: renderer.deformHistory
? [...renderer.deformHistory]
: [],
};
}
}
console.log(`💾 液化管理器状态已捕获:`, state);
return state;
} catch (error) {
console.error("捕获液化管理器状态失败:", error);
return null;
}
}
/**
* 恢复液化管理器状态
* @param {Object} state 要恢复的状态
* @private
*/
_restoreLiquifyManagerState(state) {
if (!this.liquifyManager || !state) return;
try {
// 恢复基本状态
this.liquifyManager.initialized = state.initialized;
if (state.targetObjectRef) {
this.liquifyManager.targetObject = state.targetObjectRef;
}
// 恢复增强管理器状态
if (state.enhancedManagerState && this.liquifyManager.enhancedManager) {
const enhancedManager = this.liquifyManager.enhancedManager;
const enhancedState = state.enhancedManagerState;
enhancedManager.initialized = enhancedState.initialized;
enhancedManager.renderMode = enhancedState.renderMode;
enhancedManager.targetObject = enhancedState.targetObject;
enhancedManager.originalImageData = enhancedState.originalImageData;
enhancedManager.currentImageData = enhancedState.currentImageData;
enhancedManager.params = { ...enhancedState.params };
enhancedManager.currentMode = enhancedState.currentMode;
// 恢复激活渲染器状态
if (state.activeRendererState && enhancedManager.activeRenderer) {
const renderer = enhancedManager.activeRenderer;
const rendererState = state.activeRendererState;
renderer.initialized = rendererState.initialized;
renderer.originalImageData = rendererState.originalImageData;
renderer.currentImageData = rendererState.currentImageData;
renderer.params = { ...rendererState.params };
renderer.currentMode = rendererState.currentMode;
// 恢复网格状态如果是CPU渲染器
if (rendererState.meshState && renderer.mesh) {
this._restoreMeshState(renderer.mesh, rendererState.meshState);
}
// 恢复变形历史
if (rendererState.deformHistory) {
renderer.deformHistory = [...rendererState.deformHistory];
}
}
}
console.log(`🔄 液化管理器状态已恢复`);
} catch (error) {
console.error("恢复液化管理器状态失败:", error);
}
}
/**
* 捕获网格状态
* @param {Array} mesh 网格数组
* @returns {Array} 网格状态副本
* @private
*/
_captureMeshState(mesh) {
if (!mesh || !Array.isArray(mesh)) return null;
return mesh.map((row) =>
row.map((point) => ({
x: point.x,
y: point.y,
originalX: point.originalX,
originalY: point.originalY,
}))
);
}
/**
* 恢复网格状态
* @param {Array} mesh 目标网格
* @param {Array} meshState 要恢复的网格状态
* @private
*/
_restoreMeshState(mesh, meshState) {
if (
!mesh ||
!meshState ||
!Array.isArray(mesh) ||
!Array.isArray(meshState)
)
return;
for (let i = 0; i < Math.min(mesh.length, meshState.length); i++) {
for (let j = 0; j < Math.min(mesh[i].length, meshState[i].length); j++) {
const point = mesh[i][j];
const statePoint = meshState[i][j];
point.x = statePoint.x;
point.y = statePoint.y;
point.originalX = statePoint.originalX;
point.originalY = statePoint.originalY;
}
}
}
}