合并画布

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

@@ -66,11 +66,13 @@ export class CanvasManager {
// 初始化缩略图管理器
this.thumbnailManager = new ThumbnailManager(this.canvas, {
// 可以根据需求自定义选项
layerThumbSize: { width: 32, height: 32 },
elementThumbSize: { width: 32, height: 24 },
// layerThumbSize: { width: 32, height: 32 },
// elementThumbSize: { width: 32, height: 24 },
layers: this.layers,
});
this.canvas.thumbnailManager = this.thumbnailManager; // 将缩略图管理器绑定到画布
// 设置画布辅助线
initAligningGuidelines(this.canvas);
@@ -110,6 +112,8 @@ export class CanvasManager {
activeLayer,
});
this.thumbnailManager?.generateLayerThumbnail(activeLayer.id);
// 返回true表示不要自动添加到画布因为我们已经通过图层管理器处理了
return true;
} else {
@@ -147,6 +151,10 @@ export class CanvasManager {
// 更新交互性
command &&
(await this.layerManager?.updateLayersObjectsInteractivity?.());
this.thumbnailManager?.generateLayerThumbnail(
this.layerManager?.activeLayerId?.value
);
});
}
@@ -340,9 +348,9 @@ export class CanvasManager {
* 重置视图变换,使元素回到原始位置
* @private
*/
_resetViewportTransform() {
_resetViewportTransform(zoom) {
// 保存当前缩放值
const currentZoom = this.canvas.getZoom();
const currentZoom = zoom ?? this.canvas.getZoom();
// 重置视图变换,但保留缩放级别
this.canvas.setViewportTransform([currentZoom, 0, 0, currentZoom, 0, 0]);
@@ -370,6 +378,14 @@ export class CanvasManager {
// 获取背景对象
const backgroundObject = visibleObjects.find((obj) => obj.isBackground);
this.canvas?.clipPath?.set?.({
left: this.width / 2,
top: this.height / 2,
originX: "center",
originY: "center",
});
this.canvas?.clipPath?.setCoords?.();
// 如果只有背景层或没有背景层,使用原有逻辑
if (!backgroundObject) {
console.warn("未找到背景层,使用默认居中逻辑");
@@ -462,9 +478,12 @@ export class CanvasManager {
setCanvasColor(color) {
this.backgroundColor = color;
this.canvas.setBackgroundColor(
color,
this.canvas.renderAll.bind(this.canvas)
// this.canvas.setBackgroundColor(
// color,
// this.canvas.renderAll.bind(this.canvas)
// );
this.thumbnailManager?.generateLayerThumbnail?.(
this.layers?.value.find((layer) => layer.isBackground)?.id
);
}
@@ -615,80 +634,15 @@ export class CanvasManager {
* @param {String} layerId 图层ID
*/
updateLayerThumbnail(layerId) {
if (!this.thumbnailManager || !layerId || !this.layers) return;
const layer = this.layers.value.find((l) => l.id === layerId);
if (layer) {
this.thumbnailManager.generateLayerThumbnail(layer);
}
}
/**
* 更新指定元素图层的缩略图
* @param {String} elementId 元素ID
* @param {Object} fabricObject fabric对象
*/
updateElementThumbnail(elementId, fabricObject) {
if (this.eventManager) {
this.eventManager.updateElementThumbnail(elementId, fabricObject);
} else if (
this.thumbnailManager &&
elementId &&
fabricObject &&
this.layers
) {
// 查找对应的图层(现在元素就是图层)
const layer = this.layers.value.find(
(l) =>
l.id === elementId ||
(l.fabricObject && l.fabricObject.id === elementId)
);
if (layer) {
// 生成图层缩略图
this.thumbnailManager.generateLayerThumbnail(layer);
}
// 同时也维护元素缩略图,以保持向后兼容性
this.thumbnailManager.generateElementThumbnail(
{ id: elementId, type: fabricObject.type },
fabricObject
);
}
this.thumbnailManager?.generateLayerThumbnail?.(layerId);
}
/**
* 更新所有图层和元素的缩略图
*/
updateAllThumbnails() {
if (!this.thumbnailManager || !this.layers) return;
this.thumbnailManager.generateAllLayerThumbnails(this.layers.value);
// 为所有元素生成缩略图
this.layers.value.forEach((layer) => {
// 如果是分组图层,处理子图层
if (isGroupLayer(layer) && layer.children) {
layer.children.forEach((childLayerId) => {
const childLayer = this.layers.value.find(
(l) => l.id === childLayerId
);
if (childLayer && childLayer.fabricObject) {
this.thumbnailManager.generateElementThumbnail(
{ id: childLayer.id, type: childLayer.fabricObject.type },
childLayer.fabricObject
);
}
});
}
// 如果是元素图层,则直接生成缩略图
else if (layer.isElementLayer && layer.fabricObject) {
this.thumbnailManager.generateElementThumbnail(
{ id: layer.id, type: layer.fabricObject.type },
layer.fabricObject
);
}
});
this.thumbnailManager?.generateAllLayerThumbnails?.(this.layers.value);
}
/**
@@ -710,6 +664,7 @@ export class CanvasManager {
layerManager: this.layerManager,
imageUrl: imageUrl,
targetLayerType: options.targetLayerType || "fixed", // background/fixed
options: options,
});
command.undoable =
@@ -812,110 +767,72 @@ export class CanvasManager {
getJSON() {
// // 简化图层数据在loadJSON时要根据id恢复引用
// let tempLayers = this.layers ? this.layers.value : [];
// // 创建对象ID映射表用于快速查找
// tempLayers = tempLayers.map((layer) => {
// const newLayer = { ...layer };
// // 处理fabricObjects数组
// if (Array.isArray(layer.fabricObjects)) {
// newLayer.fabricObjects = layer.fabricObjects
// .map((item) => {
// if (!item) return null;
// // 确保对象有ID
// if (!item.id) {
// item.id = `obj_${Date.now()}_${Math.floor(
// Math.random() * 10000
// )}`;
// }
// const simplifyLayers = (layers) => {
// return layers.map((layer) => {
// if (layer?.children?.length) {
// layer.children = layer.children.map((child) => {
// return {
// id: item.id,
// type: item.type || "object", // 保存类型信息用于调试
// id: child.id,
// type: child.type,
// layerId: child.layerId,
// layerName: child.layerName,
// isBackground: child.isBackground,
// isLocked: child.isLocked,
// isVisible: child.isVisible,
// isFixed: child.isFixed,
// parentId: child.parentId,
// fabricObject: child.fabricObject
// ? {
// id: child.fabricObject.id,
// type: child.fabricObject.type,
// layerId: child.fabricObject.layerId,
// layerName: child.fabricObject.layerName,
// }
// : {},
// fabricObjects:
// child.fabricObjects?.map((obj) => ({
// id: obj.id,
// type: obj.type,
// layerId: obj.layerId,
// layerName: obj.layerName,
// })) || [],
// };
// })
// .filter((item) => item !== null);
// } else {
// newLayer.fabricObjects = [];
// }
// if (layer.clippingMask) {
// layer.clippingMask = {
// id: layer.clippingMask.id,
// };
// }
// // 处理单个fabricObject
// if (layer.fabricObject) {
// if (!layer.fabricObject.id) {
// layer.fabricObject.id = `obj_${Date.now()}_${Math.floor(
// Math.random() * 10000
// )}`;
// });
// }
// newLayer.fabricObject = {
// id: layer.fabricObject.id,
// type: layer.fabricObject.type || "object",
// return {
// id: layer.id,
// type: layer.type,
// layerId: layer.layerId,
// layerName: layer.layerName,
// isBackground: layer.isBackground,
// isLocked: layer.isLocked,
// isVisible: layer.isVisible,
// isFixed: layer.isFixed,
// parentId: layer.parentId,
// fabricObject: child.fabricObject
// ? {
// id: child.fabricObject.id,
// type: child.fabricObject.type,
// layerId: child.fabricObject.layerId,
// layerName: child.fabricObject.layerName,
// }
// : {},
// fabricObjects:
// child.fabricObjects?.map((obj) => ({
// id: obj.id,
// type: obj.type,
// layerId: obj.layerId,
// layerName: obj.layerName,
// })) || [],
// children: layer.children,
// };
// } else {
// newLayer.fabricObject = null;
// }
// // 处理子图层
// if (Array.isArray(layer.children)) {
// newLayer.children = layer.children.map((cItem) => {
// const newChild = { ...cItem };
// // 处理子图层的fabricObjects
// if (Array.isArray(cItem.fabricObjects)) {
// newChild.fabricObjects = cItem.fabricObjects
// .map((item) => {
// if (!item) return null;
// if (!item.id) {
// item.id = `obj_${Date.now()}_${Math.floor(
// Math.random() * 10000
// )}`;
// }
// return {
// id: item.id,
// type: item.type || "object",
// };
// })
// .filter((item) => item !== null);
// } else {
// newChild.fabricObjects = [];
// }
// // 处理子图层的fabricObject
// if (cItem.fabricObject) {
// if (!cItem.fabricObject.id) {
// cItem.fabricObject.id = `obj_${Date.now()}_${Math.floor(
// Math.random() * 10000
// )}`;
// }
// newChild.fabricObject = {
// id: cItem.fabricObject.id,
// type: cItem.fabricObject.type || "object",
// };
// } else {
// newChild.fabricObject = null;
// }
// return newChild;
// });
// } else {
// newLayer.children = [];
// }
// return newLayer;
// });
// });
// };
try {
console.log(
"获取画布JSON数据...",
simplifyLayers(JSON.parse(JSON.stringify(this.layers.value)))
const simplifyLayersData = simplifyLayers(
JSON.parse(JSON.stringify(this.layers.value))
);
console.log("获取画布JSON数据...", simplifyLayersData);
return JSON.stringify({
canvas: this.canvas.toJSON([
"id",
@@ -931,15 +848,14 @@ export class CanvasManager {
"eraserable",
"erasable",
]),
layers: JSON.stringify(
simplifyLayers(JSON.parse(JSON.stringify(this.layers.value)))
), // 简化图层数据
layers: JSON.stringify(simplifyLayersData), // 简化图层数据
// layers: JSON.stringify(JSON.parse(JSON.stringify(this.layers.value))), // 全数据
version: "1.0", // 添加版本信息
timestamp: new Date().toISOString(), // 添加时间戳
canvasWidth: this.canvasWidth.value,
canvasHeight: this.canvasHeight.value,
canvasColor: this.canvasColor.value,
activeLayerId: this.canvas.activeLayerId.value,
activeLayerId: this.layerManager?.activeLayerId?.value,
});
} catch (error) {
console.error("获取画布JSON失败:", error);
@@ -960,7 +876,7 @@ export class CanvasManager {
try {
const parsedJson = JSON.parse(json);
return new Promise((resolve, reject) => {
return new Promise(async (resolve, reject) => {
const tempLayers = JSON.parse(parsedJson?.layers) || [];
const canvasData = parsedJson?.canvas;
@@ -983,19 +899,43 @@ export class CanvasManager {
console.log("是否检测到红绿图模式内容:", this.enabledRedGreenMode);
// 重置视图变换以确保元素位置正确
this._resetViewportTransform();
this._resetViewportTransform(1);
let canvasClipPath = null;
// 克隆当前裁剪路径
if (this.canvas?.clipPath) {
canvasClipPath = this.canvas?.clipPath;
}
// 清除当前画布内容
this.canvas.clear();
console.log("清除当前画布内容", canvasData);
delete canvasData.clipPath; // 删除当前裁剪路径
// 加载画布数据
this.canvas.loadFromJSON(canvasData, async () => {
await optimizeCanvasRendering(this.canvas, async () => {
// 清空重做栈
this.commandManager?.clear?.();
this.backgroundColor = parsedJson.backgroundColor || "#ffffff";
if (canvasClipPath) {
// canvasClipPath.set({
// absolutePositioned: true,
// });
this.canvas.clipPath = canvasClipPath;
// await new Promise((resolve) => {
// debugger;
// fabric.util.enlivenObjects([canvasClipPath], (clipPaths) => {
// if (clipPaths && clipPaths.length > 0) {
// resolve(clipPaths[0]);
// } else {
// resolve(null);
// }
// });
// });
// debugger;
}
try {
// 重置画布数据
this.setCanvasSize(this.canvas.width, this.canvas.height);
// 重新构建对象关系
restoreObjectLayerAssociations(
this.layers.value,
@@ -1010,8 +950,8 @@ export class CanvasManager {
console.log("图层关联验证结果:", isValidate);
this.canvas.activeLayerId.value =
parsedJson?.activeLayerId || this.layers.value[0]?.id || null;
this.layerManager.activeLayerId.value =
this.layers.value[0]?.id || parsedJson?.activeLayerId || null;
// // 如果检测到红绿图模式内容,进行缩放调整
// if (this.enabledRedGreenMode) {
@@ -1026,12 +966,11 @@ export class CanvasManager {
false
);
console.log(this.layerManager.layers.value);
debugger;
// 更新所有缩略图
setTimeout(() => {
this.updateAllThumbnails();
}, 100);
}, 500);
console.log("画布JSON数据加载完成");
resolve();