合并画布
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user