feat: 优化跨层级移动和套索抠图命令,支持异步执行,改进画布刷新逻辑,新增背景裁剪选项

This commit is contained in:
bighuixiang
2025-07-11 00:26:38 +08:00
parent d3e22f368b
commit 96e13cb22a
10 changed files with 129 additions and 121 deletions

View File

@@ -977,7 +977,6 @@ export class CanvasManager {
}
this.layers.value = tempLayers;
debugger;
// this.canvasWidth.value = parsedJson.canvasWidth || this.width;
// this.canvasHeight.value = parsedJson.canvasHeight || this.height;
@@ -1039,8 +1038,10 @@ export class CanvasManager {
// 使用LayerSort工具重新排列画布对象如果可用
await this?.layerManager?.layerSort?.rearrangeObjects();
this.layerManager.activeLayerId.value =
this.layers.value[0]?.id || parsedJson?.activeLayerId || null;
this.layerManager.activeLayerId.value = this.layers.value[0]
.children?.length
? this.layers.value[0].children[0].id
: this.layers.value[0]?.id || parsedJson?.activeLayerId || null;
// // 如果检测到红绿图模式内容,进行缩放调整
// if (this.enabledRedGreenMode) {

View File

@@ -28,6 +28,7 @@ export class ExportManager {
const {
isContainBg = false,
isContainFixed = false,
isCropByBg = false, // 是否使用背景大小裁剪
layerId = "",
layerIdArray = [],
expPicType = "png",
@@ -43,7 +44,8 @@ export class ExportManager {
layerId,
expPicType,
isRedGreenMode,
restoreOpacityInRedGreen
restoreOpacityInRedGreen,
isCropByBg
);
}
@@ -52,10 +54,11 @@ export class ExportManager {
return this._exportMultipleLayers(
layerIdArray,
expPicType,
isContainBg,
isContainFixed,
isRedGreenMode,
restoreOpacityInRedGreen
restoreOpacityInRedGreen,
isContainBg,
isCropByBg
);
}
@@ -65,7 +68,8 @@ export class ExportManager {
isContainBg,
isContainFixed,
isRedGreenMode,
restoreOpacityInRedGreen
restoreOpacityInRedGreen,
isCropByBg
);
} catch (error) {
console.error("导出图片失败:", error);
@@ -143,7 +147,8 @@ export class ExportManager {
isContainBg,
isContainFixed,
isRedGreenMode,
restoreOpacityInRedGreen
restoreOpacityInRedGreen,
isCropByBg
) {
if (!this.layerManager) {
throw new Error("图层管理器未初始化");
@@ -193,7 +198,8 @@ export class ExportManager {
isContainBg,
isContainFixed,
isRedGreenMode,
restoreOpacityInRedGreen
restoreOpacityInRedGreen,
isCropByBg
) {
// 按图层顺序收集对象(从底到顶)
const objectsToExport = this._collectObjectsByLayerOrder(
@@ -215,13 +221,38 @@ export class ExportManager {
restoreOpacityInRedGreen
);
}
let canvasClipPath = this.canvas.clipPath;
if (isCropByBg) {
const cropWidth =
this.canvasManager?.canvasWidth?.value ||
this.canvas?.canvasWidth ||
this.canvas.width;
const cropHeight =
this.canvasManager?.canvasHeight?.value ||
this.canvas?.canvasHeight ||
this.canvas.height;
canvasClipPath = new fabric.Rect({
left: this.canvas.width / 2,
top: this.canvas.height / 2,
width: cropWidth,
height: cropHeight,
originX: "center",
originY: "center",
fill: "#fff",
stroke: "transparent",
strokeWidth: 0,
});
canvasClipPath.set({
absolutePositioned: true,
});
canvasClipPath.setCoords();
}
// 普通模式使用画布尺寸
return this._exportWithCanvasSize(
objectsToExport,
expPicType,
restoreOpacityInRedGreen,
this.canvas.clipPath
canvasClipPath
);
}

View File

@@ -336,9 +336,10 @@ export class LayerManager {
// 设置裁剪对象
layers.forEach(async (layer) => {
let clippingMaskFabricObject = null;
if (layer.clippingMask) {
// 反序列化 clippingMask
const clippingMaskFabricObject = await restoreFabricObject(
clippingMaskFabricObject = await restoreFabricObject(
layer.clippingMask,
this.canvas
);
@@ -349,80 +350,30 @@ export class LayerManager {
// ...getOriginObjectInfo(layer.clippingMask), // 恢复原定位
absolutePositioned: true,
});
// const activeObject = this.canvas.getActiveObject();
// if (activeObject?._objects?.length > 1) {
// const { object } = findObjectById(
// this.canvas,
// layer.clippingMask?.id
// );
// if (!object) return;
// const tempClipPath = fabric.util.object.clone(object);
// tempClipPath.clipPath = null;
// tempClipPath.set({
// // 设置绝对定位
// ...getOriginObjectInfo(layer.clippingMask), // 恢复原定位
// absolutePositioned: true,
// });
// activeObject.clipPath = tempClipPath;
// // 确保选择组正确渲染
// // activeObject.setCoords();
// console.log(activeObject?._objects?.length);
// return; // 如果是多选对象,则不设置裁剪路径
// }
// 如果是组图层 则给所有子对象设置裁剪对象
if (layer.type === LayerType.GROUP || layer.children?.length > 0) {
layer.children.forEach((childLayer) => {
if (clippingMaskFabricObject) {
const childObj = this.canvas
.getObjects()
.find((o) => o.layerId === childLayer.id);
if (childObj) {
childObj.clipPath = clippingMaskFabricObject;
}
}
// const { object } = findObjectById(
// this.canvas,
// layer.clippingMask?.id
// );
// if (object) {
// const tempClipPath = fabric.util.object.clone(object);
// tempClipPath.clipPath = null;
// tempClipPath.set({
// // 设置绝对定位
// // ...layer.clippingMask, // 恢复原定位
// ...getOriginObjectInfo(layer.clippingMask),
// absolutePositioned: true,
// });
// const childObj = this.canvas
// .getObjects()
// .find((o) => o.layerId === childLayer.id);
// if (childObj) {
// childObj.clipPath = tempClipPath;
// }
// }
});
} else if (clippingMaskFabricObject) {
obj.clipPath = clippingMaskFabricObject;
}
// {
// // const { object } = findObjectById(
// // this.canvas,
// // layer.clippingMask?.id
// // );
// // if (object) {
// // const tempClipPath = fabric.util.object.clone(object);
// // tempClipPath.clipPath = null; // 确保克隆的遮罩没有clipPath
// // tempClipPath.set({
// // // 设置绝对定位
// // // ...layer.clippingMask, // 恢复原定位
// // ...getOriginObjectInfo(layer.clippingMask),
// // absolutePositioned: true,
// // });
// // obj.clipPath = tempClipPath;
// // }
// }
}
// 如果是组图层 则给所有子对象设置裁剪对象
if (layer.type === LayerType.GROUP || layer.children?.length > 0) {
layer.children.forEach((childLayer) => {
const childObj = this.canvas
.getObjects()
.find((o) => o.layerId === childLayer.id);
if (childObj) {
childObj.clipPath = clippingMaskFabricObject;
childObj.dirty = true; // 标记为脏对象
childObj.setCoords();
}
});
} else {
layer.fabricObjects?.forEach((obj) => {
const fabricObject = this.canvas
.getObjects()
.find((o) => o.id === obj.id);
if (fabricObject) {
fabricObject.clipPath = clippingMaskFabricObject;
fabricObject.dirty = true; // 标记为脏对象
fabricObject.setCoords();
}
});
}
});
}