Files
aida_front/src/component/Canvas/CanvasEditor/utils/layerUtils.js
X1627315083 584f6a7db0 合并画布
2025-06-22 13:52:28 +08:00

334 lines
9.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}