合并画布

This commit is contained in:
X1627315083
2025-06-22 13:52:28 +08:00
parent fd6d61a44a
commit 584f6a7db0
47 changed files with 4540 additions and 1952 deletions

View File

@@ -302,7 +302,18 @@ export class RemoveLayerCommand extends Command {
);
this.removedLayer = this.layers.value[this.layerIndex];
this.isActiveLayer = this.layerId === this.activeLayerId.value;
// this.beforeLayers = [...this.layers.value]; // 备份原图层列表
// 从Canvas中找到真实对象并备份确保撤销和重做时对象的一致性
this.originalObjects = [];
if (this.removedLayer) {
// 从画布中获取真实的对象引用
this.originalObjects = this.canvas.getObjects().filter((obj) => {
return obj.layerId === this.layerId;
});
}
// 备份原活动图层ID
this.originalActiveLayerId = this.activeLayerId.value;
}
execute() {
@@ -311,19 +322,22 @@ export class RemoveLayerCommand extends Command {
return false;
}
// 从画布中移除图层中的所有对象
if (
this.removedLayer.fabricObjects &&
this.removedLayer.fabricObjects.length > 0
) {
this.removedLayer.fabricObjects.forEach((obj) => {
// 从画布中移除图层中的所有真实对象
this.originalObjects.forEach((obj) => {
if (this.canvas.getObjects().includes(obj)) {
this.canvas.remove(obj);
});
}
}
});
// 如果是背景图层,移除特殊对象
if (this.removedLayer.isBackground && this.removedLayer.fabricObject) {
this.canvas.remove(this.removedLayer.fabricObject);
const { object } = findObjectById(
this.canvas,
this.removedLayer.fabricObject.id
);
if (object) {
this.canvas.remove(object);
}
}
// 从图层列表中删除
@@ -347,38 +361,49 @@ export class RemoveLayerCommand extends Command {
this.canvas.renderAll();
}
console.log(
`✅ 已移除图层: ${this.removedLayer.name} (ID: ${this.layerId})`
);
return true;
}
undo() {
// 恢复图层
// 恢复图层到原位置
if (this.layerIndex !== -1 && this.removedLayer) {
this.layers.value.splice(this.layerIndex, 0, this.removedLayer);
// 恢复图层中的所有对象到画布
if (
this.removedLayer.fabricObjects &&
this.removedLayer.fabricObjects.length > 0
) {
this.removedLayer.fabricObjects.forEach((obj) => {
// 使用优化渲染批处理恢复真实对象到画布
optimizeCanvasRendering(this.canvas, () => {
this.originalObjects.forEach((obj) => {
// 恢复对象到画布
this.canvas.add(obj);
// 确保对象的图层信息正确
obj.layerId = this.layerId;
obj.layerName = this.removedLayer.name;
obj.setCoords(); // 更新坐标
});
}
// 如果是背景图层,恢复特殊对象
if (this.removedLayer.isBackground && this.removedLayer.fabricObject) {
this.canvas.add(this.removedLayer.fabricObject);
}
// 如果是背景图层,恢复特殊对象
if (this.removedLayer.isBackground && this.removedLayer.fabricObject) {
// 检查对象是否已在画布中
const { object } = findObjectById(
this.canvas,
this.removedLayer.fabricObject.id
);
if (!object) {
this.canvas.add(this.removedLayer.fabricObject);
}
}
});
// 如果删除的是当前活动图层,恢复活动图层
if (this.isActiveLayer) {
this.activeLayerId.value = this.layerId;
}
// 重新渲染画布
if (this.canvas) {
this.canvas.renderAll();
}
console.log(
`↩️ 已恢复图层: ${this.removedLayer.name} (ID: ${this.layerId})`
);
}
}
@@ -387,6 +412,7 @@ export class RemoveLayerCommand extends Command {
name: this.name,
layerName: this.removedLayer?.name || "未知图层",
layerId: this.layerId,
objectCount: this.originalObjects.length,
};
}
}
@@ -503,56 +529,40 @@ export class ToggleLayerVisibilityCommand extends Command {
this.canvas = options.canvas;
this.layers = options.layers;
this.layerId = options.layerId;
this.layerManager = options.layerManager;
// 查找图层
const { layer } = findLayerRecursively(this.layers.value, this.layerId);
this.layer = layer;
this.oldVisibility = this.layer ? this.layer.visible : null;
// this.oldVisibility = this.layer ? this.layer.visible : null;
}
execute() {
async execute() {
if (!this.layer) {
console.error(`图层 ${this.layerId} 不存在`);
return false;
}
// 切换可见性
this.layer.visible = !this.oldVisibility;
this.layer.visible = !this.layer.visible;
// 更新画布上图层对象的可见性
if (this.canvas) {
const layerObjects = this.canvas
.getObjects()
.filter((obj) => obj.layerId === this.layerId);
layerObjects.forEach((obj) => {
obj.visible = this.layer.visible;
});
this.canvas.renderAll();
}
// 更新画布上对象的可选择状态
await this.layerManager?.updateLayersObjectsInteractivity();
return true;
return this.layer.visible;
}
undo() {
if (this.layer) {
// 恢复可见性
this.layer.visible = this.oldVisibility;
// 更新画布上图层对象的可见性
if (this.canvas) {
const layerObjects = this.canvas
.getObjects()
.filter((obj) => obj.layerId === this.layerId);
layerObjects.forEach((obj) => {
obj.visible = this.oldVisibility;
});
this.canvas.renderAll();
}
}
async undo() {
return await this.execute(); // 直接调用execute方法来恢复可见性
}
getInfo() {
@@ -565,6 +575,71 @@ export class ToggleLayerVisibilityCommand extends Command {
}
}
/**
* 切换子图层可见性命令
*/
export class ToggleChildLayerVisibilityCommand extends Command {
constructor(options) {
super({
name: "切换子图层可见性",
saveState: false,
});
this.canvas = options.canvas;
this.layers = options.layers;
this.layerId = options.layerId;
this.parentId = options.parentId;
this.layerManager = options.layerManager;
// 查找父图层和子图层
const { layer, parent } = findLayerRecursively(
this.layers.value,
this.layerId
);
this.parentLayer = parent;
this.childLayer = layer;
// this.oldVisibility = this.childLayer ? this.childLayer.visible : null;
}
async execute() {
if (!this.childLayer) {
throw new Error("找不到要切换可见性的子图层");
}
// 切换可见性
this.childLayer.visible = !this.childLayer.visible;
// 更新画布上图层对象的可见性
if (this.canvas) {
const layerObjects = this.canvas
.getObjects()
.filter((obj) => obj.layerId === this.layerId);
layerObjects.forEach((obj) => {
obj.visible = this.childLayer.visible;
});
}
// 更新画布上对象的可选择状态
await this.layerManager?.updateLayersObjectsInteractivity();
return this.childLayer.visible;
}
async undo() {
return await this.execute(); // 直接调用execute方法来恢复可见性
}
getInfo() {
return {
name: this.name,
layerName: this.childLayer?.name || "未知子图层",
layerId: this.layerId,
parentId: this.parentId,
newVisibility: this.childLayer?.visible,
};
}
}
/**
* 重命名图层命令
*/
@@ -1031,9 +1106,9 @@ export class GroupLayersCommand extends Command {
// 备份原图层
this.originalLayers = [...this.layers.value];
// 新组ID
this.groupId = `group_layer_${Date.now()}_${Math.floor(
Math.random() * 1000
)}`;
this.groupId =
generateId("group_layer_") ||
`group_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
this.originalActiveLayerId = this.activeLayerId.value; // 备份原活动图层ID
}
@@ -1097,6 +1172,8 @@ export class GroupLayersCommand extends Command {
// 更新当前活动图层
this.activeLayerId.value = this.layerIds[0];
this.canvas?.thumbnailManager?.generateLayerThumbnail?.(this.groupId);
return this.groupId;
}
@@ -2199,9 +2276,9 @@ export class LayerObjectsToGroupCommand extends Command {
* @private
*/
_updateThumbnail() {
if (this.canvas.thumbnailManager) {
this.canvas.thumbnailManager.generateLayerThumbnail(this.activeLayer.id);
}
// this.canvas?.thumbnailManager?.generateLayerThumbnail?.(
// this.activeLayer.id
// );
}
getInfo() {
@@ -2232,8 +2309,12 @@ export class CreateImageLayerCommand extends Command {
this.toolManager = options.toolManager;
this.layerName = options.layerName || null;
this.imageId = generateId("image_");
// 存储执行过程中的结果
this.newLayerId = null;
this.newLayerId =
generateId("layer_image_") ||
`layer_image_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
this.commands = [];
this.executedCommands = [];
}
@@ -2251,12 +2332,15 @@ export class CreateImageLayerCommand extends Command {
const fileName =
this.layerName || `图片 ${new Date().toLocaleTimeString()}`;
this.fabricImage.set({
id: this.imageId,
});
// 1. 创建新图层命令
const createLayerCmd = new AddLayerCommand({
canvas: this.layerManager.canvas,
layers: this.layerManager.layers,
newLayer: createLayer({
id: this.newLayerId || generateId("layer"),
id: this.newLayerId,
name: fileName,
type: LayerType.BITMAP,
visible: true,
@@ -2658,6 +2742,11 @@ export class CutLayerCommand extends Command {
this.cutLayer = null;
this.clipboardData = null;
this.wasActiveLayer = false;
// 生成新图层ID和名称
this.newLayerId =
generateId("layer_") ||
`layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
}
async execute() {
@@ -2678,9 +2767,6 @@ export class CutLayerCommand extends Command {
console.warn("不能复制背景图层");
return null;
}
// 生成新图层ID和名称
this.newLayerId = `layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
const newName = `${sourceLayer.name} copy`;
// 创建新图层
@@ -2781,100 +2867,6 @@ export class CutLayerCommand extends Command {
await this.layerManager?.updateLayersObjectsInteractivity(false);
}
getInfo() {
return {
name: this.name,
sourceLayerId: this.layerId,
newLayerId: this.newLayerId,
newLayerName: this.newLayer?.name,
objectCount: this.createdObjects.length,
isChildLayer: this.isChildLayer,
parentLayerId: this.parentLayer?.id,
};
}
}
/**
* 复制图层到指定位置命令
*/
export class DuplicateLayerCommand extends Command {
constructor(options) {
super({
name: "复制图层",
saveState: true,
});
this.canvas = options.canvas;
this.layers = options.layers;
this.layerId = options.layerId;
this.activeLayerId = options.activeLayerId;
this.insertIndex = options.insertIndex || null;
this.layerManager = options.layerManager;
this.newLayer = null;
this.newLayerId = null;
this.createdObjects = [];
}
async execute() {
const { layer } = findLayerRecursively(this.layers.value, this.layerId);
const sourceLayer = layer;
if (!sourceLayer) {
console.error(`源图层 ${this.layerId} 不存在`);
return null;
}
// 不允许复制背景图层
if (sourceLayer.isBackground) {
console.warn("不能复制背景图层");
return null;
}
// 生成新图层ID和名称
this.newLayerId = `layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
const newName = `${sourceLayer.name} copy`;
// 创建新图层
this.newLayer = createLayer({
id: this.newLayerId,
name: newName,
type: sourceLayer.type,
visible: sourceLayer.visible,
locked: sourceLayer.locked,
opacity: sourceLayer.opacity,
blendMode: sourceLayer.blendMode,
fabricObjects: [],
children: sourceLayer.children ? [...sourceLayer.children] : [],
layerProperties: sourceLayer.layerProperties
? { ...sourceLayer.layerProperties }
: {},
metadata: sourceLayer.metadata ? { ...sourceLayer.metadata } : {},
});
// 计算插入位置
const sourceIndex = this.layers.value.findIndex(
(l) => l.id === this.layerId
);
const insertIndex =
this.insertIndex !== null ? this.insertIndex : sourceIndex + 1;
// 插入新图层
this.layers.value.splice(insertIndex, 0, this.newLayer);
// 复制源图层中的对象
if (sourceLayer.fabricObjects && sourceLayer.fabricObjects.length > 0) {
await this._duplicateObjects(sourceLayer.fabricObjects);
}
// 设置为活动图层
this.activeLayerId.value = this.newLayerId;
// 重新渲染画布
await this.layerManager?.updateLayersObjectsInteractivity(false);
console.log(`已复制图层:${newName}`);
return this.newLayerId;
}
async _duplicateObjects(sourceObjects) {
const serializedObjects = sourceObjects.map((obj) => {
// 序列化对象时保留必要的属性
@@ -2914,27 +2906,6 @@ export class DuplicateLayerCommand extends Command {
});
}
async undo() {
if (!this.newLayer) return;
// 从图层列表中删除新图层
const index = this.layers.value.findIndex((l) => l.id === this.newLayerId);
if (index !== -1) {
this.layers.value.splice(index, 1);
}
// 从画布中移除所有创建的对象
this.createdObjects.forEach((obj) => {
this.canvas.remove(obj);
});
// 恢复原活动图层
this.activeLayerId.value = this.layerId;
// 重新渲染画布
await this.layerManager?.updateLayersObjectsInteractivity(false);
}
getInfo() {
return {
name: this.name,
@@ -2942,6 +2913,8 @@ export class DuplicateLayerCommand extends Command {
newLayerId: this.newLayerId,
newLayerName: this.newLayer?.name,
objectCount: this.createdObjects.length,
isChildLayer: this.isChildLayer,
parentLayerId: this.parentLayer?.id,
};
}
}
@@ -2963,15 +2936,13 @@ export class CreateAdjustmentLayerCommand extends Command {
this.insertIndex = options.insertIndex || null;
this.newLayer = null;
this.newLayerId = null;
// 生成新图层ID
this.newLayerId =
generateId("adj_layer_") ||
`adj_layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
}
execute() {
// 生成新图层ID
this.newLayerId = `adj_layer_${Date.now()}_${Math.floor(
Math.random() * 1000
)}`;
// 创建调整图层
this.newLayer = createLayer({
id: this.newLayerId,
@@ -3959,6 +3930,10 @@ export class RemoveChildLayerCommand extends Command {
) ?? -1;
this.removedChild = this.parentLayer?.children?.[this.childIndex];
this.isActiveLayer = this.layerId === this.activeLayerId.value;
this.originalObjects = this.canvas.getObjects().filter((obj) => {
return obj.layerId === this.layerId;
});
}
async execute() {
@@ -3972,8 +3947,9 @@ export class RemoveChildLayerCommand extends Command {
this.removedChild.fabricObjects.length > 0
) {
this.removedChild.fabricObjects.forEach((obj) => {
if (this.canvas.getObjects().includes(obj)) {
this.canvas.remove(obj);
const { object } = findObjectById(this.canvas, obj.id);
if (object) {
this.canvas.remove(...this.originalObjects);
}
});
}
@@ -4001,29 +3977,34 @@ export class RemoveChildLayerCommand extends Command {
}
async undo() {
if (!this.parentLayer || this.childIndex === -1 || !this.removedChild)
if (
!this.parentLayer ||
this.childIndex === -1 ||
!this.removedChild ||
this.originalObjects.length === 0
) {
return;
}
// 恢复子图层到原位置
this.parentLayer.children.splice(this.childIndex, 0, this.removedChild);
// 恢复子图层中的所有对象到画布
if (
this.removedChild.fabricObjects &&
this.removedChild.fabricObjects.length > 0
) {
this.removedChild.fabricObjects.forEach((obj) => {
optimizeCanvasRendering(this.canvas, async () => {
this.originalObjects.forEach((obj) => {
// 恢复对象到画布
this.canvas.add(obj);
// 恢复对象的图层信息
obj.layerId = this.layerId;
obj.layerName = this.removedChild.name;
obj.setCoords(); // 更新坐标
});
}
// 如果是原活动图层,恢复活动图层
if (this.isActiveLayer) {
this.activeLayerId.value = this.layerId;
}
// 如果是原活动图层,恢复活动图层
if (this.isActiveLayer) {
this.activeLayerId.value = this.layerId;
}
// 重新渲染画布
await this.layerManager?.updateLayersObjectsInteractivity();
// 重新渲染画布
await this.layerManager?.updateLayersObjectsInteractivity(false);
});
}
getInfo() {
@@ -4117,6 +4098,7 @@ export class ChildLayerLockCommand extends Command {
this.layers = options.layers;
this.layerId = options.layerId;
this.parentId = options.parentId;
this.layerManager = options.layerManager;
// 查找父图层和子图层
const { layer, parent } = findLayerRecursively(
@@ -4163,61 +4145,3 @@ export class ChildLayerLockCommand extends Command {
};
}
}
/**
* 切换子图层可见性命令
*/
export class ToggleChildLayerVisibilityCommand extends Command {
constructor(options) {
super({
name: "切换子图层可见性",
saveState: false,
});
this.canvas = options.canvas;
this.layers = options.layers;
this.layerId = options.layerId;
this.parentId = options.parentId;
// 查找父图层和子图层
const { layer, parent } = findLayerRecursively(
this.layers.value,
this.layerId
);
this.parentLayer = parent;
this.childLayer = layer;
this.oldVisibility = this.childLayer ? this.childLayer.visible : null;
}
async execute() {
if (!this.childLayer) {
throw new Error("找不到要切换可见性的子图层");
}
// 切换可见性
this.childLayer.visible = !this.oldVisibility;
// 更新画布上对象的可选择状态
await this.layerManager?.updateLayersObjectsInteractivity();
return true;
}
async undo() {
if (this.childLayer) {
this.childLayer.visible = this.oldVisibility;
// 更新画布上对象的可选择状态
await this.layerManager?.updateLayersObjectsInteractivity();
}
}
getInfo() {
return {
name: this.name,
layerName: this.childLayer?.name || "未知子图层",
layerId: this.layerId,
parentId: this.parentId,
newVisibility: this.childLayer?.visible,
};
}
}