feat: 优化填充组图层背景命令,支持实时更新和撤销功能,改进填充对象的处理逻辑
This commit is contained in:
@@ -7,11 +7,12 @@ import {
|
|||||||
insertObjectAtZIndex,
|
insertObjectAtZIndex,
|
||||||
removeCanvasObjectByObject,
|
removeCanvasObjectByObject,
|
||||||
} from "../utils/helper";
|
} from "../utils/helper";
|
||||||
|
import { restoreFabricObject } from "../utils/objectHelper";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 填充组图层背景命令
|
* 填充组图层背景命令
|
||||||
*/
|
*/
|
||||||
export class FillLayerBackgroundCommand extends Command {
|
export class FillGroupLayerBackgroundCommand extends Command {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super({ name: "填充组图层背景", saveState: true });
|
super({ name: "填充组图层背景", saveState: true });
|
||||||
this.canvas = options.canvas;
|
this.canvas = options.canvas;
|
||||||
@@ -30,54 +31,85 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
this.group = null;
|
this.group = null;
|
||||||
|
|
||||||
this.originalfabricObjects = this._collectOriginalObjects(); // 记录所有的原始对象
|
this.originalfabricObjects = this._collectOriginalObjects(); // 记录所有的原始对象
|
||||||
|
|
||||||
|
// 计算所有对象的边界
|
||||||
|
this.originalInfo = this._getCurrentObjectsBoundingRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute() {
|
async execute() {
|
||||||
const layer = this.layer;
|
const layer = this.layer;
|
||||||
// 只允许填充背景层或普通图层
|
|
||||||
if (!layer.isBackground && !layer.isFixed && !layer.fabricObjects?.length) return false;
|
if (!layer.isBackground && !layer.isFixed && !layer.fabricObjects?.length) return false;
|
||||||
|
|
||||||
// 记录原填充色
|
|
||||||
this.oldFill = layer.fill ?? null;
|
this.oldFill = layer.fill ?? null;
|
||||||
this.oldFillColor = layer.oldFillColor ?? null;
|
this.oldFillColor = layer.oldFillColor ?? null;
|
||||||
|
|
||||||
// 更新fabric对象填充
|
// 构建填充对象
|
||||||
// 判断是否有遮罩层 有遮罩使用遮罩层大小 否则使用第一个大小
|
let clippingMaskFabricObject = null;
|
||||||
const originalInfo =
|
if (layer.clippingMask) {
|
||||||
findObjectById(this.canvas.value, layer.fabricObjects?.[0]?.id)?.object?.getBoundingRect?.(
|
clippingMaskFabricObject = await restoreFabricObject(layer.clippingMask, this.canvas);
|
||||||
true,
|
clippingMaskFabricObject.clipPath = null;
|
||||||
true
|
clippingMaskFabricObject.set({ absolutePositioned: true });
|
||||||
) ||
|
this.newFill = new fabric.Rect({
|
||||||
layer?.clippingMask ||
|
width: clippingMaskFabricObject.width,
|
||||||
layer.fabricObjects?.[0];
|
height: clippingMaskFabricObject.height,
|
||||||
|
left: clippingMaskFabricObject.left || 0,
|
||||||
|
top: clippingMaskFabricObject.top || 0,
|
||||||
|
fill: this.fillColor,
|
||||||
|
layerId: this.layerId,
|
||||||
|
id: this.oldFill?.id || generateId("fill-"),
|
||||||
|
selectable: false,
|
||||||
|
evented: false,
|
||||||
|
originX: clippingMaskFabricObject.originX || "center",
|
||||||
|
originY: clippingMaskFabricObject.originY || "center",
|
||||||
|
scaleX: clippingMaskFabricObject.scaleX || 1,
|
||||||
|
scaleY: clippingMaskFabricObject.scaleY || 1,
|
||||||
|
// type: "fill",
|
||||||
|
});
|
||||||
|
this.newFill.clipPath = clippingMaskFabricObject;
|
||||||
|
// this.newFill.dirty = true;
|
||||||
|
// this.newFill.setCoords();
|
||||||
|
} else {
|
||||||
|
const originalInfo = this.originalInfo;
|
||||||
|
if (originalInfo) {
|
||||||
this.newFill = new fabric.Rect({
|
this.newFill = new fabric.Rect({
|
||||||
width: originalInfo.width,
|
width: originalInfo.width,
|
||||||
height: originalInfo.height,
|
height: originalInfo.height,
|
||||||
left: originalInfo.left || 0,
|
left: originalInfo.left + originalInfo.width / 2 || 0,
|
||||||
top: originalInfo.top || 0,
|
top: originalInfo.top + originalInfo.height / 2 || 0,
|
||||||
fill: this.fillColor,
|
fill: this.fillColor,
|
||||||
layerId: this.layerId,
|
layerId: this.layerId,
|
||||||
id: generateId("fill-"),
|
id: this.oldFill?.id || generateId("fill-"),
|
||||||
selectable: false,
|
selectable: false,
|
||||||
evented: false,
|
evented: false,
|
||||||
originX: originalInfo.originX || "center",
|
originX: "center",
|
||||||
originY: originalInfo.originY || "center",
|
originY: "center",
|
||||||
scaleX: originalInfo.scaleX || 1,
|
// type: "fill",
|
||||||
scaleY: originalInfo.scaleY || 1,
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 判断fabricObjects是否是组,是组则添加填充到最前面,否则创建组
|
// 判断fabricObjects是否是组对象
|
||||||
if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
const firstObj = layer.fabricObjects?.[0];
|
||||||
// 如果是组,直接添加到组中
|
const canvasObj = findObjectById(this.canvas, firstObj?.id)?.object;
|
||||||
// 否则创建一个新的组 插入到原本的图层对象前面
|
if ((canvasObj && canvasObj.type === "group") || canvasObj._objects?.length > 0) {
|
||||||
const layerObjects = this.canvas
|
this.newFill.set({
|
||||||
.getObjects()
|
left: 0,
|
||||||
.reverse()
|
top: 0,
|
||||||
.filter((obj) => obj.layerId === this.layerId);
|
});
|
||||||
let insertIndex =
|
// 将新填充对象添加到组的最前面
|
||||||
this.canvas.getObjects()?.findIndex((obj) => obj.id === layer.fabricObjects?.[0]?.id) || 0;
|
// canvasObj._objects.unshift(this.newFill);
|
||||||
insertIndex = insertIndex == -1 ? 0 : insertIndex;
|
canvasObj.insertAt(this.newFill, 0, false);
|
||||||
|
// canvasObj.addWithUpdate();
|
||||||
|
canvasObj.setCoords();
|
||||||
|
canvasObj.setObjectsCoords();
|
||||||
|
// canvasObj.dirty = true; // 标记为脏对象
|
||||||
|
// this.canvas.renderAll();
|
||||||
|
// this.group = canvasObj;
|
||||||
|
} else if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
||||||
|
// 普通对象,组成新组
|
||||||
|
const layerObjects = this.canvas.getObjects().filter((obj) => obj.layerId === this.layerId);
|
||||||
|
let insertIndex = this.canvas.getObjects()?.findIndex((obj) => obj.id === firstObj?.id) ?? 0;
|
||||||
|
insertIndex = insertIndex === -1 ? 0 : insertIndex;
|
||||||
|
|
||||||
this.group = new fabric.Group([this.newFill, ...layerObjects]);
|
this.group = new fabric.Group([this.newFill, ...layerObjects]);
|
||||||
this.group.set({
|
this.group.set({
|
||||||
@@ -85,29 +117,47 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
layerId: layerObjects[0]?.layerId,
|
layerId: layerObjects[0]?.layerId,
|
||||||
});
|
});
|
||||||
this.group.setCoords();
|
this.group.setCoords();
|
||||||
layer.fabricObjects = [this.group?.toObject?.(["id", "layerId"]) || this.group];
|
removeCanvasObjectByObject(this.canvas, layerObjects[0]);
|
||||||
removeCanvasObjectByObject(this.canvas, layer.fabricObjects[0]);
|
insertObjectAtZIndex(this.canvas, this.group, insertIndex, false);
|
||||||
|
|
||||||
insertObjectAtZIndex(this.canvas, this.group, insertIndex, false); // 插入到画布的指定位置
|
|
||||||
// 将新填充对象添加到画布
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// layer.fabricObjects = [this.group?.toObject?.(["id", "layerId"]) || this.group];
|
||||||
this.canvas.renderAll();
|
this.canvas.renderAll();
|
||||||
|
layer.fill = null; // this.newFill.toObject(["id", "layerId"]);
|
||||||
layer.fill = this.newFill.toObject(["id", "layerId"]);
|
|
||||||
layer.fillColor = this.fillColor;
|
layer.fillColor = this.fillColor;
|
||||||
|
|
||||||
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async undo() {
|
async undo() {
|
||||||
this.layer.fillColor = this.oldFillColor;
|
this.layer.fillColor = this.oldFillColor;
|
||||||
this.layer.fill = this.oldFill;
|
this.layer.fill = this.oldFill;
|
||||||
|
|
||||||
this.group.removeWithUpdate(this.newFill);
|
// 判断fabricObjects是否是组对象
|
||||||
this.canvas.remove(this.newFill);
|
const firstObj = this.layer.fabricObjects?.[0];
|
||||||
|
const canvasObj = this.group || findObjectById(this.canvas, firstObj?.id)?.object;
|
||||||
|
|
||||||
|
if ((canvasObj && canvasObj.type === "group") || canvasObj?._objects?.length > 0) {
|
||||||
|
// 移除新添加的填充对象
|
||||||
|
if (canvasObj._objects?.[0] === this.newFill) {
|
||||||
|
canvasObj._objects.shift();
|
||||||
|
canvasObj.addWithUpdate();
|
||||||
|
canvasObj.setCoords();
|
||||||
|
canvasObj.dirty = true;
|
||||||
|
}
|
||||||
this.canvas.renderAll();
|
this.canvas.renderAll();
|
||||||
|
} else if (this.group) {
|
||||||
|
// 如果是新建的group,需要拆分还原
|
||||||
|
// 先移除新建的group
|
||||||
|
this.canvas.remove(this.group);
|
||||||
|
// 重新添加原始对象
|
||||||
|
this.originalfabricObjects.forEach((obj) => {
|
||||||
|
if (!this.canvas.getObjects().includes(obj)) {
|
||||||
|
this.canvas.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.canvas.renderAll();
|
||||||
|
this.group = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
||||||
return true;
|
return true;
|
||||||
@@ -131,4 +181,30 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 获取当前所有对象的边界信息
|
||||||
|
_getCurrentObjectsBoundingRect() {
|
||||||
|
// this.originalfabricObjects = this._collectOriginalObjects();
|
||||||
|
let minLeft = Infinity,
|
||||||
|
minTop = Infinity,
|
||||||
|
maxRight = -Infinity,
|
||||||
|
maxBottom = -Infinity;
|
||||||
|
console.log("计算当前所有对象的边界信息:===>", this.originalfabricObjects.length);
|
||||||
|
this.originalfabricObjects?.forEach((obj) => {
|
||||||
|
const { object } = findObjectById(this.canvas, obj.id) || {};
|
||||||
|
if (object) {
|
||||||
|
const rect = object.getBoundingRect({ absolute: true, includeStroke: false });
|
||||||
|
minLeft = Math.min(minLeft, rect.left);
|
||||||
|
minTop = Math.min(minTop, rect.top);
|
||||||
|
maxRight = Math.max(maxRight, rect.left + rect.width);
|
||||||
|
maxBottom = Math.max(maxBottom, rect.top + rect.height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (minLeft === Infinity || minTop === Infinity) return null;
|
||||||
|
return {
|
||||||
|
left: minLeft,
|
||||||
|
top: minTop,
|
||||||
|
width: maxRight - minLeft,
|
||||||
|
height: maxBottom - minTop,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
this.canvasManager = options.canvasManager;
|
this.canvasManager = options.canvasManager;
|
||||||
this.layerId = options.layerId;
|
this.layerId = options.layerId;
|
||||||
this.fillColor = options.fillColor;
|
this.fillColor = options.fillColor;
|
||||||
|
this.isRetimeUpdate = options.isRetimeUpdate; // 是否实时更新
|
||||||
this.oldFill = null;
|
this.oldFill = null;
|
||||||
this.oldFillColor = null;
|
this.oldFillColor = null;
|
||||||
this.newFill = null;
|
this.newFill = null;
|
||||||
@@ -33,6 +34,8 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
this.isGroupLayer = layer.isGroup || !!layer.children?.length || false; // 是否为组图层
|
this.isGroupLayer = layer.isGroup || !!layer.children?.length || false; // 是否为组图层
|
||||||
|
|
||||||
this.originalfabricObjects = this._collectOriginalObjects(); // 记录所有的原始对象
|
this.originalfabricObjects = this._collectOriginalObjects(); // 记录所有的原始对象
|
||||||
|
// 计算所有对象的边界
|
||||||
|
this.originalInfo = this._getCurrentObjectsBoundingRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute() {
|
async execute() {
|
||||||
@@ -45,31 +48,11 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
this.oldFillColor = layer.oldFillColor ?? null;
|
this.oldFillColor = layer.oldFillColor ?? null;
|
||||||
|
|
||||||
// 更新fabric对象填充
|
// 更新fabric对象填充
|
||||||
// 判断是否有遮罩层 有遮罩使用遮罩层大小 否则使用第一个大小
|
// 1.如果图层有遮罩则用遮罩 2.如果没有遮罩则汇总当前fabricObjects下的所有对象的边界
|
||||||
const { object } = findObjectById(this.canvas, layer.fabricObjects?.[0]?.id);
|
let clippingMaskFabricObject = null;
|
||||||
|
|
||||||
if (object) {
|
|
||||||
const originalInfo = object?.getBoundingRect?.(true, true);
|
|
||||||
this.newFill = new fabric.Rect({
|
|
||||||
width: originalInfo.width,
|
|
||||||
height: originalInfo.height,
|
|
||||||
left: originalInfo.left || 0,
|
|
||||||
top: originalInfo.top || 0,
|
|
||||||
fill: this.fillColor,
|
|
||||||
layerId: this.layerId,
|
|
||||||
id: generateId("fill-"),
|
|
||||||
selectable: false,
|
|
||||||
evented: false,
|
|
||||||
originX: object.originX || "center",
|
|
||||||
originY: object.originY || "center",
|
|
||||||
scaleX: object.scaleX || 1,
|
|
||||||
scaleY: object.scaleY || 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layer.clippingMask) {
|
if (layer.clippingMask) {
|
||||||
// 反序列化 clippingMask
|
// 反序列化 clippingMask
|
||||||
const clippingMaskFabricObject = await restoreFabricObject(layer.clippingMask, this.canvas);
|
clippingMaskFabricObject = await restoreFabricObject(layer.clippingMask, this.canvas);
|
||||||
clippingMaskFabricObject.clipPath = null;
|
clippingMaskFabricObject.clipPath = null;
|
||||||
|
|
||||||
clippingMaskFabricObject.set({
|
clippingMaskFabricObject.set({
|
||||||
@@ -85,40 +68,51 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
top: clippingMaskFabricObject.top || 0,
|
top: clippingMaskFabricObject.top || 0,
|
||||||
fill: this.fillColor,
|
fill: this.fillColor,
|
||||||
layerId: this.layerId,
|
layerId: this.layerId,
|
||||||
id: generateId("fill-"),
|
id: this.oldFill?.id || generateId("fill-"),
|
||||||
selectable: false,
|
selectable: false,
|
||||||
evented: false,
|
evented: false,
|
||||||
originX: clippingMaskFabricObject.originX || "center",
|
originX: clippingMaskFabricObject.originX || "center",
|
||||||
originY: clippingMaskFabricObject.originY || "center",
|
originY: clippingMaskFabricObject.originY || "center",
|
||||||
scaleX: clippingMaskFabricObject.scaleX || 1,
|
scaleX: clippingMaskFabricObject.scaleX || 1,
|
||||||
scaleY: clippingMaskFabricObject.scaleY || 1,
|
scaleY: clippingMaskFabricObject.scaleY || 1,
|
||||||
|
type: "fill",
|
||||||
});
|
});
|
||||||
|
|
||||||
this.newFill.clipPath = clippingMaskFabricObject; // 设置填充的遮罩
|
this.newFill.clipPath = clippingMaskFabricObject; // 设置填充的遮罩
|
||||||
this.newFill.dirty = true; // 标记为脏,以便重新渲染
|
this.newFill.dirty = true; // 标记为脏,以便重新渲染
|
||||||
this.newFill.setCoords();
|
this.newFill.setCoords();
|
||||||
|
} else {
|
||||||
|
const originalInfo = this.originalInfo;
|
||||||
|
if (originalInfo) {
|
||||||
|
this.newFill = new fabric.Rect({
|
||||||
|
width: originalInfo.width,
|
||||||
|
height: originalInfo.height,
|
||||||
|
left: originalInfo.left + originalInfo.width / 2 || 0,
|
||||||
|
top: originalInfo.top + originalInfo.height / 2 || 0,
|
||||||
|
fill: this.fillColor,
|
||||||
|
layerId: this.layerId,
|
||||||
|
id: this.oldFill?.id || generateId("fill-"),
|
||||||
|
selectable: false,
|
||||||
|
evented: false,
|
||||||
|
originX: "center",
|
||||||
|
originY: "center",
|
||||||
|
type: "fill",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断fabricObjects是否是组,是组则添加填充到最前面,否则创建组
|
// 判断fabricObjects是否是组,是组则添加填充到最前面,否则创建组
|
||||||
if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
||||||
// 如果是组,直接添加到组中
|
|
||||||
// 否则创建一个新的组 插入到原本的图层对象前面
|
|
||||||
// const layerObjects = this.canvas
|
|
||||||
// .getObjects()
|
|
||||||
// .reverse()
|
|
||||||
// .filter((obj) => obj.layerId === this.layerId);
|
|
||||||
let insertIndex =
|
let insertIndex =
|
||||||
this.canvas.getObjects()?.findIndex((obj) => obj.id === layer.fabricObjects?.[0]?.id) || 0;
|
this.canvas.getObjects()?.findIndex((obj) => obj.id === layer.fabricObjects?.[0]?.id) || 0;
|
||||||
|
if (this.oldFill) {
|
||||||
|
// 如果有旧填充,先获取旧的索引再移除旧填充
|
||||||
|
insertIndex =
|
||||||
|
this.canvas.getObjects()?.findIndex((obj) => obj.id === this.oldFill?.id) || 0;
|
||||||
|
removeCanvasObjectByObject(this.canvas, this.oldFill);
|
||||||
|
}
|
||||||
insertIndex = insertIndex == -1 ? 0 : insertIndex;
|
insertIndex = insertIndex == -1 ? 0 : insertIndex;
|
||||||
|
// layer.fabricObjects = [this.newFill?.toObject?.(["id", "layerId"]) || this.newFill];
|
||||||
// this.group = new fabric.Group([this.newFill, ...layerObjects]);
|
|
||||||
// this.group.set({
|
|
||||||
// id: layerObjects[0]?.id || generateId("group-"),
|
|
||||||
// layerId: layerObjects[0]?.layerId,
|
|
||||||
// });
|
|
||||||
// this.group.setCoords();
|
|
||||||
layer.fabricObjects = [this.newFill?.toObject?.(["id", "layerId"]) || this.newFill];
|
|
||||||
// removeCanvasObjectByObject(this.canvas, layer.fabricObjects[0]);
|
|
||||||
insertObjectAtZIndex(this.canvas, this.newFill, insertIndex, false); // 插入到画布的指定位置
|
insertObjectAtZIndex(this.canvas, this.newFill, insertIndex, false); // 插入到画布的指定位置
|
||||||
// 将新填充对象添加到画布
|
// 将新填充对象添加到画布
|
||||||
} else if (layer.children && layer.children.length > 0) {
|
} else if (layer.children && layer.children.length > 0) {
|
||||||
@@ -130,6 +124,13 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
(obj) =>
|
(obj) =>
|
||||||
obj.id === this.originalfabricObjects[this.originalfabricObjects.length - 1]?.id
|
obj.id === this.originalfabricObjects[this.originalfabricObjects.length - 1]?.id
|
||||||
) || 0;
|
) || 0;
|
||||||
|
|
||||||
|
if (this.oldFill) {
|
||||||
|
// 如果有旧填充,先获取旧的索引再移除旧填充
|
||||||
|
insertIndex =
|
||||||
|
this.canvas.getObjects()?.findIndex((obj) => obj.id === this.oldFill?.id) || 0;
|
||||||
|
removeCanvasObjectByObject(this.canvas, this.oldFill);
|
||||||
|
}
|
||||||
insertIndex = insertIndex == -1 ? 0 : insertIndex;
|
insertIndex = insertIndex == -1 ? 0 : insertIndex;
|
||||||
|
|
||||||
insertObjectAtZIndex(this.canvas, this.newFill, insertIndex, false); // 插入到画布的指定位置
|
insertObjectAtZIndex(this.canvas, this.newFill, insertIndex, false); // 插入到画布的指定位置
|
||||||
@@ -137,25 +138,43 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
|
|
||||||
this.canvas.renderAll();
|
this.canvas.renderAll();
|
||||||
|
|
||||||
|
// 实时更新的时候不生成缩略图
|
||||||
|
if (!this.isRetimeUpdate) {
|
||||||
layer.fill = this.newFill.toObject(["id", "layerId"]);
|
layer.fill = this.newFill.toObject(["id", "layerId"]);
|
||||||
layer.fillColor = this.fillColor;
|
layer.fillColor = this.fillColor;
|
||||||
|
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
||||||
|
|
||||||
// 重新排序
|
// 重新排序
|
||||||
// 使用LayerSort工具重新排列画布对象(如果可用)
|
// 使用LayerSort工具重新排列画布对象(如果可用)
|
||||||
await this?.canvasManager?.layerManager?.layerSort?.rearrangeObjects?.();
|
// await this?.canvasManager?.layerManager?.layerSort?.rearrangeObjects?.();
|
||||||
|
}
|
||||||
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async undo() {
|
async undo() {
|
||||||
this.layer.fillColor = this.oldFillColor;
|
// this.group.removeWithUpdate(this.newFill);
|
||||||
this.layer.fill = this.oldFill;
|
// this.canvas.remove(this.newFill);
|
||||||
|
if (this.oldFill) {
|
||||||
this.group.removeWithUpdate(this.newFill);
|
// 如果有旧填充,恢复旧填充
|
||||||
this.canvas.remove(this.newFill);
|
const { object } = findObjectById(this.canvas, this.oldFill.id);
|
||||||
|
if (object) {
|
||||||
|
this.newFill.set({
|
||||||
|
fill: this.oldFill.fill,
|
||||||
|
left: this.oldFill.left,
|
||||||
|
top: this.oldFill.top,
|
||||||
|
width: this.oldFill.width,
|
||||||
|
height: this.oldFill.height,
|
||||||
|
});
|
||||||
|
this.newFill.setCoords();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有旧填充,移除新填充
|
||||||
|
removeCanvasObjectByObject(this.canvas, this.layer.fill);
|
||||||
|
}
|
||||||
this.canvas.renderAll();
|
this.canvas.renderAll();
|
||||||
|
|
||||||
|
this.layer.fillColor = this.oldFillColor;
|
||||||
|
this.layer.fill = this.oldFill;
|
||||||
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -178,4 +197,30 @@ export class FillLayerBackgroundCommand extends Command {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 获取当前所有对象的边界信息
|
||||||
|
_getCurrentObjectsBoundingRect() {
|
||||||
|
// this.originalfabricObjects = this._collectOriginalObjects();
|
||||||
|
let minLeft = Infinity,
|
||||||
|
minTop = Infinity,
|
||||||
|
maxRight = -Infinity,
|
||||||
|
maxBottom = -Infinity;
|
||||||
|
console.log("计算当前所有对象的边界信息:===>", this.originalfabricObjects.length);
|
||||||
|
this.originalfabricObjects?.forEach((obj) => {
|
||||||
|
const { object } = findObjectById(this.canvas, obj.id) || {};
|
||||||
|
if (object) {
|
||||||
|
const rect = object.getBoundingRect({ absolute: true, includeStroke: false });
|
||||||
|
minLeft = Math.min(minLeft, rect.left);
|
||||||
|
minTop = Math.min(minTop, rect.top);
|
||||||
|
maxRight = Math.max(maxRight, rect.left + rect.width);
|
||||||
|
maxBottom = Math.max(maxBottom, rect.top + rect.height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (minLeft === Infinity || minTop === Infinity) return null;
|
||||||
|
return {
|
||||||
|
left: minLeft,
|
||||||
|
top: minTop,
|
||||||
|
width: maxRight - minLeft,
|
||||||
|
height: maxBottom - minTop,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,18 +228,18 @@ export class RasterizeLayerCommand extends Command {
|
|||||||
const objectsWithZIndex = [];
|
const objectsWithZIndex = [];
|
||||||
|
|
||||||
this.layersToRasterize.forEach((layer) => {
|
this.layersToRasterize.forEach((layer) => {
|
||||||
if (layer.fill) {
|
// if (layer.fill) {
|
||||||
const { object } = findObjectById(this.canvas, layer.fill.id);
|
// const { object } = findObjectById(this.canvas, layer.fill.id);
|
||||||
if (object) {
|
// if (object) {
|
||||||
// 获取对象在画布中的z-index(数组索引)
|
// // 获取对象在画布中的z-index(数组索引)
|
||||||
const zIndex = allCanvasObjects.indexOf(object);
|
// const zIndex = allCanvasObjects.indexOf(object);
|
||||||
objectsWithZIndex.push({
|
// objectsWithZIndex.push({
|
||||||
object: object,
|
// object: object,
|
||||||
zIndex: zIndex,
|
// zIndex: zIndex,
|
||||||
layerObj: layer.fill,
|
// layerObj: layer.fill,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
||||||
layer.fabricObjects.forEach((layerObj) => {
|
layer.fabricObjects.forEach((layerObj) => {
|
||||||
if (layerObj && layerObj.id) {
|
if (layerObj && layerObj.id) {
|
||||||
@@ -532,18 +532,18 @@ export class ExportLayerToImageCommand extends Command {
|
|||||||
const objectsWithZIndex = [];
|
const objectsWithZIndex = [];
|
||||||
|
|
||||||
this.layersToRasterize.forEach((layer) => {
|
this.layersToRasterize.forEach((layer) => {
|
||||||
if (layer.fill) {
|
// if (layer.fill) {
|
||||||
const { object } = findObjectById(this.canvas, layer.fill.id);
|
// const { object } = findObjectById(this.canvas, layer.fill.id);
|
||||||
if (object) {
|
// if (object) {
|
||||||
// 获取对象在画布中的z-index(数组索引)
|
// // 获取对象在画布中的z-index(数组索引)
|
||||||
const zIndex = allCanvasObjects.indexOf(object);
|
// const zIndex = allCanvasObjects.indexOf(object);
|
||||||
objectsWithZIndex.push({
|
// objectsWithZIndex.push({
|
||||||
object: object,
|
// object: object,
|
||||||
zIndex: zIndex,
|
// zIndex: zIndex,
|
||||||
layerObj: layer.fill,
|
// layerObj: layer.fill,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
||||||
layer.fabricObjects.forEach((layerObj) => {
|
layer.fabricObjects.forEach((layerObj) => {
|
||||||
if (layerObj && layerObj.id) {
|
if (layerObj && layerObj.id) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, nextTick, inject } from "vue";
|
import { computed, ref, nextTick, inject, watch } from "vue";
|
||||||
import { findLayerRecursively, isGroupLayer } from "../../utils/layerHelper";
|
import { findLayerRecursively, isGroupLayer } from "../../utils/layerHelper";
|
||||||
import ContextMenu from "./ContextMenu.vue";
|
import ContextMenu from "./ContextMenu.vue";
|
||||||
import LayerItem from "./LayerItem.vue";
|
import LayerItem from "./LayerItem.vue";
|
||||||
@@ -13,6 +13,7 @@ import { createCrossLevelMoveCommand } from "../../commands/CrossLevelMoveComman
|
|||||||
// UngroupLayersCommand,
|
// UngroupLayersCommand,
|
||||||
// } from "../../commands/LayerCommands";
|
// } from "../../commands/LayerCommands";
|
||||||
import { findObjectById, generateId } from "../../utils/helper";
|
import { findObjectById, generateId } from "../../utils/helper";
|
||||||
|
import { throttle } from "lodash-es";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
// layers: Array,
|
// layers: Array,
|
||||||
@@ -70,6 +71,7 @@ const contextMenuLayer = ref(null);
|
|||||||
const contextMenuItems = ref([]);
|
const contextMenuItems = ref([]);
|
||||||
|
|
||||||
// 颜色填充相关
|
// 颜色填充相关
|
||||||
|
const currLayerId = ref(null); // 当前图层ID
|
||||||
const fillColor = ref("#ffffff"); // 默认填充颜色
|
const fillColor = ref("#ffffff"); // 默认填充颜色
|
||||||
const fillColorRef = ref(null);
|
const fillColorRef = ref(null);
|
||||||
|
|
||||||
@@ -652,22 +654,28 @@ function buildContextMenuItems(layer) {
|
|||||||
{
|
{
|
||||||
label: "填充图层",
|
label: "填充图层",
|
||||||
icon: "CThemeColor",
|
icon: "CThemeColor",
|
||||||
disabled: layer.isBackground || layer.isFixed || !layerManager?.canRasterizeLayer?.(layer.id),
|
disabled:
|
||||||
|
layer.isBackground ||
|
||||||
|
layer.isFixed ||
|
||||||
|
!layerManager?.canRasterizeLayer?.(layer.id) ||
|
||||||
|
layer.isGroup ||
|
||||||
|
layer?.children?.length > 0, // 如果是组图层或有子图层则禁用
|
||||||
action: () => {
|
action: () => {
|
||||||
// 调用浏览器原生颜色选择器
|
// 调用浏览器原生颜色选择器
|
||||||
fillColorRef.value.click();
|
fillColorRef.value.click();
|
||||||
// 监听颜色选择器的变化
|
currLayerId.value = layer.id;
|
||||||
fillColorRef.value.addEventListener("change", () => {
|
// // 监听颜色选择器的变化
|
||||||
const selectedColor = fillColor.value;
|
// fillColorRef.value.addEventListener("change", () => {
|
||||||
layerManager
|
// const selectedColor = fillColor.value;
|
||||||
.fillLayerBackground(layer.id, selectedColor)
|
// layerManager
|
||||||
.then(() => {
|
// .fillLayerBackground(layer.id, selectedColor)
|
||||||
console.log(`✅ 已填充图层 ${layer.name} 背景颜色: ${selectedColor}`);
|
// .then(() => {
|
||||||
})
|
// console.log(`✅ 已填充图层 ${layer.name} 背景颜色: ${selectedColor}`);
|
||||||
.catch((error) => {
|
// })
|
||||||
console.error(`❌ 填充图层 ${layer.name} 背景颜色失败:`, error);
|
// .catch((error) => {
|
||||||
});
|
// console.error(`❌ 填充图层 ${layer.name} 背景颜色失败:`, error);
|
||||||
});
|
// });
|
||||||
|
// });
|
||||||
// 隐藏右键菜单
|
// 隐藏右键菜单
|
||||||
hideContextMenu();
|
hideContextMenu();
|
||||||
},
|
},
|
||||||
@@ -790,6 +798,11 @@ function buildContextMenuItems(layer) {
|
|||||||
].filter((item) => item !== null);
|
].filter((item) => item !== null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 填充颜色选择器
|
||||||
|
function fillColorChange() {
|
||||||
|
layerManager.fillLayerBackground(currLayerId.value, fillColor.value, true);
|
||||||
|
}
|
||||||
|
|
||||||
// 右键菜单操作方法
|
// 右键菜单操作方法
|
||||||
function copySelectedLayers() {
|
function copySelectedLayers() {
|
||||||
const selectedLayers = getSelectedLayers();
|
const selectedLayers = getSelectedLayers();
|
||||||
@@ -806,6 +819,25 @@ function copySelectedLayers() {
|
|||||||
hideContextMenu();
|
hideContextMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// watch(fillColor, (newColor) => {
|
||||||
|
// // 使用loadash-es 节流函数
|
||||||
|
// // 使用throttle节流 控制更新评率
|
||||||
|
// if (currLayerId.value) {
|
||||||
|
// throttle(() => {
|
||||||
|
// if (layerManager && layerManager.fillLayerBackground) {
|
||||||
|
// layerManager
|
||||||
|
// .fillLayerBackground(currLayerId.value, newColor, false)
|
||||||
|
// .then(() => {
|
||||||
|
// console.log(`✅ 已填充图层 ${currLayerId.value} 背景颜色: ${newColor}`);
|
||||||
|
// })
|
||||||
|
// .catch((error) => {
|
||||||
|
// console.error(`❌ 填充图层 ${currLayerId.value} 背景颜色失败:`, error);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }, 300)(); // 每300毫秒执行一次
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
function toggleSelectedLayersLock() {
|
function toggleSelectedLayersLock() {
|
||||||
const selectedLayers = getSelectedLayers();
|
const selectedLayers = getSelectedLayers();
|
||||||
if (selectedLayers.length === 0) return;
|
if (selectedLayers.length === 0) return;
|
||||||
@@ -1477,6 +1509,15 @@ async function moveGroupToGroup(draggedLayer, fromParentId, toParentId, newIndex
|
|||||||
<template>
|
<template>
|
||||||
<div class="layers-panel-inner" @click="handlePanelClick">
|
<div class="layers-panel-inner" @click="handlePanelClick">
|
||||||
<div class="layers-header">
|
<div class="layers-header">
|
||||||
|
<!-- 颜色填充选择组件 -->
|
||||||
|
<input
|
||||||
|
class="fillColor-input"
|
||||||
|
v-model="fillColor"
|
||||||
|
ref="fillColorRef"
|
||||||
|
type="color"
|
||||||
|
@change="fillColorChange"
|
||||||
|
style="width: 0; height: 0; opacity: 0"
|
||||||
|
/>
|
||||||
<h3>
|
<h3>
|
||||||
{{ $t("图层") }}
|
{{ $t("图层") }}
|
||||||
{{ selectedLayerIds.length > 0 ? `(${selectedLayerIds.length})` : "" }}
|
{{ selectedLayerIds.length > 0 ? `(${selectedLayerIds.length})` : "" }}
|
||||||
@@ -1619,9 +1660,6 @@ async function moveGroupToGroup(draggedLayer, fromParentId, toParentId, newIndex
|
|||||||
:items="contextMenuItems"
|
:items="contextMenuItems"
|
||||||
@close="hideContextMenu"
|
@close="hideContextMenu"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 颜色填充选择组件 -->
|
|
||||||
<input v-model="fillColor" ref="fillColorRef" type="color" style="display: none" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { FillGroupLayerBackgroundCommand } from "../commands/FillGroupLayerBackgroundCommand";
|
||||||
import { FillLayerBackgroundCommand } from "../commands/FillLayerBackgroundCommand";
|
import { FillLayerBackgroundCommand } from "../commands/FillLayerBackgroundCommand";
|
||||||
|
|
||||||
export class BackgroundFillManager {
|
export class BackgroundFillManager {
|
||||||
@@ -12,15 +13,21 @@ export class BackgroundFillManager {
|
|||||||
* 填充指定图层背景
|
* 填充指定图层背景
|
||||||
* @param {string} layerId 图层ID
|
* @param {string} layerId 图层ID
|
||||||
* @param {string} fillColor 填充颜色
|
* @param {string} fillColor 填充颜色
|
||||||
|
* @param {boolean} undoable 是否可撤销
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async fillLayerBackground(layerId, fillColor) {
|
async fillLayerBackground(layerId, fillColor, undoable) {
|
||||||
const command = new FillLayerBackgroundCommand({
|
const command = new FillGroupLayerBackgroundCommand({
|
||||||
canvas: this.canvas,
|
canvas: this.canvas,
|
||||||
layers: this.layers,
|
layers: this.layers,
|
||||||
layerId,
|
layerId,
|
||||||
fillColor,
|
fillColor,
|
||||||
canvasManager: this.canvasManager,
|
canvasManager: this.canvasManager,
|
||||||
|
// 是否实时更新
|
||||||
|
isRetimeUpdate: !undoable,
|
||||||
});
|
});
|
||||||
|
command.undoable = undoable;
|
||||||
|
|
||||||
if (this.commandManager) {
|
if (this.commandManager) {
|
||||||
await this.commandManager.execute(command);
|
await this.commandManager.execute(command);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -340,14 +340,14 @@ export class LayerManager {
|
|||||||
}
|
}
|
||||||
// 如果是组图层 则给所有子对象设置裁剪对象
|
// 如果是组图层 则给所有子对象设置裁剪对象
|
||||||
if (layer.type === LayerType.GROUP || layer.children?.length > 0) {
|
if (layer.type === LayerType.GROUP || layer.children?.length > 0) {
|
||||||
if (layer.fill) {
|
// if (layer.fill) {
|
||||||
const fabricObject = this.canvas.getObjects().find((o) => o.id === layer.fill.id);
|
// const fabricObject = this.canvas.getObjects().find((o) => o.id === layer.fill.id);
|
||||||
if (fabricObject) {
|
// if (fabricObject) {
|
||||||
fabricObject.clipPath = clippingMaskFabricObject;
|
// fabricObject.clipPath = clippingMaskFabricObject;
|
||||||
fabricObject.dirty = true; // 标记为脏对象
|
// fabricObject.dirty = true; // 标记为脏对象
|
||||||
fabricObject.setCoords();
|
// fabricObject.setCoords();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
layer.children.forEach((childLayer) => {
|
layer.children.forEach((childLayer) => {
|
||||||
const childObj = this.canvas.getObjects().find((o) => o.layerId === childLayer.id);
|
const childObj = this.canvas.getObjects().find((o) => o.layerId === childLayer.id);
|
||||||
if (childObj) {
|
if (childObj) {
|
||||||
@@ -356,14 +356,14 @@ export class LayerManager {
|
|||||||
childObj.setCoords();
|
childObj.setCoords();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (childLayer.fill) {
|
// if (childLayer.fill) {
|
||||||
const fabricObject = this.canvas.getObjects().find((o) => o.id === childLayer.fill.id);
|
// const fabricObject = this.canvas.getObjects().find((o) => o.id === childLayer.fill.id);
|
||||||
if (fabricObject) {
|
// if (fabricObject) {
|
||||||
fabricObject.clipPath = clippingMaskFabricObject;
|
// fabricObject.clipPath = clippingMaskFabricObject;
|
||||||
fabricObject.dirty = true; // 标记为脏对象
|
// fabricObject.dirty = true; // 标记为脏对象
|
||||||
fabricObject.setCoords();
|
// fabricObject.setCoords();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
layer.fabricObjects?.forEach((obj) => {
|
layer.fabricObjects?.forEach((obj) => {
|
||||||
@@ -375,14 +375,14 @@ export class LayerManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (layer.fill) {
|
// if (layer.fill) {
|
||||||
const fabricObject = this.canvas.getObjects().find((o) => o.id === layer.fill.id);
|
// const fabricObject = this.canvas.getObjects().find((o) => o.id === layer.fill.id);
|
||||||
if (fabricObject) {
|
// if (fabricObject) {
|
||||||
fabricObject.clipPath = clippingMaskFabricObject;
|
// fabricObject.clipPath = clippingMaskFabricObject;
|
||||||
fabricObject.dirty = true; // 标记为脏对象
|
// fabricObject.dirty = true; // 标记为脏对象
|
||||||
fabricObject.setCoords();
|
// fabricObject.setCoords();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -391,9 +391,10 @@ export class LayerManager {
|
|||||||
* 填充图层背景
|
* 填充图层背景
|
||||||
* @param {string} layerId 图层ID
|
* @param {string} layerId 图层ID
|
||||||
* @param {string} fillColor 填充颜色
|
* @param {string} fillColor 填充颜色
|
||||||
|
* @param {boolean} undoable 是否可撤销
|
||||||
*/
|
*/
|
||||||
async fillLayerBackground(layerId, fillColor) {
|
async fillLayerBackground(layerId, fillColor, undoable = true) {
|
||||||
await this.backgroundFillManager.fillLayerBackground(layerId, fillColor);
|
await this.backgroundFillManager.fillLayerBackground(layerId, fillColor, undoable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -963,13 +964,13 @@ export class LayerManager {
|
|||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (layer.fill) {
|
// if (layer.fill) {
|
||||||
// 如果图层有填充颜色,设置所有对象的填充颜色
|
// // 如果图层有填充颜色,设置所有对象的填充颜色
|
||||||
const { object } = findObjectById(this.canvas, layer.fill.id);
|
// const { object } = findObjectById(this.canvas, layer.fill.id);
|
||||||
if (object) {
|
// if (object) {
|
||||||
allObjects.push(object);
|
// allObjects.push(object);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (allObjects.length) {
|
if (allObjects.length) {
|
||||||
// 切换到选择模式
|
// 切换到选择模式
|
||||||
|
|||||||
@@ -143,18 +143,18 @@ export class ThumbnailManager {
|
|||||||
const objectsWithZIndex = [];
|
const objectsWithZIndex = [];
|
||||||
|
|
||||||
layersToRasterize.forEach((layer) => {
|
layersToRasterize.forEach((layer) => {
|
||||||
if (layer.fill) {
|
// if (layer.fill) {
|
||||||
const { object } = findObjectById(this.canvas, layer.fill.id);
|
// const { object } = findObjectById(this.canvas, layer.fill.id);
|
||||||
if (object) {
|
// if (object) {
|
||||||
// 获取对象在画布中的z-index(数组索引)
|
// // 获取对象在画布中的z-index(数组索引)
|
||||||
const zIndex = allCanvasObjects.indexOf(object);
|
// const zIndex = allCanvasObjects.indexOf(object);
|
||||||
objectsWithZIndex.push({
|
// objectsWithZIndex.push({
|
||||||
object: object,
|
// object: object,
|
||||||
zIndex: zIndex,
|
// zIndex: zIndex,
|
||||||
layerObj: layer.fill,
|
// layerObj: layer.fill,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (layer.fabricObject) {
|
if (layer.fabricObject) {
|
||||||
// 如果图层本身有fabricObject,直接添加
|
// 如果图层本身有fabricObject,直接添加
|
||||||
|
|||||||
@@ -96,10 +96,10 @@ export class LayerSort {
|
|||||||
* @returns {number} 更新后的z-index
|
* @returns {number} 更新后的z-index
|
||||||
*/
|
*/
|
||||||
processLayerObjects(layer, currentZIndex, zIndexMap) {
|
processLayerObjects(layer, currentZIndex, zIndexMap) {
|
||||||
if (layer.fill) {
|
// if (layer.fill) {
|
||||||
// 如果图层有填充,则填充在最底层
|
// // 如果图层有填充,则填充在最底层
|
||||||
zIndexMap.set(layer.fill.id, currentZIndex++);
|
// zIndexMap.set(layer.fill.id, currentZIndex++);
|
||||||
}
|
// }
|
||||||
// 检查是否有子图层(组图层)
|
// 检查是否有子图层(组图层)
|
||||||
if (layer.children?.length > 0) {
|
if (layer.children?.length > 0) {
|
||||||
// 处理每个子图层
|
// 处理每个子图层
|
||||||
|
|||||||
@@ -391,13 +391,17 @@ const createRasterizedImageWithMask = async ({
|
|||||||
*/
|
*/
|
||||||
const cloneObjectAsync = (obj) => {
|
const cloneObjectAsync = (obj) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
obj.clone((cloned) => {
|
try {
|
||||||
|
obj?.clone?.((cloned) => {
|
||||||
if (cloned) {
|
if (cloned) {
|
||||||
resolve(cloned);
|
resolve(cloned);
|
||||||
} else {
|
} else {
|
||||||
reject(new Error("对象克隆失败"));
|
reject(new Error("对象克隆失败"));
|
||||||
}
|
}
|
||||||
});
|
}, {});
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error(`克隆对象时发生错误: ${error.message}`));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user