合并画布

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

@@ -44,10 +44,8 @@ import {
BackgroundSizeCommand,
BackgroundSizeWithScaleCommand,
} from "../commands/BackgroundCommands";
import {
RasterizeLayerCommand,
MergeGroupLayerCommand,
} from "../commands/GroupCommands";
import { MergeGroupLayerCommand } from "../commands/GroupCommands";
import { RasterizeLayerCommand } from "../commands/RasterizeLayerCommand";
// 导入图层排序相关类和混入
import {
@@ -59,8 +57,13 @@ import {
import CanvasConfig from "../config/canvasConfig";
import { isBoolean, template } from "lodash-es";
import { findObjectById, optimizeCanvasRendering } from "../utils/helper";
import {
findObjectById,
generateId,
optimizeCanvasRendering,
} from "../utils/helper";
import { message } from "ant-design-vue";
import { fabric } from "fabric-with-all";
/**
* 图层管理器 - 负责管理画布上的所有图层
@@ -168,17 +171,17 @@ export class LayerManager {
* 根据当前编辑模式和图层状态设置对象的交互属性
* @private
*/
updateLayersObjectsInteractivity(isUseOptimize = true) {
async updateLayersObjectsInteractivity(isUseOptimize = true) {
if (!this.canvas) return;
if (isUseOptimize) {
// 优化渲染 - 统一批处理 支持异步回调
optimizeCanvasRendering(this.canvas, () => {
await optimizeCanvasRendering(this.canvas, async () => {
// 应用图层交互规则
this._applyInteractionRules();
await this._applyInteractionRules();
});
} else {
// 直接应用图层交互规则
this._applyInteractionRules();
await this._applyInteractionRules();
}
// // 性能优化使用requestAnimationFrame
@@ -201,7 +204,7 @@ export class LayerManager {
// this.canvas.renderAll(); // 确保画布重新渲染 - 同步渲染
// });
}
_setObjectInteractivity(obj, layer, editorMode) {
async _setObjectInteractivity(obj, layer, editorMode) {
// 设置可见性
obj.visible = layer.visible;
@@ -281,12 +284,14 @@ export class LayerManager {
if (layer.blendMode) obj.globalCompositeOperation = layer.blendMode;
if (layer.clippingMask) {
const { object } = findObjectById(this.canvas, layer.clippingMask?.id);
obj.clipPath = object || null;
if (object) {
obj.clipPath = object;
}
}
}
// 私有方法:应用交互规则
_applyInteractionRules() {
async _applyInteractionRules() {
console.log("updateLayersObjectsInteractivity ===>", this.editorMode);
const objects = this.canvas.getObjects();
const editorMode = this.editorMode || CanvasConfig.defaultTool;
@@ -302,7 +307,7 @@ export class LayerManager {
});
// 批量更新对象
objects.forEach((obj) => {
objects.forEach(async (obj) => {
const layer = layerMap[obj.layerId];
if (!obj.layerId) {
@@ -316,15 +321,15 @@ export class LayerManager {
if (!layer) return;
// 设置一级图层对象的交互性
this._setObjectInteractivity(obj, layer, editorMode);
await this._setObjectInteractivity(obj, layer, editorMode);
// 设置子图层对象的交互性
layer?.childLayer?.forEach((childLayer) => {
layer?.childLayer?.forEach(async (childLayer) => {
const childObj = this.canvas
.getObjects()
.find((o) => o.layerId === childLayer.id);
if (childObj) {
this._setObjectInteractivity(childObj, childLayer, editorMode);
await this._setObjectInteractivity(childObj, childLayer, editorMode);
}
});
});
@@ -336,9 +341,13 @@ export class LayerManager {
* @param {Object} options 额外选项
* @returns {string} 新创建的图层ID
*/
createLayer(name = null, type = LayerType.EMPTY, options = {}) {
async createLayer(name = null, type = LayerType.EMPTY, options = {}) {
// 生成唯一ID
const layerId = `layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
const layerId =
options.id ||
options.layerId ||
generateId("layer_") ||
`layer_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
const layerIndex = this.layers.value.length;
// 计算插入位置如果没有指定insertIndex则根据当前选中图层决定插入位置
@@ -380,15 +389,15 @@ export class LayerManager {
command.undoable = options.undoable;
// 如果是第一个图层或者普通图层数量小于等于3设置为不可撤销
if (this.layers.value.length === 3 || normalLayersCount <= 1) {
if (this.layers.value.length === 3 || normalLayersCount < 1) {
command.undoable = false;
}
// 执行命令
if (this.commandManager) {
this.commandManager.execute(command);
await this.commandManager.execute(command);
} else {
command.execute();
await command.execute();
}
return layerId;
@@ -505,7 +514,7 @@ export class LayerManager {
/**
* 初始化图层,确保有背景层、固定图层和一个空白图层
*/
initializeLayers() {
async initializeLayers() {
// 如果没有任何图层,创建背景层、固定图层和一个空白图层
if (this.layers.value.length === 0) {
// 创建背景图层
@@ -515,7 +524,7 @@ export class LayerManager {
this.createFixedLayer();
// 创建一个空白图层(默认位于背景图层和固定图层之上)
this.createLayer("图层 1");
await this.createLayer("图层 1");
} else {
// 检查是否已有背景层
const hasBackgroundLayer = this.layers.value.some(
@@ -539,7 +548,7 @@ export class LayerManager {
);
if (!hasNormalLayer) {
this.createLayer("图层 1");
await this.createLayer("图层 1");
}
}
@@ -679,14 +688,26 @@ export class LayerManager {
* @return {Object} layer 图层对象
*/
getActiveLayer() {
const { layer: activeLayer } = findLayerRecursively(
this.layers.value,
this.activeLayerId.value
);
if (activeLayer) {
return activeLayer;
} else {
console.warn("没有活动图层");
if (!this.activeLayerId.value) {
console.warn(
"没有活动图层ID无法获取活动图层 ==== 默认设置第一个图层为活动图层"
);
this.activeLayerId.value = this.layers.value[0]?.id || null;
}
try {
const { layer: activeLayer } = findLayerRecursively(
this.layers.value,
this.activeLayerId.value
);
if (activeLayer) {
return activeLayer;
} else {
console.warn("没有活动图层");
return null;
}
} catch (error) {
console.error("获取活动图层失败:", error);
return null;
}
}
@@ -868,27 +889,21 @@ export class LayerManager {
* @param {string} layerId 图层ID
* @returns {boolean} 更新后的可见性状态
*/
toggleLayerVisibility(layerId) {
async toggleLayerVisibility(layerId) {
// 直接创建和执行命令
const command = new ToggleLayerVisibilityCommand({
canvas: this.canvas,
layers: this.layers,
layerId: layerId,
layerManager: this,
});
// 执行命令
if (this.commandManager) {
this.commandManager.execute(command);
return await this.commandManager.execute(command);
} else {
command.execute();
return await command.execute();
}
// 更新对象交互性
this.updateLayersObjectsInteractivity();
// 获取当前可见性
const layer = this.layers.value.find((layer) => layer.id === layerId);
return layer ? layer.visible : false;
}
/**
@@ -2029,7 +2044,7 @@ export class LayerManager {
* @param {Object} options 文本选项
* @returns {Object} 创建的文本对象
*/
createTextLayerWithObject(textObject, options = {}) {
async createTextLayerWithObject(textObject, options = {}) {
if (!this.canvas || !textObject) return null;
// 确保对象有ID
@@ -2038,7 +2053,7 @@ export class LayerManager {
// 创建文本图层
const layerName = options.name || "文本图层";
const layerId = this.createLayer(layerName, LayerType.TEXT, {
const layerId = await this.createLayer(layerName, LayerType.TEXT, {
layerProperties: {
text: options.text || textObject.text || "新文本",
fontFamily: options.fontFamily || textObject.fontFamily || "Arial",
@@ -2075,7 +2090,9 @@ export class LayerManager {
const layer = this.getLayerById(layerId);
if (layer) {
layer.fabricObjects = layer.fabricObjects || [];
layer.fabricObjects.push(textObject);
layer.fabricObjects.push(
textObject.toObject(["id", "layerId", "layerName"])
);
}
// 设置此图层为活动图层
@@ -2218,7 +2235,7 @@ export class LayerManager {
* @param {string} parentId 父图层ID
* @returns {boolean} 是否删除成功
*/
removeChildLayer(layerId, parentId) {
async removeChildLayer(layerId, parentId) {
// 直接创建和执行命令
const command = new RemoveChildLayerCommand({
canvas: this.canvas,
@@ -2231,9 +2248,9 @@ export class LayerManager {
// 执行命令
if (this.commandManager) {
return this.commandManager.execute(command);
return await this.commandManager.execute(command);
} else {
return command.execute();
return await command.execute();
}
}
@@ -2298,28 +2315,22 @@ export class LayerManager {
* @param {string} parentId 父图层ID
* @returns {boolean} 更新后的可见性状态
*/
toggleChildLayerVisibility(layerId, parentId) {
async toggleChildLayerVisibility(layerId, parentId) {
// 直接创建和执行命令
const command = new ToggleChildLayerVisibilityCommand({
canvas: this.canvas,
layers: this.layers,
layerId: layerId,
parentId: parentId,
layerManager: this,
});
// 执行命令
if (this.commandManager) {
this.commandManager.execute(command);
return await this.commandManager.execute(command);
} else {
command.execute();
return await command.execute();
}
// 更新对象交互性
this.updateLayersObjectsInteractivity();
// 获取当前可见性
const childLayer = this.findChildLayer(layerId, parentId);
return childLayer ? childLayer.visible : false;
}
// ==================== 红绿图模式相关操作 ====================
@@ -2782,7 +2793,12 @@ export class LayerManager {
}
// 查找目标图层
const targetLayer = this.getLayerById(targetLayerId);
// const targetLayer = this.getLayerById(targetLayerId);
const { layer: targetLayer } = findLayerRecursively(
this.layers.value,
targetLayerId
);
if (!targetLayer) {
console.error($t("图层不存在", { layerId: targetLayerId }));
return false;