import { isArray } from "lodash-es"; /** * 图层关联工具类 * 提供图层与画布对象关联管理的通用方法 */ /** * 构建单个图层与画布对象的关联关系 * @param {Object} layer 图层对象 * @param {Array} canvasObjects 画布对象数组 */ export function buildLayerAssociations(layer, canvasObjects) { if (!layer || !canvasObjects || !isArray(canvasObjects)) return; // 处理单个fabricObject关联 if (layer.fabricObject) { // 如果图层已经有关联的fabricObject,确保它的layerId和layerName正确 layer.fabricObject = canvasObjects.find((obj) => obj.id === layer.fabricObject.id) || null; } if (layer.clippingMask) { // clippingMask 可能是一个fabricObject或组 const clippingMaskObj = canvasObjects.find( (obj) => obj.id === layer.clippingMask.id ); layer.clippingMask = clippingMaskObj?.toObject?.(["id"]) || null; } // 处理多个fabricObjects关联 if (layer.fabricObjects && isArray(layer.fabricObjects)) { layer.fabricObjects = layer.fabricObjects .map((fabricObject) => { // 确保每个fabricObject的layerId和layerName正确 const obj = canvasObjects.find((obj) => obj.id === fabricObject.id); if (obj) { obj.layerId = layer.id; // 确保对象的layerId正确 obj.layerName = layer.name; // 确保对象的layerName正确 return obj; } return null; // 如果没有找到对象,返回null }) .filter((obj) => obj !== null); // 过滤掉null值 } } /** * 恢复对象与图层的关联关系 * @param {Object} layerManager 图层管理器实例 * @param {Array} canvasObjects 画布对象数组 */ export function restoreObjectLayerAssociations(layers, canvasObjects) { if (!layers || !canvasObjects || !isArray(canvasObjects)) return; layers.forEach((layer) => { buildLayerAssociations(layer, canvasObjects); // 处理子图层 if (layer?.children?.length) { restoreObjectLayerAssociations(layer.children, canvasObjects); } }); } /** * 为画布对象设置图层信息 * @param {Object} fabricObject 画布对象 * @param {Object} layer 图层对象 */ export function setObjectLayerInfo(fabricObject, layer) { if (!fabricObject || !layer) return; fabricObject.layerId = layer.id; fabricObject.layerName = layer.name; } /** * 清除画布对象的图层信息 * @param {Object} fabricObject 画布对象 */ export function clearObjectLayerInfo(fabricObject) { if (!fabricObject) return; delete fabricObject.layerId; delete fabricObject.layerName; } /** * 验证图层关联关系的完整性 * @param {Object} layerManager 图层管理器实例 * @param {fabric.Canvas} canvas 画布实例 * @returns {Object} 验证结果 { valid: boolean, issues: Array } */ export function validateLayerAssociations(layers, canvasObjects) { const issues = []; // 检查画布对象是否都有对应的图层 canvasObjects.forEach((obj) => { if (obj.layerId) { const layer = layers.find((l) => l.id === obj.layerId); if (!layer) { issues.push({ type: "orphaned_object", objectId: obj.id, layerId: obj.layerId, message: `对象 ${obj.id} 关联的图层 ${obj.layerId} 不存在`, }); } } else { issues.push({ type: "missing_layer_id", objectId: obj.id, message: `对象 ${obj.id} 缺少图层ID关联`, }); } }); // 检查图层是否都有对应的画布对象 layers.forEach((layer) => { if (layer.fabricObject && layer.fabricObject.id) { const obj = canvasObjects.find((o) => o.id === layer.fabricObject.id); if (!obj) { issues.push({ type: "missing_object", layerId: layer.id, objectId: layer.fabricObject.id, message: `图层 ${layer.id} 关联的对象 ${layer.fabricObject.id} 不存在于画布中`, }); } } if (layer.fabricObjects && isArray(layer.fabricObjects)) { layer.fabricObjects.forEach((fabricObj) => { if (fabricObj.id) { const obj = canvasObjects.find((o) => o.id === fabricObj.id); if (!obj) { issues.push({ type: "missing_object", layerId: layer.id, objectId: fabricObj.id, message: `图层 ${layer.id} 关联的对象 ${fabricObj.id} 不存在于画布中`, }); } } }); } }); return { valid: issues.length === 0, issues, }; } /** * 简化layers对象属性,只保留必要的属性 * @param {Array} layers 图层数组 * @returns {Array} 简化后的图层数组 */ export function simplifyLayers(layers) { if (!layers || !isArray(layers)) { console.warn("simplifyLayers 请传入有效的图层数组:", layers); return []; } return layers.map((layer) => { const simplifiedLayer = { id: layer.id, name: layer.name, visible: layer.visible, locked: layer.locked, opacity: layer.opacity, isBackground: layer.isBackground || false, isFixed: layer.isFixed || false, clippingMask: layer.clippingMask ? { id: layer.clippingMask.id, type: layer.clippingMask.type, } : null, fabricObject: layer.fabricObject ? { id: layer.fabricObject.id, type: layer.fabricObject.type, } : null, fabricObjects: layer.fabricObjects && isArray(layer.fabricObjects) ? layer.fabricObjects .map((fabricObject) => fabricObject?.id ? { id: fabricObject.id, type: fabricObject.type, } : null ) .filter((obj) => obj !== null) : [], children: layer.children && isArray(layer.children) ? simplifyLayers(layer.children) : [], }; return simplifiedLayer; }); } /** * 恢复图层的完整关联关系 * @param {Array} simplifiedLayers 简化的图层数组 * @param {Array} canvasObjects 画布对象数组 * @returns {Array} 恢复关联后的图层数组 */ export function restoreLayers(simplifiedLayers, canvasObjects) { if (!simplifiedLayers || !isArray(simplifiedLayers)) { console.warn("restoreLayers 请传入有效的简化图层数组:", simplifiedLayers); return []; } if (!canvasObjects || !isArray(canvasObjects)) { console.warn("restoreLayers 请传入有效的画布对象数组:", canvasObjects); return simplifiedLayers; } return simplifiedLayers.map((layer) => { const restoredLayer = { ...layer }; // 恢复clippingMask关联 if (layer.clippingMask?.id) { const clippingMaskObj = canvasObjects.find( (obj) => obj.id === layer.clippingMask.id ); restoredLayer.clippingMask = clippingMaskObj || null; } // 恢复单个fabricObject关联 if (layer.fabricObject?.id) { const fabricObj = canvasObjects.find( (obj) => obj.id === layer.fabricObject.id ); if (fabricObj) { fabricObj.layerId = layer.id; fabricObj.layerName = layer.name; restoredLayer.fabricObject = fabricObj; } else { restoredLayer.fabricObject = null; } } // 恢复多个fabricObjects关联 if (layer.fabricObjects && isArray(layer.fabricObjects)) { restoredLayer.fabricObjects = layer.fabricObjects .map((fabricRef) => { const fabricObj = canvasObjects.find( (obj) => obj.id === fabricRef.id ); if (fabricObj) { fabricObj.layerId = layer.id; fabricObj.layerName = layer.name; return fabricObj; } return null; }) .filter((obj) => obj !== null); } // 递归处理子图层 if (layer.children && isArray(layer.children)) { restoredLayer.children = restoreLayers(layer.children, canvasObjects); } return restoredLayer; }); } /** * 序列化图层数据用于保存 * @param {Array} layers 图层数组 * @returns {string} 序列化后的JSON字符串 */ export function serializeLayers(layers) { try { const simplified = simplifyLayers(layers); return JSON.stringify(simplified, null, 2); } catch (error) { console.error("序列化图层数据失败:", error); return null; } } /** * 反序列化图层数据并恢复关联 * @param {string} serializedLayers 序列化的图层JSON字符串 * @param {Array} canvasObjects 画布对象数组 * @returns {Array} 恢复关联后的图层数组 */ export function deserializeLayers(serializedLayers, canvasObjects) { try { const simplified = JSON.parse(serializedLayers); return restoreLayers(simplified, canvasObjects); } catch (error) { console.error("反序列化图层数据失败:", error); return []; } } /** * 获取图层的存储快照(用于撤销/重做) * @param {Array} layers 图层数组 * @returns {Object} 图层快照对象 */ export function createLayerSnapshot(layers) { return { timestamp: Date.now(), data: simplifyLayers(layers), }; } /** * 从快照恢复图层状态 * @param {Object} snapshot 图层快照对象 * @param {Array} canvasObjects 画布对象数组 * @returns {Array} 恢复的图层数组 */ export function restoreFromSnapshot(snapshot, canvasObjects) { if (!snapshot?.data) { console.warn("无效的图层快照:", snapshot); return []; } return restoreLayers(snapshot.data, canvasObjects); }