Files
aida_front/src/component/Canvas/CanvasEditor/managers/ToolManager.js
2025-06-18 11:05:23 +08:00

1242 lines
33 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 { BrushStore } from "../store/BrushStore";
import { BrushManager } from "./brushes/brushManager";
import { ToolCommand } from "../commands/ToolCommands";
import { OperationType } from "../utils/layerHelper";
import CanvasConfig from "../config/canvasConfig";
import { fabric } from "fabric-with-all";
import { InitLiquifyToolCommand } from "../commands/LiquifyCommands";
import { RasterizeLayerCommand } from "../commands/GroupCommands";
import { message, Modal } from "ant-design-vue";
import { h } from "vue";
/**
* 工具管理器
* 负责管理编辑器中的各种工具
*/
export class ToolManager {
/**
* 创建工具管理器
* @param {Object} options 配置选项
* @param {Object} options.canvas fabric.js画布实例
* @param {Object} options.commandManager 命令管理器实例
* @param {Object} options.canvasManager 画布管理实例
* @param {Object} options.layerManager 图层管理实例
* @param {Object} options.brushManager 画笔管理器实例(可选,如果不提供会创建一个)
* @param {Object} options.activeTool 当前活动工具的响应式引用
*/
constructor(options = {}) {
this.canvas = options.canvas;
this.commandManager = options.commandManager;
this.canvasManager = options.canvasManager;
this.layerManager = options.layerManager;
this.activeTool = options.activeTool || {
value: OperationType.SELECT,
};
// 红绿图模式状态
this.isRedGreenMode = false;
this.redGreenModeManager = null;
// 使用传入的brushManager或创建新的实例
this.brushManager =
options.brushManager ||
new BrushManager({
canvas: this.canvas,
brushSize: options.brushSize,
layerManager: this.layerManager, // 传入图层管理器引用
});
// 观察者列表
this.observers = [];
// 工具列表 - 与OperationType保持一致
this.tools = {
// 基础工具
[OperationType.SELECT]: {
name: "选择工具",
icon: "select",
cursor: "default",
shortcut: "V",
setup: this.setupSelectTool.bind(this),
allowedInRedGreen: false,
},
[OperationType.DRAW]: {
name: "画笔工具",
icon: "brush",
cursor: "crosshair",
shortcut: "B",
setup: this.setupBrushTool.bind(this),
allowedInRedGreen: false,
},
[OperationType.ERASER]: {
name: "橡皮擦",
icon: "eraser",
cursor: "crosshair",
shortcut: "E",
setup: this.setupEraserTool.bind(this),
allowedInRedGreen: true, // 红绿图模式允许橡皮擦
},
[OperationType.EYEDROPPER]: {
name: "吸色工具",
icon: "eyedropper",
cursor: "crosshair",
shortcut: "I",
setup: this.setupEyedropperTool.bind(this),
allowedInRedGreen: false,
},
[OperationType.PAN]: {
name: "移动画布",
icon: "hand",
cursor: "grab",
shortcut: "H",
setup: this.setupHandTool.bind(this),
allowedInRedGreen: false, // 红绿图模式不允许PAN
},
// 套索工具
[OperationType.LASSO]: {
name: "套索工具",
icon: "lasso",
cursor: "crosshair",
shortcut: "L",
setup: this.setupLassoTool.bind(this),
allowedInRedGreen: false,
},
[OperationType.LASSO_RECTANGLE]: {
name: "矩形套索工具",
icon: "lasso",
cursor: "crosshair",
// shortcut: "L",
altKey: true,
setup: this.setupRectangleLassoTool.bind(this),
allowedInRedGreen: false,
},
[OperationType.LASSO_ELLIPSE]: {
name: "椭圆形套索工具",
icon: "lasso",
cursor: "crosshair",
// shortcut: "L",
altKey: true,
setup: this.setupEllipseLassoTool.bind(this),
allowedInRedGreen: false,
},
// 选区工具 - 只需要矩形选区
[OperationType.AREA_RECTANGLE]: {
name: "矩形选区工具",
icon: "area-rectangle",
cursor: "crosshair",
shortcut: "M",
altKey: true,
setup: this.setupRectangleAreaTool.bind(this),
allowedInRedGreen: false,
},
// 特效工具
[OperationType.WAVE]: {
name: "波浪工具",
icon: "wave",
cursor: "crosshair",
shortcut: "W",
setup: this.setupWaveTool.bind(this),
allowedInRedGreen: false,
},
[OperationType.LIQUIFY]: {
name: "液化工具",
icon: "liquify",
cursor: "crosshair",
shortcut: "J",
setup: this.setupLiquifyTool.bind(this),
allowedInRedGreen: false, // 红绿图模式不允许液化
},
[OperationType.TEXT]: {
name: "文本工具",
icon: "text",
cursor: "text",
shortcut: "T",
setup: this.setupTextTool.bind(this),
allowedInRedGreen: false, // 红绿图模式不允许文本
},
// 红绿图模式专用工具
[OperationType.RED_BRUSH]: {
name: "红色笔刷",
icon: "brush",
cursor: "crosshair",
shortcut: "R",
setup: this.setupRedBrushTool.bind(this),
allowedInRedGreen: true,
redGreenOnly: true, // 只在红绿图模式显示
},
[OperationType.GREEN_BRUSH]: {
name: "绿色笔刷",
icon: "brush",
cursor: "crosshair",
shortcut: "G",
setup: this.setupGreenBrushTool.bind(this),
allowedInRedGreen: true,
redGreenOnly: true, // 只在红绿图模式显示
},
};
// 记录先前的工具
this.previousTool = null;
// 初始化默认工具
this.setTool(this.activeTool.value);
// 初始化工具快捷键
this.initKeyboardShortcuts();
// 设置文本编辑事件
this.setupTextEditingEvents();
// 添加观察者
// this.addObserver(this.brushManager);
this.addObserver(this.layerManager);
this.addObserver(this.canvasManager);
}
/**
* 添加观察者
* @param {Object} observer 观察者对象必须实现toolChanged方法
*/
addObserver(observer) {
if (typeof observer.toolChanged === "function") {
this.observers.push(observer);
} else {
console.warn("Observer must implement toolChanged method");
}
}
/**
* 移除观察者
* @param {Object} observer 要移除的观察者对象
*/
removeObserver(observer) {
this.observers = this.observers.filter((obs) => obs !== observer);
}
/**
* 通知所有观察者工具已更改
* @param {String} toolId 工具ID
*/
notifyObservers(toolId) {
this.observers.forEach((observer) => {
observer.toolChanged(toolId, this.tools[toolId]);
});
}
/**
* 初始化工具快捷键
*/
initKeyboardShortcuts() {
// 可以在这里设置工具快捷键的全局监听
// 如需要由外部统一管理键盘事件,则不需要此方法
}
/**
* 处理快捷键事件
* @param {KeyboardEvent} event 键盘事件
*/
handleKeyboardShortcut(event) {
const key = event.key.toUpperCase();
const altKey = event.altKey;
const ctrlKey = event.ctrlKey;
const shiftKey = event.shiftKey;
// 当处于输入状态时不触发快捷键
if (
event.target.tagName === "INPUT" ||
event.target.tagName === "TEXTAREA"
) {
return;
}
// 在红绿图模式下,只允许特定快捷键
if (this.isRedGreenMode) {
const allowedKeys = ["E", "R", "G"]; // 橡皮擦、红色笔刷、绿色笔刷
if (!allowedKeys.includes(key)) {
return; // 忽略不允许的快捷键
}
}
// 查找匹配的工具
for (const [toolId, tool] of Object.entries(this.tools)) {
if (tool.shortcut && tool.shortcut.toUpperCase() === key) {
// 检查可能的辅助键要求
if (
(tool.altKey && !altKey) ||
(tool.ctrlKey && !ctrlKey) ||
(tool.shiftKey && !shiftKey)
) {
continue;
}
// 在红绿图模式下检查工具可用性
if (
this.isRedGreenMode &&
!this.isToolAvailableInRedGreenMode(toolId)
) {
continue;
}
// 切换到该工具
this.setToolWithCommand(toolId);
event.preventDefault();
return;
}
}
}
/**
* 获取所有可用工具列表
* @returns {Array} 工具列表
*/
getTools() {
return Object.keys(this.tools).map((key) => {
return {
id: key,
...this.tools[key],
};
});
}
/**
* 获取当前工具
* @returns {String} 当前工具ID
*/
getCurrentTool() {
return this.activeTool.value;
}
/**
* 设置当前活动工具
* @param {String} toolId 工具ID
*/
setTool(toolId) {
// 检查工具是否存在
if (!this.tools[toolId]) {
console.error(`工具 '${toolId}' 不存在`);
return;
}
// 在红绿图模式下检查工具可用性
if (this.isRedGreenMode && !this.isToolAvailableInRedGreenMode(toolId)) {
console.warn(`工具 '${toolId}' 在红绿图模式下不可用`);
return;
}
// 在普通模式下检查是否为红绿图专用工具
if (!this.isRedGreenMode && this.isRedGreenOnlyTool(toolId)) {
console.warn(`工具 '${toolId}' 只能在红绿图模式下使用`);
return;
}
// 保存先前的工具
this.previousTool = this.activeTool.value;
// 设置新工具
this.activeTool.value = toolId;
// 设置光标
if (this.canvas) {
this.canvas.defaultCursor = this.tools[toolId].cursor;
}
// 设置工具特定的状态
const tool = this.tools[toolId];
if (tool && typeof tool.setup === "function") {
tool.setup();
}
// 通知选区管理器工具已改变
if (this.canvasManager && this.canvasManager.selectionManager) {
this.canvasManager.selectionManager.setCurrentTool(toolId);
}
// 通知观察者
this.notifyObservers(toolId);
return this.activeTool.value;
}
/**
* 通过命令模式设置工具
* @param {String} toolId 工具ID
*/
setToolWithCommand(toolId, options = {}) {
if (!this.commandManager) {
this.setTool(toolId);
return;
}
// 创建工具切换命令
const command = new ToolCommand({
toolManager: this,
tool: toolId,
previousTool: this.activeTool.value,
});
command.undoable = options.undoable !== undefined ? options.undoable : true;
// 执行命令
this.commandManager.execute(command, { ...options });
}
/**
* 恢复当前工具的选择状态
* 在拖拽结束时调用确保canvas.selection状态与当前工具一致
*/
restoreSelectionState() {
if (!this.canvas) return;
const currentTool = this.activeTool.value;
const tool = this.tools[currentTool];
// 根据当前工具设置selection状态
if (currentTool === OperationType.SELECT) {
this.canvas.selection = true;
} else {
// 对于大多数工具selection应该是false
this.canvas.selection = false;
}
// 如有必要可以调用当前工具的setup方法来全面恢复状态
if (tool && typeof tool.setup === "function") {
tool.setup();
}
}
/**
* 切换回先前使用的工具
*/
togglePreviousTool() {
if (this.previousTool && this.previousTool !== this.activeTool.value) {
this.setTool(this.previousTool);
}
}
/**
* 设置选择工具
*/
setupSelectTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = true;
}
/**
* 设置画笔工具
*/
setupBrushTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = true;
this.canvas.selection = false;
// 确保有笔刷管理器
if (this.brushManager) {
// 检查画笔是否正在更新中
if (this.brushManager.isUpdatingBrush) {
console.warn("画笔正在更新中,请稍候...");
return;
}
if (BrushStore) {
// 同步基本属性
this.brushManager.setBrushSize(BrushStore.state.size);
this.brushManager.setBrushColor(BrushStore.state.color);
this.brushManager.setBrushOpacity(BrushStore.state.opacity);
// 同步笔刷类型 - 修复方法名使用正确的setBrushType方法
this.brushManager.setBrushType(BrushStore.state.type);
// 同步材质设置
if (BrushStore.state.textureEnabled && BrushStore.state.texturePath) {
this.brushManager.setTexturePath(BrushStore.state.texturePath);
this.brushManager.setTextureScale(BrushStore.state.textureScale);
}
}
// 更新应用到画布
this.brushManager.updateBrush();
}
}
/**
* 设置橡皮擦工具
*/
setupEraserTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = true;
this.canvas.selection = false;
// 确保有笔刷管理器
if (this.brushManager) {
this.brushManager.createEraser();
}
}
/**
* 设置吸色工具
*/
setupEyedropperTool() {
if (!this.canvas || !this.brushManager) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// 保存当前工具,以便吸色完成后还原
const currentTool = this.activeTool.value;
// 使用吸色工具
this.brushManager.createEyedropper((color) => {
// 设置画笔颜色
this.brushManager.setBrushColor(color);
// 吸色完成后,恢复到之前的工具
this.setTool(currentTool);
});
}
/**
* 设置移动画布工具
*/
setupHandTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// 设置画布为可拖动状态
this.canvas.defaultCursor = "grab";
}
/**
* 设置套索工具
*/
setupLassoTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// 通知选区管理器切换到自由套索工具
if (this.canvasManager && this.canvasManager.selectionManager) {
this.canvasManager.selectionManager.setCurrentTool(OperationType.LASSO);
}
}
/**
* 设置矩形套索工具
*/
setupRectangleLassoTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// 通知选区管理器切换到矩形套索工具
if (this.canvasManager && this.canvasManager.selectionManager) {
this.canvasManager.selectionManager.setCurrentTool(
OperationType.LASSO_RECTANGLE
);
}
}
/**
* 设置椭圆形套索工具
*/
setupEllipseLassoTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// 通知选区管理器切换到椭圆套索工具
if (this.canvasManager && this.canvasManager.selectionManager) {
this.canvasManager.selectionManager.setCurrentTool(
OperationType.LASSO_ELLIPSE
);
}
}
/**
* 设置自由选区工具
*/
setupCustomAreaTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// 通知选区管理器切换到椭圆套索工具
if (this.canvasManager && this.canvasManager.selectionManager) {
this.canvasManager.selectionManager.setCurrentTool(
OperationType.AREA_CUSTOM
);
}
}
/**
* 设置矩形选区工具
*/
setupRectangleAreaTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// // 设置矩形选区模式
// // 这里需要具体的矩形选区工具实现
console.log("矩形选区工具已激活");
if (this.canvasManager && this.canvasManager.selectionManager) {
this.canvasManager.selectionManager.setCurrentTool(
OperationType.AREA_RECTANGLE
);
}
}
/**
* 设置波浪工具
*/
setupWaveTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
}
/**
* 设置液化工具
*/
setupLiquifyTool() {
if (!this.canvas || !this.layerManager) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
// 获取当前活动图层
const activeLayerId = this.layerManager.getActiveLayerId();
// 准备液化面板显示的详情信息
let panelDetail = {
activeLayerId: activeLayerId,
layerStatus: null,
canLiquify: false,
targetObject: null,
originalImageData: null,
};
// 如果有活动图层,检查其状态
if (activeLayerId) {
const liquifyManager = this.canvasManager?.liquifyManager;
if (liquifyManager) {
// 检查图层状态
const checkResult = liquifyManager.checkLayerForLiquify(activeLayerId);
panelDetail.layerStatus = checkResult;
// 获取图层对象
const layer = this.layerManager.getLayerById(activeLayerId);
// 检查图层是否为空
if (!checkResult.isEmpty) {
// 图层不为空,判断是否可直接液化或需要栅格化
if (checkResult.valid) {
// 可以直接液化 (单个图像对象)
panelDetail.canLiquify = true;
// 设置目标对象
if (layer) {
if (layer.isBackground || layer.type === "background") {
panelDetail.targetObject = layer.fabricObject;
} else if (
layer.fabricObjects &&
layer.fabricObjects.length > 0
) {
panelDetail.targetObject = layer.fabricObjects[0];
}
// 准备液化环境,获取原始图像数据
if (panelDetail.targetObject && liquifyManager) {
liquifyManager.initialize({
canvas: this.canvas,
layerManager: this.layerManager,
});
// 异步获取原始图像数据
liquifyManager
.prepareForLiquify(panelDetail.targetObject)
.then((result) => {
if (result && result.originalImageData) {
// 当获取到原始图像数据后触发更新
const updatedDetail = {
...panelDetail,
originalImageData: result.originalImageData,
};
// 重新触发液化面板显示事件,这次包含原始图像数据
document.dispatchEvent(
new CustomEvent("showLiquifyPanel", {
detail: updatedDetail,
})
);
}
})
.catch((err) => {
console.error("准备液化环境失败:", err);
});
}
}
} else if (checkResult.needsRasterization) {
// 需要栅格化 (多个对象或组)
// 使用Modal询问用户是否要栅格化
this._showRasterizeConfirmModal(checkResult.isGroup, activeLayerId);
return; // 等待用户确认,不继续执行
}
}
}
}
// 总是触发液化面板显示事件,不论图层状态如何
document.dispatchEvent(
new CustomEvent("showLiquifyPanel", {
detail: panelDetail,
})
);
}
/**
* 显示栅格化确认Modal对话框
* @param {Boolean} isGroup 是否为组对象
* @param {String} layerId 图层ID
* @private
*/
_showRasterizeConfirmModal(isGroup, layerId) {
const title = "栅格化图层";
const content = "需要先栅格化才能进行液化操作,是否立即栅格化?";
Modal.confirm({
title,
content,
okText: "确定栅格化",
cancelText: "取消",
centered: true,
icon: h("span", { style: "color: #faad14;" }, "⚠️"),
onOk: () => {
// 用户确认栅格化,执行栅格化操作
this._rasterizeLayerForLiquify(layerId);
},
onCancel: () => {
console.log("用户取消了栅格化操作");
// 用户取消,触发液化面板显示事件但不能液化
document.dispatchEvent(
new CustomEvent("showLiquifyPanel", {
detail: {
activeLayerId: layerId,
layerStatus: { needsRasterization: true, isGroup },
canLiquify: false,
targetObject: null,
originalImageData: null,
},
})
);
},
});
}
/**
* 栅格化图层用于液化操作
* @param {String} layerId 图层ID
* @private
*/
async _rasterizeLayerForLiquify(layerId) {
if (!this.commandManager || !this.layerManager) return;
try {
// 显示加载Modal
const loadingModal = Modal.info({
title: "正在栅格化",
content: "正在栅格化图层,请稍候...",
okButtonProps: { style: { display: "none" } },
centered: true,
closable: false,
maskClosable: false,
});
// 创建栅格化命令
const rasterizeCommand = new RasterizeLayerCommand({
canvas: this.canvas,
layerManager: this.layerManager,
layerId: layerId,
layers: this.layerManager.layers,
activeLayerId: this.layerManager.activeLayerId,
});
// 执行命令
const result = await this.commandManager.execute(rasterizeCommand);
// 关闭加载Modal
loadingModal.destroy();
if (result) {
// 栅格化成功,启动液化
message.success("图层已成功栅格化,可以进行液化操作");
this._startLiquify(layerId);
} else {
// 栅格化失败
Modal.error({
title: "栅格化失败",
content: "栅格化失败,无法进行液化操作",
okText: "确定",
centered: true,
});
}
} catch (error) {
console.error("栅格化图层失败:", error);
Modal.error({
title: "栅格化错误",
content: `栅格化失败:${error.message}`,
okText: "确定",
centered: true,
});
}
}
/**
* 开始液化操作
* @param {String} layerId 图层ID
* @private
*/
async _startLiquify(layerId) {
// 获取图层信息
const layer = this.layerManager.getLayerById(layerId);
if (!layer) {
Modal.error({
title: "图层错误",
content: "图层不存在",
okText: "确定",
centered: true,
});
return;
}
// 检查图层是否为空
let targetObject = null;
if (layer.isBackground) {
// 背景图层使用 fabricObject (单数)
if (!layer.fabricObject) {
Modal.warning({
title: "背景图层为空",
content: "背景图层为空,无法进行液化操作",
okText: "确定",
centered: true,
});
return;
}
targetObject = layer.fabricObject;
} else {
// 普通图层使用 fabricObjects (复数)
if (!layer.fabricObjects || layer.fabricObjects.length === 0) {
Modal.warning({
title: "图层为空",
content: "图层为空,无法进行液化操作",
okText: "确定",
centered: true,
});
return;
}
targetObject = layer.fabricObjects[0];
}
// 确保liquifyManager可用
const liquifyManager = this.canvasManager?.liquifyManager;
if (!liquifyManager) {
Modal.error({
title: "液化管理器错误",
content: "液化管理器未初始化",
okText: "确定",
centered: true,
});
return;
}
try {
// 显示准备中的Modal
const preparingModal = Modal.info({
title: "准备液化环境",
content: "正在准备液化环境,请稍候...",
okButtonProps: { style: { display: "none" } },
centered: true,
closable: false,
maskClosable: false,
});
// 准备液化环境
liquifyManager.initialize({
canvas: this.canvas,
layerManager: this.layerManager,
});
// 准备液化操作,获取原始图像数据
const prepareResult = await liquifyManager.prepareForLiquify(
targetObject
);
// 创建和初始化命令
const initCommand = new InitLiquifyToolCommand({
canvas: this.canvas,
layerManager: this.layerManager,
liquifyManager,
toolManager: this,
});
// 执行初始化命令
await this.commandManager.execute(initCommand);
// 关闭准备Modal
preparingModal.destroy();
// 触发液化面板显示事件
document.dispatchEvent(
new CustomEvent("showLiquifyPanel", {
detail: {
targetObject,
targetLayerId: layerId,
originalImageData: prepareResult.originalImageData,
},
})
);
} catch (error) {
console.error("启动液化工具失败:", error);
Modal.error({
title: "液化工具启动失败",
content: `启动液化工具失败:${error.message}`,
okText: "确定",
centered: true,
});
}
}
/**
* 触发文件上传操作
*/
openFile() {
this.onFileSelected?.();
}
/**
* 设置文件选择回调
* @param {Function} callback 回调函数
*/
setFileUploadHandler(callback) {
this.onFileSelected = callback;
}
/**
* 更新笔刷大小
* @param {Number} size 笔刷大小
*/
updateBrushSize(size) {
if (!this.canvas || !this.brushManager) return;
// 更新BrushStore
BrushStore.setBrushSize(size);
// 直接更新笔刷管理器
this.brushManager.setBrushSize(size);
// 更新应用到画布
this.brushManager.updateBrush();
}
/**
* 创建文字对象并添加到画布
* @param {Number} x 文本位置x坐标
* @param {Number} y 文本位置y坐标
* @param {Object} options 文本选项
*/
createText(x, y, options = {}) {
if (!this.canvas || !this.layerManager) return null;
// 默认文本属性
const defaultOptions = {
text: "双击编辑文本",
fontFamily: "Arial",
fontSize: 24,
fontWeight: "normal",
fontStyle: "normal",
textAlign: "left",
fill: "#000000",
opacity: 1,
underline: false,
overline: false,
linethrough: false,
textBackgroundColor: "transparent",
lineHeight: 1.16,
charSpacing: 0,
};
// 合并默认选项和用户选项
const textOptions = { ...defaultOptions, ...options, left: x, top: y };
// 创建文本对象
const textObj = new fabric.IText(textOptions.text, {
...textOptions,
originX: "center",
originY: "center",
id: options.id || this.generateId(), // 生成唯一ID
});
// 创建文本图层并通过LayerManager添加到画布
this.layerManager.createTextLayerWithObject(textObj, textOptions);
this.canvas.renderAll();
return textObj;
}
/**
* 生成唯一ID
* @returns {String} 唯一ID
*/
generateId() {
return "text_" + Date.now() + "_" + Math.floor(Math.random() * 1000);
}
/**
* 更新笔刷颜色
* @param {String} color 颜色值,如 "#ff0000"
*/
updateBrushColor(color) {
if (!this.canvas || !this.brushManager) return;
// 更新BrushStore
BrushStore.setBrushColor(color);
// 直接更新笔刷管理器
this.brushManager.setBrushColor(color);
// 更新应用到画布
this.brushManager.updateBrush();
}
/**
* 更新笔刷透明度
* @param {Number} opacity 透明度值,范围 0-1
*/
updateBrushOpacity(opacity) {
if (!this.canvas || !this.brushManager) return;
// 更新BrushStore
BrushStore.setBrushOpacity(opacity);
// 直接更新笔刷管理器
this.brushManager.setBrushOpacity(opacity);
// 更新应用到画布
this.brushManager.updateBrush();
}
/**
* 设置双击文本的事件监听
* 当用户双击文本对象时,显示文本编辑弹窗
*/
setupTextEditingEvents() {
if (!this.canvas) return;
// 如果已有监听器,先移除以避免重复
if (this._textEditHandler) {
this.canvas.off("mouse:dblclick", this._textEditHandler);
}
// 创建双击事件处理函数
this._textEditHandler = (e) => {
const target = e.target;
if (
target &&
(target.type === "text" ||
target.type === "i-text" ||
target.type === "textbox")
) {
// 获取对应的图层
const layer = this.layerManager.getLayerById(target.layerId);
if (layer) {
// 显示文本编辑面板
this.showTextEditor(target, layer);
}
}
};
// 添加双击事件监听
this.canvas.on("mouse:dblclick", this._textEditHandler);
}
/**
* 显示文本编辑面板
* @param {Object} textObject 文本对象
* @param {Object} layer 图层对象
*/
showTextEditor(textObject, layer) {
// 这个方法将在TextEditorPanel组件实现后调用
console.log("显示文本编辑面板", textObject, layer);
// 将发出一个事件让Vue组件捕获并显示编辑面板
document.dispatchEvent(
new CustomEvent("showTextEditor", {
detail: {
textObject,
layer,
},
})
);
}
/**
* 清理资源
*/
dispose() {
if (this.brushManager) {
this.brushManager.dispose();
}
// 移除文本编辑相关事件监听器
if (this.canvas) {
this.canvas.off("mouse:dblclick", this._textEditHandler);
}
this._textEditHandler = null;
this.observers = []; // 清空观察者
this.canvas = null;
this.commandManager = null;
this.onFileSelected = null;
}
/**
* 设置文本工具
*/
setupTextTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = false;
this.canvas.selection = false;
console.log("文本工具已激活");
}
/**
* 设置红色笔刷工具(红绿图模式专用)
*/
setupRedBrushTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = true;
this.canvas.selection = false;
// 确保有笔刷管理器
if (this.brushManager) {
// 设置红色笔刷
this.brushManager.setBrushColor("#FF0000"); // 纯红色
this.brushManager.setBrushOpacity(1.0); // 完全不透明
this.brushManager.setBrushType("pencil"); // 铅笔类型
// 更新笔刷大小(使用当前大小)
if (BrushStore && BrushStore.state.size) {
this.brushManager.setBrushSize(BrushStore.state.size);
}
// 更新应用到画布
this.brushManager.updateBrush();
}
}
/**
* 设置绿色笔刷工具(红绿图模式专用)
*/
setupGreenBrushTool() {
if (!this.canvas) return;
this.canvas.isDrawingMode = true;
this.canvas.selection = false;
// 确保有笔刷管理器
if (this.brushManager) {
// 设置绿色笔刷
this.brushManager.setBrushColor("#00FF00"); // 纯绿色
this.brushManager.setBrushOpacity(1.0); // 完全不透明
this.brushManager.setBrushType("pencil"); // 铅笔类型
// 更新笔刷大小(使用当前大小)
if (BrushStore && BrushStore.state.size) {
this.brushManager.setBrushSize(BrushStore.state.size);
}
// 更新应用到画布
this.brushManager.updateBrush();
}
}
/**
* 进入红绿图模式
* @param {Object} redGreenModeManager 红绿图模式管理器实例
*/
enterRedGreenMode(redGreenModeManager) {
this.isRedGreenMode = true;
this.redGreenModeManager = redGreenModeManager;
// 切换到红色笔刷工具作为默认工具
this.setTool(OperationType.RED_BRUSH);
console.log("工具管理器已进入红绿图模式");
}
/**
* 退出红绿图模式
*/
exitRedGreenMode() {
this.isRedGreenMode = false;
this.redGreenModeManager = null;
// 切换回选择工具
this.setTool(OperationType.SELECT);
console.log("工具管理器已退出红绿图模式");
}
/**
* 检查工具是否在红绿图模式下可用
* @param {String} toolId 工具ID
* @returns {Boolean} 是否可用
*/
isToolAvailableInRedGreenMode(toolId) {
if (!this.isRedGreenMode) return true;
const tool = this.tools[toolId];
return tool && tool.allowedInRedGreen === true;
}
/**
* 获取红绿图模式下可用的工具列表
* @returns {Array} 工具列表
*/
getRedGreenModeTools() {
return Object.keys(this.tools)
.filter((toolId) => this.tools[toolId].allowedInRedGreen === true)
.map((toolId) => ({
id: toolId,
...this.tools[toolId],
}));
}
/**
* 检查是否为红绿图模式专用工具
* @param {String} toolId 工具ID
* @returns {Boolean} 是否为红绿图模式专用工具
*/
isRedGreenOnlyTool(toolId) {
const tool = this.tools[toolId];
return tool && tool.redGreenOnly === true;
}
}