From e001c9dd491ccc1836fa308df3145ddd85e6bfa9 Mon Sep 17 00:00:00 2001 From: bighuixiang <472705331@qq.com> Date: Tue, 24 Jun 2025 01:54:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=AC=94=E5=88=B7?= =?UTF-8?q?=E6=8C=87=E7=A4=BA=E5=99=A8=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=8A=A8=E6=80=81=E6=98=BE=E7=A4=BA=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E7=AC=94=E5=88=B7=E5=A4=A7=E5=B0=8F=E5=92=8C=E9=A2=9C=E8=89=B2?= =?UTF-8?q?=EF=BC=9B=E6=9B=B4=E6=96=B0=E5=9B=BE=E5=B1=82=E5=8F=AF=E6=93=A6?= =?UTF-8?q?=E9=99=A4=E7=8A=B6=E6=80=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Canvas/CanvasEditor/index.vue | 43 ++ .../CanvasEditor/managers/BrushIndicator.js | 483 ++++++++++++++++++ .../CanvasEditor/managers/CanvasManager.js | 20 + .../CanvasEditor/managers/LayerManager.js | 3 +- .../CanvasEditor/managers/ToolManager.js | 179 ++++++- 5 files changed, 725 insertions(+), 3 deletions(-) create mode 100644 src/component/Canvas/CanvasEditor/managers/BrushIndicator.js diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index 8db2b205..3faa912b 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -8,6 +8,7 @@ import { provide, defineExpose, nextTick, + watchEffect, } from "vue"; import { CanvasManager } from "./managers/CanvasManager"; import { LayerManager } from "./managers/LayerManager"; @@ -76,6 +77,14 @@ const props = defineProps({ }; }, }, + isFixedErasable: { + type: Boolean, + default: false, // 是否允许擦除固定图层 + }, + isBackgroundErasable: { + type: Boolean, + default: false, // 是否允许擦除背景图层 + }, }); // 引用和状态 @@ -344,6 +353,32 @@ onMounted(async () => { canvasManager.canvas.height ); } + + // // 设置固定图层是否可擦除 + // canvasManager.setFixedLayerErasable({ + // type: "isFixed", + // flag: !props.isFixedErasable, // 设置操作类型为可擦除 + // }); + // // 设置背景图层是否可擦除 + // canvasManager.setFixedLayerErasable({ + // type: "isBackground", + // flag: !props.isBackgroundErasable, // 设置操作类型为可擦除 + // }); +}); + +watchEffect(() => { + // 设置固定图层是否可擦除 + if (canvasManagerLoaded.value) { + canvasManager?.setFixedLayerErasable({ + type: "isFixed", + flag: !props.isFixedErasable, // 设置操作类型为可擦除 + }); + // 设置背景图层是否可擦除 + canvasManager?.setFixedLayerErasable({ + type: "isBackground", + flag: !props.isBackgroundErasable, // 设置操作类型为可擦除 + }); + } }); onBeforeUnmount(() => { @@ -640,7 +675,15 @@ const changeCanvas = (command) => { // 提供外部ref实例方法 defineExpose({ + layers, // 图层数据 getCanvasManager: () => canvasManager, // 获取画布管理器实例 + // type : isBackground isFixed flag: 是否可擦除图层 + setFixedLayerErasable: ({ type = "isFixed", flag = false }) => { + canvasManager?.setFixedLayerErasable({ + type, + flag, // 设置操作类型为可擦除 + }); + }, // 获取fabric画布实例 canvasManagerLoaded, // 加载新数据到画布 loadJSON: (json, calllBack) => { diff --git a/src/component/Canvas/CanvasEditor/managers/BrushIndicator.js b/src/component/Canvas/CanvasEditor/managers/BrushIndicator.js new file mode 100644 index 00000000..f23925dd --- /dev/null +++ b/src/component/Canvas/CanvasEditor/managers/BrushIndicator.js @@ -0,0 +1,483 @@ +import { fabric } from "fabric-with-all"; + +/** + * 笔刷指示器 + * 在画笔模式下显示当前笔刷大小的圆圈指示器 + */ +export class BrushIndicator { + /** + * 构造函数 + * @param {Object} canvas fabric.js画布实例 + * @param {Object} options 配置选项 + */ + constructor(canvas, options = {}) { + this.canvas = canvas; + this.options = { + strokeColor: options.strokeColor || "rgba(0, 0, 0, 0.5)", + strokeWidth: options.strokeWidth || 1, + fillColor: options.fillColor || "rgba(0, 0, 0, 0.1)", + ...options, + }; + + // 指示器圆圈对象 + this.indicator = null; + + // 事件处理器 + this._mouseEnterHandler = null; + this._mouseLeaveHandler = null; + this._mouseMoveHandler = null; + + // 当前状态 + this.isVisible = false; + this.currentSize = 10; + this.isEnabled = false; + } + + /** + * 启用笔刷指示器 + * @param {Number} brushSize 笔刷大小 + */ + enable(brushSize) { + if (this.isEnabled) return; + + this.isEnabled = true; + this.currentSize = brushSize; + + // 绑定事件 + this._bindEvents(); + } + + /** + * 禁用笔刷指示器 + */ + disable() { + if (!this.isEnabled) return; + + this.isEnabled = false; + + // 隐藏指示器 + this.hide(); + + // 重置颜色配置为默认值 + this.options.strokeColor = ""; + this.options.fillColor = ""; + + // 解绑事件 + this._unbindEvents(); + } + + /** + * 更新笔刷大小 + * @param {Number} size 新的笔刷大小 + */ + updateSize(size) { + this.currentSize = size; + + // 如果指示器正在显示,更新其大小 + if (this.isVisible && this.indicator) { + this._updateIndicatorSize(); + } + } + + /** + * 更新指示器颜色 + * @param {String} color 新的颜色值 + */ + updateColor(color) { + // 更新配置选项中的颜色 + if (color) { + this.options.strokeColor = color; + // 将颜色转换为半透明填充色 + // this.options.fillColor = this._convertToTransparentFill(color); + } + + // 如果指示器正在显示,更新其颜色 + if (this.isVisible && this.indicator) { + this.indicator.set({ + stroke: this.options.strokeColor, + fill: this.options.fillColor, + }); + + // 重新渲染画布 + this.canvas.requestRenderAll(); + } + } + + /** + * 显示指示器 + * @param {Object} pointer 鼠标位置 + */ + show(pointer) { + if (!this.isEnabled || this.isVisible) return; + + this.isVisible = true; + + // 创建指示器圆圈 + this._createIndicator(pointer); + } + + /** + * 隐藏指示器 + */ + hide() { + if (!this.isVisible || !this.indicator) return; + + this.isVisible = false; + + // 从画布移除指示器 + this.canvas.remove(this.indicator); + this.indicator = null; + + // 重新渲染画布 + this.canvas.renderAll(); + } + + /** + * 更新指示器位置 + * @param {Object} pointer 鼠标位置 + */ + updatePosition(pointer) { + if (!this.isVisible || !this.indicator) return; + + // 转换坐标考虑画布变换 + const canvasPointer = this.canvas.getPointer(pointer); + + // 批量更新位置属性 + this.indicator.set({ + left: canvasPointer.x, + top: canvasPointer.y, + }); + + // 更新坐标系 + this.indicator.setCoords(); + + // 使用requestRenderAll优化渲染性能 + this.canvas.requestRenderAll(); + } + + /** + * 绑定事件处理器 + * @private + */ + _bindEvents() { + if (!this.canvas) return; + + // 鼠标进入画布 + this._mouseEnterHandler = (e) => { + // 只在画笔相关模式下显示 + if (this._shouldShowIndicator()) { + this.show(e.e); + } + }; + + // 鼠标离开画布 + this._mouseLeaveHandler = () => { + this.hide(); + }; + + // 鼠标在画布上移动 - 修改事件处理逻辑 + this._mouseMoveHandler = (e) => { + // 如果正在绘图,不处理指示器更新,避免干扰绘图 + if (this.canvas._isCurrentlyDrawing) { + return; + } + + if (this._shouldShowIndicator()) { + if (!this.isVisible) { + this.show(e.e); + } else { + this.updatePosition(e.e); + } + } else { + this.hide(); + } + }; + + // 监听绘图开始事件,隐藏指示器并模拟微小移动 + this._drawingStartHandler = (e) => { + if (this.isVisible) { + this.hide(); + } + + // 模拟1px的微小移动来确保笔刷能正常启动绘画 + this._simulateTinyMovement(e); + }; + + // 监听绘图结束事件,重新显示指示器 + this._drawingEndHandler = () => { + // 延迟一点重新显示,确保绘图完全结束 + setTimeout(() => { + if (this._shouldShowIndicator() && !this.isVisible) { + // 重新检查鼠标位置并显示指示器 + this._checkAndShowIndicator(); + } + }, 50); + }; + + // 画布缩放变化处理器 + this._zoomHandler = () => { + if (this.isVisible && this.indicator) { + // 立即更新指示器大小 + this._updateIndicatorSize(); + } + }; + + // 画布视口变化处理器 + this._viewportHandler = () => { + if (this.isVisible && this.indicator) { + // 视口变化时也需要更新指示器 + this._updateIndicatorSize(); + } + }; + + // 绑定事件 + this.canvas.on("mouse:over", this._mouseEnterHandler); + this.canvas.on("mouse:out", this._mouseLeaveHandler); + this.canvas.on("mouse:move", this._mouseMoveHandler); + + // 监听绘图状态变化 + this.canvas.on("path:created", this._drawingEndHandler); + this.canvas.on("mouse:down", this._drawingStartHandler); + this.canvas.on("mouse:up", this._drawingEndHandler); + + // 监听画布缩放和视口变化 + this.canvas.on("after:render", this._zoomHandler); + this.canvas.on("canvas:zoomed", this._zoomHandler); + this.canvas.on("viewport:changed", this._viewportHandler); + } + + /** + * 解绑事件处理器 + * @private + */ + _unbindEvents() { + if (!this.canvas) return; + + if (this._mouseEnterHandler) { + this.canvas.off("mouse:over", this._mouseEnterHandler); + this._mouseEnterHandler = null; + } + + if (this._mouseLeaveHandler) { + this.canvas.off("mouse:out", this._mouseLeaveHandler); + this._mouseLeaveHandler = null; + } + + if (this._mouseMoveHandler) { + this.canvas.off("mouse:move", this._mouseMoveHandler); + this._mouseMoveHandler = null; + } + + // 清理绘图相关事件 + if (this._drawingStartHandler) { + this.canvas.off("mouse:down", this._drawingStartHandler); + this.canvas.off("path:created", this._drawingEndHandler); + this.canvas.off("mouse:up", this._drawingEndHandler); + this._drawingStartHandler = null; + this._drawingEndHandler = null; + } + + // 清理缩放相关事件 + if (this._zoomHandler) { + this.canvas.off("after:render", this._zoomHandler); + this.canvas.off("canvas:zoomed", this._zoomHandler); + this._zoomHandler = null; + } + + if (this._viewportHandler) { + this.canvas.off("viewport:changed", this._viewportHandler); + this._viewportHandler = null; + } + } + + /** + * 创建指示器圆圈 + * @private + * @param {Object} pointer 鼠标位置 + */ + _createIndicator(pointer) { + // 转换坐标考虑画布变换 + const canvasPointer = this.canvas.getPointer(pointer); + + // 计算考虑画布缩放的半径 + const radius = this._getIndicatorRadius(); + + // 创建圆圈 + this.indicator = new fabric.Circle({ + left: canvasPointer.x, + top: canvasPointer.y, + radius: radius, + fill: this.options.fillColor, + stroke: this.options.strokeColor, + strokeWidth: this.options.strokeWidth / this.canvas.getZoom(), // 线宽不受缩放影响 + originX: "center", + originY: "center", + selectable: false, + evented: false, + excludeFromExport: true, // 导出时排除 + isTemp: true, // 标记为临时对象 + pointer: true, // 标记为鼠标指示器 + }); + + // 添加到画布 + this.canvas.add(this.indicator); + + // 确保指示器在最顶层 + this.canvas.bringToFront(this.indicator); + + // 重新渲染画布 + this.canvas.renderAll(); + } + + /** + * 更新指示器大小 + * @private + */ + _updateIndicatorSize() { + if (!this.indicator) return; + + // 获取当前画布缩放比例 + const zoom = this.canvas.getZoom(); + const radius = this._getIndicatorRadius(); + const strokeWidth = this.options.strokeWidth / zoom; + + // 批量更新属性,减少重绘次数 + this.indicator.set({ + radius: radius, + strokeWidth: strokeWidth, + }); + + // 标记指示器需要重绘 + this.indicator.setCoords(); + + // 重新渲染画布 + this.canvas.requestRenderAll(); + } + + /** + * 获取指示器半径(与笔刷实际绘制大小一致) + * @private + * @returns {Number} 半径值 + */ + _getIndicatorRadius() { + // 指示器大小应该与笔刷实际绘制大小一致 + // 笔刷的实际绘制大小不受画布缩放影响,所以指示器也不应该受缩放影响 + return this.currentSize / 2; + } + + /** + * 判断是否应该显示指示器 + * @private + * @returns {Boolean} 是否显示 + */ + _shouldShowIndicator() { + // 检查画布是否在绘图模式 + if (!this.canvas.isDrawingMode) return false; + + // 检查是否有笔刷 + if (!this.canvas.freeDrawingBrush) return false; + + return true; + } + + /** + * 检查并显示指示器(如果鼠标在画布内) + * @private + */ + _checkAndShowIndicator() { + // 这个方法用于在绘图结束后重新显示指示器 + // 由于无法直接获取当前鼠标位置,我们依赖下一次鼠标移动事件 + } + + /** + * 模拟微小移动 + * @private + * @param {Object} e 鼠标事件对象 + */ + _simulateTinyMovement(e) { + // 获取当前鼠标位置 + const pointer = this.canvas.getPointer(e.e); + + // 模拟移动1px + this.canvas.fire("mouse:move", { + ...e, + e: { + ...e.e, + clientX: pointer.x + 1, + clientY: pointer.y + 1, + pointer: { + x: pointer.x + 1, + y: pointer.y + 1, + }, + }, + }); + + // 再模拟移动回原位置 + this.canvas.fire("mouse:move", { + ...e, + e: { + ...e.e, + clientX: pointer.x, + clientY: pointer.y, + pointer: { + x: pointer.x, + y: pointer.y, + }, + }, + }); + } + + /** + * 销毁指示器 + */ + dispose() { + this.disable(); + this.canvas = null; + this.indicator = null; + this.options = null; + } + + /** + * 将颜色转换为半透明填充色 + * @private + * @param {String} color 原始颜色值 + * @returns {String} 半透明填充色 + */ + _convertToTransparentFill(color) { + // 如果已经是 rgba 格式,直接使用但降低透明度 + if (color.startsWith("rgba")) { + return color.replace(/[\d\.]+\)$/, "0.1)"); + } + + // 如果是 rgb 格式,转换为 rgba + if (color.startsWith("rgb")) { + return color.replace("rgb", "rgba").replace(")", ", 0.1)"); + } + + // 如果是十六进制格式,转换为 rgba + if (color.startsWith("#")) { + const hex = color.slice(1); + let r, g, b; + + if (hex.length === 3) { + // 处理 #RGB 格式 + r = parseInt(hex[0] + hex[0], 16); + g = parseInt(hex[1] + hex[1], 16); + b = parseInt(hex[2] + hex[2], 16); + } else if (hex.length === 6) { + // 处理 #RRGGBB 格式 + r = parseInt(hex.slice(0, 2), 16); + g = parseInt(hex.slice(2, 4), 16); + b = parseInt(hex.slice(4, 6), 16); + } else { + // 无法解析的格式,返回默认半透明黑色 + return "rgba(0, 0, 0, 0.1)"; + } + + return `rgba(${r}, ${g}, ${b}, 0.1)`; + } + + // 处理命名颜色或其他格式,使用默认半透明效果 + return "rgba(0, 0, 0, 0.1)"; + } +} diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 89db592f..a9a8ae00 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -328,6 +328,26 @@ export class CanvasManager { this.canvas.renderAll(); } + // 设置固定图层可擦除状态 + setFixedLayerErasable({ type = "isFixed", flag = false }) { + const layer = this.layers.value.find((layer) => layer[type]); + if (layer) { + // 设置固定图层的可擦除状态 + layer.locked = flag; + // 更新画布对象的erasable属性 + const fabricObject = this.canvas + .getObjects() + .find((obj) => obj.id === layer.id); + if (fabricObject) { + fabricObject.erasable = flag; + fabricObject.set("erasable", flag); + fabricObject.setCoords(); // 更新控制点坐标 + this.canvas.renderAll(); // 重新渲染画布 + } + return; + } + } + setCanvasSize(width, height) { this.width = width; this.height = height; diff --git a/src/component/Canvas/CanvasEditor/managers/LayerManager.js b/src/component/Canvas/CanvasEditor/managers/LayerManager.js index 4be2c749..67cb0d99 100644 --- a/src/component/Canvas/CanvasEditor/managers/LayerManager.js +++ b/src/component/Canvas/CanvasEditor/managers/LayerManager.js @@ -225,10 +225,11 @@ export class LayerManager { // 图层状态决定交互性 if (layer.isBackground || obj.isBackground || layer.isFixed) { + //|| layer.isFixed // 背景层永远不可选择和擦除 obj.selectable = false; obj.evented = false; - obj.erasable = false; + obj.erasable = !layer.locked; } else if (layer.locked) { // 锁定图层不可交互和擦除 obj.selectable = false; diff --git a/src/component/Canvas/CanvasEditor/managers/ToolManager.js b/src/component/Canvas/CanvasEditor/managers/ToolManager.js index c6d46561..3abf8369 100644 --- a/src/component/Canvas/CanvasEditor/managers/ToolManager.js +++ b/src/component/Canvas/CanvasEditor/managers/ToolManager.js @@ -1,5 +1,6 @@ import { BrushStore } from "../store/BrushStore"; import { BrushManager } from "./brushes/brushManager"; +import { BrushIndicator } from "./BrushIndicator"; import { ToolCommand } from "../commands/ToolCommands"; import { CreateTextCommand } from "../commands/TextCommands"; import { OperationType } from "../utils/layerHelper"; @@ -47,6 +48,16 @@ export class ToolManager { layerManager: this.layerManager, // 传入图层管理器引用 }); + // 初始化笔刷指示器 + this.brushIndicator = null; + if (this.canvas) { + this.brushIndicator = new BrushIndicator(this.canvas, { + strokeColor: "rgba(0, 0, 0, 0.6)", + strokeWidth: 1, + fillColor: "rgba(0, 0, 0, 0.1)", + }); + } + // 观察者列表 this.observers = []; @@ -337,6 +348,11 @@ export class ToolManager { // 保存先前的工具 this.previousTool = this.activeTool.value; + // 如果切换到非画笔工具,禁用笔刷指示器 + if (!this._shouldShowBrushIndicator(toolId)) { + this._disableBrushIndicator(); + } + // 设置新工具 this.activeTool.value = toolId; @@ -465,6 +481,9 @@ export class ToolManager { // 更新应用到画布 this.brushManager.updateBrush(); } + + // 启用笔刷指示器并同步颜色 + this._enableBrushIndicator(); } /** @@ -479,6 +498,9 @@ export class ToolManager { if (this.brushManager) { this.brushManager.createEraser(); } + + // 启用笔刷指示器 + this._enableBrushIndicator(); } /** @@ -953,6 +975,9 @@ export class ToolManager { // 更新应用到画布 this.brushManager.updateBrush(); + + // 更新笔刷指示器大小 + this.updateBrushIndicatorSize(size); } /** @@ -1046,6 +1071,9 @@ export class ToolManager { // 更新应用到画布 this.brushManager.updateBrush(); + + // 更新笔刷指示器颜色 + this.updateBrushIndicatorColor(color); } /** @@ -1126,6 +1154,12 @@ export class ToolManager { this.brushManager.dispose(); } + // 清理笔刷指示器 + if (this.brushIndicator) { + this.brushIndicator.dispose(); + this.brushIndicator = null; + } + // 移除文本编辑相关事件监听器 if (this.canvas) { this.canvas.off("mouse:dblclick", this._textEditHandler); @@ -1160,10 +1194,12 @@ export class ToolManager { this.canvas.isDrawingMode = true; this.canvas.selection = false; + const redColor = "#FF0000"; + // 确保有笔刷管理器 if (this.brushManager) { // 设置红色笔刷 - this.brushManager.setBrushColor("#FF0000"); // 纯红色 + this.brushManager.setBrushColor(redColor); // 纯红色 this.brushManager.setBrushOpacity(1.0); // 完全不透明 this.brushManager.setBrushType("pencil"); // 铅笔类型 @@ -1175,6 +1211,9 @@ export class ToolManager { // 更新应用到画布 this.brushManager.updateBrush(); } + + // 启用笔刷指示器并设置红色 + this._enableBrushIndicator(redColor); } /** @@ -1186,10 +1225,12 @@ export class ToolManager { this.canvas.isDrawingMode = true; this.canvas.selection = false; + const greenColor = "#00FF00"; + // 确保有笔刷管理器 if (this.brushManager) { // 设置绿色笔刷 - this.brushManager.setBrushColor("#00FF00"); // 纯绿色 + this.brushManager.setBrushColor(greenColor); // 纯绿色 this.brushManager.setBrushOpacity(1.0); // 完全不透明 this.brushManager.setBrushType("pencil"); // 铅笔类型 @@ -1201,6 +1242,9 @@ export class ToolManager { // 更新应用到画布 this.brushManager.updateBrush(); } + + // 启用笔刷指示器并设置绿色 + this._enableBrushIndicator(greenColor); } /** @@ -1264,4 +1308,135 @@ export class ToolManager { const tool = this.tools[toolId]; return tool && tool.redGreenOnly === true; } + + /** + * 启用笔刷指示器 + * @param {String} color 笔刷颜色(可选) + * @private + */ + _enableBrushIndicator(color) { + if (!this.brushIndicator) return; + + // 获取当前笔刷大小 + const brushSize = this._getCurrentBrushSize(); + + // 获取当前笔刷颜色 + const brushColor = color || this._getCurrentBrushColor(); + + // 启用指示器 + this.brushIndicator.enable(brushSize); + + // 更新指示器颜色 + this.brushIndicator.updateColor(brushColor); + + console.log(`笔刷指示器已启用,大小: ${brushSize}, 颜色: ${brushColor}`); + } + + /** + * 禁用笔刷指示器 + * @private + */ + _disableBrushIndicator() { + if (!this.brushIndicator) return; + + this.brushIndicator.disable(); + console.log("笔刷指示器已禁用"); + } + + /** + * 更新笔刷指示器大小 + * @param {Number} size 新的笔刷大小 + */ + updateBrushIndicatorSize(size) { + if (!this.brushIndicator) return; + + this.brushIndicator.updateSize(size); + } + + /** + * 更新笔刷指示器颜色 + * @param {String} color 新的笔刷颜色 + */ + updateBrushIndicatorColor(color) { + if (!this.brushIndicator) return; + + this.brushIndicator.updateColor(color); + } + + /** + * 获取当前笔刷大小 + * @private + * @returns {Number} 当前笔刷大小 + */ + _getCurrentBrushSize() { + // 优先从 BrushStore 获取 + if (BrushStore && BrushStore.state.size) { + return BrushStore.state.size; + } + + // 从笔刷管理器获取 + if (this.brushManager && this.brushManager.getBrushSize) { + return this.brushManager.getBrushSize(); + } + + // 从画布笔刷获取 + if ( + this.canvas && + this.canvas.freeDrawingBrush && + this.canvas.freeDrawingBrush.width + ) { + return this.canvas.freeDrawingBrush.width; + } + + // 默认值 + return 10; + } + + /** + * 获取当前笔刷颜色 + * @private + * @returns {String} 当前笔刷颜色 + */ + _getCurrentBrushColor() { + // 优先从 BrushStore 获取 + if (BrushStore && BrushStore.state.color) { + return BrushStore.state.color; + } + + // 从笔刷管理器获取 + if (this.brushManager && this.brushManager.getBrushColor) { + return this.brushManager.getBrushColor(); + } + + // 从画布笔刷获取 + if ( + this.canvas && + this.canvas.freeDrawingBrush && + this.canvas.freeDrawingBrush.color + ) { + return this.canvas.freeDrawingBrush.color; + } + + // 默认值 + return "#000000"; + } + + /** + * 检查当前工具是否需要显示笔刷指示器 + * @param {String} toolId 工具ID(可选,不传则使用当前工具) + * @returns {Boolean} 是否需要显示 + */ + _shouldShowBrushIndicator(toolId) { + const currentTool = toolId || this.activeTool.value; + + // 画笔相关工具需要显示指示器 + const brushTools = [ + OperationType.DRAW, + OperationType.ERASER, + OperationType.RED_BRUSH, + OperationType.GREEN_BRUSH, + ]; + + return brushTools.includes(currentTool); + } }