2026-03-09 13:44:32 +08:00
|
|
|
|
import { ref } from 'vue'
|
|
|
|
|
|
import { OperationType } from '../tools/layerHelper'
|
2026-03-11 15:34:56 +08:00
|
|
|
|
import { BrushManager } from "./brushes/brushManager";
|
|
|
|
|
|
import { BrushIndicator } from "./BrushIndicator";
|
|
|
|
|
|
import i18n from "@/lang";
|
|
|
|
|
|
const t = i18n.global.t
|
2026-03-06 15:50:05 +08:00
|
|
|
|
export class ToolManager {
|
|
|
|
|
|
stateManager: any
|
2026-03-09 13:44:32 +08:00
|
|
|
|
canvasManager: any
|
|
|
|
|
|
currentTool: any
|
2026-03-11 15:34:56 +08:00
|
|
|
|
brushManager: any
|
2026-03-09 13:44:32 +08:00
|
|
|
|
tools: any[]
|
2026-03-11 15:34:56 +08:00
|
|
|
|
brushIndicator: any
|
2026-03-06 15:50:05 +08:00
|
|
|
|
constructor(options) {
|
|
|
|
|
|
this.stateManager = options.stateManager;
|
2026-03-09 13:44:32 +08:00
|
|
|
|
this.canvasManager = options.canvasManager;
|
|
|
|
|
|
this.currentTool = ref(null)
|
2026-03-11 15:34:56 +08:00
|
|
|
|
|
2026-03-09 13:44:32 +08:00
|
|
|
|
this.tools = [
|
|
|
|
|
|
/** 选择工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.SELECT,
|
|
|
|
|
|
cursor: "default",
|
|
|
|
|
|
setup: this.setupSelectTool.bind(this),
|
|
|
|
|
|
selection: true,
|
|
|
|
|
|
},
|
|
|
|
|
|
/** 移动工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.PAN,
|
|
|
|
|
|
cursor: "grab",
|
|
|
|
|
|
setup: this.setupMoveTool.bind(this),
|
|
|
|
|
|
},
|
|
|
|
|
|
/** 画笔工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.DRAW,
|
|
|
|
|
|
cursor: "crosshair",
|
2026-03-11 15:34:56 +08:00
|
|
|
|
setup: this.setupBrushTool.bind(this),
|
|
|
|
|
|
isDrawingMode: true,
|
2026-03-09 13:44:32 +08:00
|
|
|
|
},
|
|
|
|
|
|
/** 橡皮擦工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.ERASER,
|
|
|
|
|
|
cursor: "crosshair",
|
2026-03-11 15:34:56 +08:00
|
|
|
|
setup: this.setupEraserTool.bind(this),
|
|
|
|
|
|
isDrawingMode: true,
|
2026-03-09 13:44:32 +08:00
|
|
|
|
},
|
|
|
|
|
|
/** 智能选框工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.SELECTBOX,
|
|
|
|
|
|
cursor: "crosshair",
|
|
|
|
|
|
},
|
|
|
|
|
|
/** 矩形工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.RECTANGLE,
|
|
|
|
|
|
cursor: "crosshair",
|
|
|
|
|
|
},
|
2026-03-17 17:17:48 +08:00
|
|
|
|
/** 直线工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.LINE,
|
|
|
|
|
|
cursor: "crosshair",
|
|
|
|
|
|
},
|
|
|
|
|
|
/** 箭头工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.ARROW,
|
|
|
|
|
|
cursor: "crosshair",
|
|
|
|
|
|
},
|
|
|
|
|
|
/** 椭圆工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.ELLIPSE,
|
|
|
|
|
|
cursor: "crosshair",
|
|
|
|
|
|
},
|
|
|
|
|
|
/** 三角形工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.TRIANGLE,
|
|
|
|
|
|
cursor: "crosshair",
|
|
|
|
|
|
},
|
|
|
|
|
|
/** 五角星工具 */
|
|
|
|
|
|
{
|
|
|
|
|
|
name: OperationType.STAR,
|
|
|
|
|
|
cursor: "crosshair",
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2026-03-09 13:44:32 +08:00
|
|
|
|
]
|
2026-03-06 15:50:05 +08:00
|
|
|
|
}
|
2026-03-11 15:34:56 +08:00
|
|
|
|
onMounted() {
|
|
|
|
|
|
this.brushIndicator = new BrushIndicator(this.canvasManager.canvas, {
|
|
|
|
|
|
strokeColor: "rgba(0, 0, 0, 0.6)",
|
|
|
|
|
|
strokeWidth: 1,
|
|
|
|
|
|
fillColor: "rgba(0, 0, 0, 0.1)",
|
|
|
|
|
|
});
|
|
|
|
|
|
this.brushManager = new BrushManager({
|
|
|
|
|
|
canvas: this.canvasManager.canvas,
|
|
|
|
|
|
layerManager: this.canvasManager.layerManager, // 传入图层管理器引用
|
|
|
|
|
|
brushIndicator: this.brushIndicator,
|
|
|
|
|
|
t,
|
|
|
|
|
|
});
|
|
|
|
|
|
this.stateManager.setManager({
|
|
|
|
|
|
brushManager: this.brushManager,
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2026-03-06 15:50:05 +08:00
|
|
|
|
setTool(value: string) {
|
2026-03-09 13:44:32 +08:00
|
|
|
|
const tool = this.tools.find((t) => t.name === value)
|
2026-03-06 15:50:05 +08:00
|
|
|
|
if (!tool) return console.warn(`工具${tool}不存在`)
|
2026-03-09 13:44:32 +08:00
|
|
|
|
this.currentTool.value = tool.name
|
|
|
|
|
|
this.canvasManager.canvas.defaultCursor = tool.cursor
|
|
|
|
|
|
this.setCanvasEvented(!!tool.selection)
|
2026-03-11 15:34:56 +08:00
|
|
|
|
this.canvasManager.canvas.isDrawingMode = !!tool.isDrawingMode;// 绘制模式
|
|
|
|
|
|
if (!tool.isDrawingMode) this._disableBrushIndicator()// 非绘制模式,禁用笔刷指示器
|
|
|
|
|
|
|
2026-03-06 15:50:05 +08:00
|
|
|
|
|
2026-03-09 13:44:32 +08:00
|
|
|
|
if (tool.setup) tool.setup()
|
2026-03-11 15:34:56 +08:00
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
this.canvasManager.renderAll()
|
|
|
|
|
|
});
|
2026-03-09 13:44:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
// 切换工具时,设置画布事件
|
|
|
|
|
|
setCanvasEvented(value: boolean) {
|
|
|
|
|
|
this.canvasManager.canvas.selection = value
|
|
|
|
|
|
this.canvasManager.canvas.getObjects().forEach((v) => v.evented = value)
|
|
|
|
|
|
}
|
|
|
|
|
|
/** 选择工具 */
|
|
|
|
|
|
setupSelectTool() {
|
|
|
|
|
|
}
|
|
|
|
|
|
/** 移动工具 */
|
|
|
|
|
|
setupMoveTool() {
|
|
|
|
|
|
}
|
2026-03-11 15:34:56 +08:00
|
|
|
|
/** 画笔工具 */
|
|
|
|
|
|
setupBrushTool() {
|
|
|
|
|
|
if (!this.canvasManager.canvas) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 确保有笔刷管理器
|
|
|
|
|
|
if (this.brushManager) {
|
|
|
|
|
|
// 检查画笔是否正在更新中
|
|
|
|
|
|
if (this.brushManager.isUpdatingBrush) {
|
|
|
|
|
|
console.warn("画笔正在更新中,请稍候...");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const brushStore = this.brushManager?.brushStore
|
|
|
|
|
|
if (brushStore) {
|
|
|
|
|
|
// 同步基本属性
|
|
|
|
|
|
this.brushManager.setBrushSize(brushStore.state.size);
|
|
|
|
|
|
this.brushManager.setBrushColor(brushStore.state.color);
|
|
|
|
|
|
this.brushManager.setBrushOpacity(brushStore.state.opacity);
|
|
|
|
|
|
|
|
|
|
|
|
// 同步笔刷类型 - 修复方法名,使用正确的setBrushType方法
|
|
|
|
|
|
this.brushManager.setBrushType("pencil");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新应用到画布
|
|
|
|
|
|
this.brushManager.updateBrush();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 启用笔刷指示器并同步颜色
|
|
|
|
|
|
this._enableBrushIndicator();
|
|
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置橡皮擦工具
|
|
|
|
|
|
*/
|
|
|
|
|
|
setupEraserTool() {
|
|
|
|
|
|
if (!this.canvasManager.canvas) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 确保有笔刷管理器
|
|
|
|
|
|
if (this.brushManager) {
|
|
|
|
|
|
this.brushManager.createEraser();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.stateManager.layerManager.setActiveObjectErasable()
|
|
|
|
|
|
// 启用笔刷指示器
|
|
|
|
|
|
this._enableBrushIndicator();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 启用笔刷指示器
|
|
|
|
|
|
* @param {String} color 笔刷颜色(可选)
|
|
|
|
|
|
* @private
|
|
|
|
|
|
*/
|
|
|
|
|
|
_enableBrushIndicator(color?: string) {
|
|
|
|
|
|
if (!this.brushIndicator) return;
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前笔刷大小
|
|
|
|
|
|
const brushSize = this.brushManager?.getBrushSize() || 5;
|
|
|
|
|
|
// 获取当前笔刷颜色
|
|
|
|
|
|
const brushColor = color || this.brushManager?.getBrushColor() || "#000000";
|
|
|
|
|
|
|
|
|
|
|
|
// 启用指示器
|
|
|
|
|
|
this.brushIndicator.enable(brushSize);
|
|
|
|
|
|
this.brushIndicator.updateSize(brushSize);
|
|
|
|
|
|
// 更新指示器颜色
|
|
|
|
|
|
this.brushIndicator.updateColor(brushColor);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 禁用笔刷指示器 */
|
|
|
|
|
|
_disableBrushIndicator() {
|
|
|
|
|
|
if (!this.brushIndicator) return;
|
|
|
|
|
|
|
|
|
|
|
|
this.brushIndicator.disable();
|
|
|
|
|
|
}
|
2026-03-12 11:40:48 +08:00
|
|
|
|
dispose() {
|
|
|
|
|
|
this.brushIndicator?.dispose()
|
|
|
|
|
|
this.brushManager?.dispose()
|
|
|
|
|
|
}
|
2026-03-06 15:50:05 +08:00
|
|
|
|
}
|