import { fabric } from "fabric-with-all"; import "./fabric.brushes.js"; import { BrushState } from "./BrushStore.js"; import { brushRegistry } from "./BrushRegistry"; // 导入基础笔刷类型 import { PencilBrush } from "./types/PencilBrush"; import { TextureBrush } from "./types/TextureBrush"; // 导入集成的笔刷类型 import { CrayonBrush } from "./types/CrayonBrush"; import { FurBrush } from "./types/FurBrush"; import { InkBrush } from "./types/InkBrush"; import { LongfurBrush } from "./types/LongfurBrush"; import { WritingBrush } from "./types/WritingBrush"; import { MarkerBrush } from "./types/MarkerBrush"; import { CustomPenBrush } from "./types/CustomPenBrush"; import { RibbonBrush } from "./types/RibbonBrush"; import { ShadedBrush } from "./types/ShadedBrush"; import { EraserStateManager } from "../EraserStateManager.js"; import { SprayBrush } from "./types/SprayBrush"; // import { SketchyBrush } from "./types/SketchyBrush"; // import { SpraypaintBrush } from "./types/SpraypaintBrush"; /** * 笔刷管理器 * 负责管理和切换不同的笔刷类型 */ export class BrushManager { /** * 构造函数 * @param {Object} options 配置选项 * @param {Object} options.canvas fabric.js画布实例 * @param {Object} options.layerManager 图层管理器实例(可选) * @param {Object} options.brushIndicator 笔刷指示器实例(可选) * @param {Function} options.t 国际化函数 */ constructor(options = {}) { this.canvas = options.canvas; this.brushStore = new BrushState(); this.layerManager = options.layerManager; // 添加图层管理器引用 this.brushIndicator = options.brushIndicator; // 添加笔刷指示器引用 // this.t = options.t this.t = (v) => v // 当前活动笔刷 this.activeBrush = null; this.activeBrushId = null; // 初始化笔刷注册 this._registerDefaultBrushes(); // 初始化橡皮擦状态管理器 this.eraserStateManager = null; this.isErasingActive = false; this.currentErasedObjects = []; // 当前擦除会话中被影响的对象 } /** * 注册默认笔刷 * @private */ _registerDefaultBrushes() { // 注册铅笔笔刷 brushRegistry.register("pencil", PencilBrush, { name: this.t("Canvas.Pencil"), description: "基础铅笔工具,适合精细线条绘制", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/pencil.jpg', }); // 注册材质笔刷 brushRegistry.register("texture", TextureBrush, { name: this.t("Canvas.Texture"), description: "使用纹理图片作为笔刷,支持缩放和透明度", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/texture.jpg', }); // 注册集成的笔刷类型 brushRegistry.register("crayon", CrayonBrush, { name: this.t("Canvas.Crayon"), description: "使用纹理图片作为笔刷,支持缩放和透明度", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/crayon.jpg', }); brushRegistry.register("fur", FurBrush, { name: this.t("Canvas.Fur"), description: "使用纹理图片作为笔刷,支持缩放和透明度", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/fur.jpg', }); brushRegistry.register("ink", InkBrush, { name: this.t("Canvas.Ink"), description: "墨水笔刷,适合书写和绘图", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/ink.jpg', }); brushRegistry.register("", LongfurBrush, { name: this.t("Canvas.Longfur"), description: "长毛发笔刷,适合绘制动物毛皮、草或头发", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/longFur.jpg', }); brushRegistry.register("writing", WritingBrush, { name: this.t("Canvas.Writing"), description: "书法笔刷,模拟中国传统书法毛笔效果,具有笔锋和墨色变化", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/writing.jpg', }); brushRegistry.register("marker", MarkerBrush, { name: this.t("Canvas.Marker"), description: "马克笔笔刷,适合粗线条和填充", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/marker.jpg', }); brushRegistry.register("pen", CustomPenBrush, { name: this.t("Canvas.Pen"), description: "自定义钢笔笔刷,适合书写和绘图", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/pen.jpg', }); brushRegistry.register("ribbon", RibbonBrush, { name: this.t("Canvas.Ribbon"), description: "丝带笔刷,适合创建流动的丝带效果", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/ribbon.jpg', }); brushRegistry.register("shaded", ShadedBrush, { name: this.t("Canvas.Shaded"), description: "阴影笔刷,适合创建渐变和阴影效果", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/shaded.jpg', }); brushRegistry.register("spray", SprayBrush, { name: this.t("Canvas.Spray"), description: "模拟喷枪效果,创建散点效果", t: this.t, category: this.t('Canvas.BasicBrushes'), imgUrl: '/image/brush/spray.jpg', }); // brushRegistry.register("sketchy", SketchyBrush); // brushRegistry.register("spraypaint", SpraypaintBrush, { // name: "Spraypaint", // description: "喷漆笔刷,模拟喷漆效果", // t:this.t, // category: this.t('Canvas.BasicBrushes'), // }); // // // 注册喷枪笔刷 // brushRegistry.register( // "spray", // class SprayBrush extends PencilBrush { // constructor(canvas, options = {}) { // super(canvas, { // id: "spray", // name: "Spray", // description: "模拟喷枪效果,创建散点效果", // category: this.t('Canvas.BasicBrushes'), // ...options, // }); // } // create() { // this.brush = new fabric.SprayBrush(this.canvas); // this.configure(this.brush, this.options); // return this.brush; // } // configure(brush, options = {}) { // super.configure(brush, options); // if (options.density !== undefined) { // brush.density = options.density; // } // if (options.randomOpacity !== undefined) { // brush.randomOpacity = options.randomOpacity; // } // if (options.dotWidth !== undefined) { // brush.dotWidth = options.dotWidth; // } // } // }, // { // name: "喷枪", // description: "模拟喷枪效果,创建散点效果", // } // ); // 注册橡皮擦笔刷 const outerThis = this; brushRegistry.register( "eraser", class EraserBrush extends PencilBrush { constructor(canvas, options = {}) { super(canvas, { id: "eraser", name: "橡皮擦", t: outerThis.t, description: "擦除已绘制的内容", category: "工具", ...options, }); } create() { // 直接使用 fabric-with-erasing 库提供的 EraserBrush this.brush = new fabric.EraserBrush(this.canvas); this.configure(this.brush, this.options); // 配置橡皮擦特有属性 this.brush.inverted = this.options.inverted || false; // 是否反向擦除(恢复擦除) return this.brush; } configure(brush, options = {}) { super.configure(brush, options); // 橡皮擦特有配置 if (options.inverted !== undefined) { brush.inverted = options.inverted; } } /** * 设置反向擦除模式 * @param {Boolean} inverted 是否启用反向擦除(撤销擦除效果) */ setInverted(inverted) { if (this.brush) { this.brush.inverted = inverted; } } /** * 获取橡皮擦配置属性 * @returns {Array} 可配置属性数组 */ getConfigurableProperties() { return [ ...super.getConfigurableProperties(), { id: "inverted", name: "反向擦除", type: "boolean", description: "启用时可以恢复已擦除的内容", defaultValue: false, min: null, max: null, }, ]; } /** * 更新橡皮擦属性 * @param {String} propId 属性ID * @param {any} value 属性值 */ updateProperty(propId, value) { if (propId === "inverted") { this.setInverted(value); } else { super.updateProperty(propId, value); } } } ); // // 注册水彩笔刷 // brushRegistry.register( // "watercolor", // class WatercolorBrush extends PencilBrush { // constructor(canvas, options = {}) { // super(canvas, { // id: "watercolor", // name: "水彩", // description: "模拟水彩效果,带有流动感和透明感", // category: "特效笔刷", // ...options, // }); // } // create() { // // 创建一个自定义的PencilBrush来模拟水彩效果 // this.brush = new fabric.PencilBrush(this.canvas); // this.configure(this.brush, this.options); // // 水彩效果特有的属性 // this.brush.globalCompositeOperation = "multiply"; // this.brush.shadow = new fabric.Shadow({ // color: this.options.color || "#000", // blur: 5, // offsetX: 0, // offsetY: 0, // }); // return this.brush; // } // configure(brush, options = {}) { // super.configure(brush, options); // // 水彩笔刷特有的配置 // brush.opacity = Math.min(0.5, options.opacity || 0.3); // 默认透明度30% // } // } // ); // // 注册粉笔笔刷 // brushRegistry.register( // "chalk", // class ChalkBrush extends PencilBrush { // constructor(canvas, options = {}) { // super(canvas, { // id: "chalk", // name: "粉笔", // description: "模拟粉笔效果,有颗粒感和不连续性", // category: "特效笔刷", // ...options, // }); // } // create() { // this.brush = new fabric.PencilBrush(this.canvas); // this.configure(this.brush, this.options); // // 自定义绘画方法来模拟粉笔效果 // const originalOnMouseMove = this.brush.onMouseMove; // this.brush.onMouseMove = function (pointer, options) { // // 随机调整坐标位置,增加粉笔质感 // const jitter = 2; // pointer.x += (Math.random() - 0.5) * jitter; // pointer.y += (Math.random() - 0.5) * jitter; // // 调用原始方法 // originalOnMouseMove.call(this, pointer, options); // }; // return this.brush; // } // configure(brush, options = {}) { // super.configure(brush, options); // // 粉笔特有的设置 // brush.strokeDashArray = [5, 5]; // 虚线效果 // } // } // ); } /** * 获取所有可用笔刷类型 * @returns {Array} 笔刷类型数组,包含id、name和description */ getBrushTypes() { // 从注册表获取所有笔刷信息 const brushes = brushRegistry.getAllBrushes(); // 将笔刷信息转换为期望的格式 return brushes.map((brushInfo) => ({ id: brushInfo.id, name: brushInfo.metadata.name || brushInfo.id, description: brushInfo.metadata.description || "", category: brushInfo.metadata.category || "默认", icon: brushInfo.metadata.icon || null, imgUrl: brushInfo.metadata.imgUrl || null, })); } /** * 初始化笔刷列表并更新BrushStore */ initializeBrushes() { // 获取所有笔刷 const allBrushes = this.getBrushTypes(); // 更新BrushStore中的可用笔刷列表 this.brushStore.setAvailableBrushes(allBrushes); // 设置默认笔刷 if (!this.activeBrushId && allBrushes.length > 0) { this.setBrushType(allBrushes[0].id); } } /** * 设置笔刷类型 * @param {String} brushId 笔刷ID * @returns {Object|null} 设置的笔刷实例 */ setBrushType(brushId) { // 如果相同笔刷,不做处理 if (this.activeBrushId === brushId) { return this.activeBrush; } // 销毁当前笔刷 if (this.activeBrush) { // 调用生命周期方法 if (this.activeBrush.onDeselected) { this.activeBrush.onDeselected(); } this.activeBrush.destroy(); } // 创建新笔刷实例 try { const brushInstance = brushRegistry.createBrushInstance( brushId, this.canvas, { color: brushId === "eraser" ? this.brushStore.state.color : undefined, width: this.brushStore.state.size, opacity: this.brushStore.state.opacity, // 阴影相关配置 shadowEnabled: this.brushStore.state.shadowEnabled, shadowColor: this.brushStore.state.shadowColor, shadowWidth: this.brushStore.state.shadowWidth, shadowOffsetX: this.brushStore.state.shadowOffsetX, shadowOffsetY: this.brushStore.state.shadowOffsetY, // 材质笔刷特有配置 textureEnabled: this.brushStore.state.textureEnabled, texturePath: this.brushStore.state.texturePath, textureScale: this.brushStore.state.textureScale, } ); if (brushInstance) { // 创建笔刷 const fabricBrush = brushInstance.create(); // 更新画布的当前笔刷 if (fabricBrush) { this.canvas.freeDrawingBrush = fabricBrush; } // 更新当前笔刷引用 this.activeBrush = brushInstance; this.activeBrushId = brushId; // 调用生命周期方法 if (this.activeBrush.onSelected) { this.activeBrush.onSelected(); } // 更新Store的笔刷类型 this.brushStore.setBrushType(brushId); // 更新Store的当前笔刷实例,用于动态属性系统 this.brushStore.setCurrentBrushInstance(brushInstance); return brushInstance; } } catch (error) { console.error(`创建笔刷 ${brushId} 失败:`, error); } return null; } /** * 设置笔刷颜色 * @param {String} color 十六进制颜色值 */ setBrushColor(color) { if (!this.canvas.freeDrawingBrush) return; // 更新笔刷颜色 this.canvas.freeDrawingBrush.color = color; // 更新活动笔刷 if (this.activeBrush) { this.activeBrush.configure(this.canvas.freeDrawingBrush, { color }); } // 更新笔刷指示器大小 if (this.brushIndicator) { this.brushIndicator.updateColor(color); } // 更新Store this.brushStore.setBrushColor(color); } /** * 设置笔刷大小 * @param {Number} size 笔刷大小 */ setBrushSize(size) { if (!this.canvas.freeDrawingBrush) return; // 限制大小范围 const brushSize = Math.max(0.1, Math.min(100, size)); // 更新笔刷大小 this.canvas.freeDrawingBrush.width = brushSize; // 更新活动笔刷 if (this.activeBrush) { this.activeBrush.configure(this.canvas.freeDrawingBrush, { width: brushSize, }); } // 更新笔刷指示器大小 if (this.brushIndicator) { this.brushIndicator.updateSize(brushSize); } // 更新Store this.brushStore.setBrushSize(brushSize); return brushSize; } /** * 增加笔刷大小 * @param {Number} amount 增加量 * @returns {Number} 新的笔刷大小 */ increaseBrushSize(amount = 1) { const currentSize = this.brushStore.state.size; return this.setBrushSize(currentSize + amount); } /** * 减少笔刷大小 * @param {Number} amount 减少量 * @returns {Number} 新的笔刷大小 */ decreaseBrushSize(amount = 1) { const currentSize = this.brushStore.state.size; return this.setBrushSize(currentSize - amount); } /** * 增加笔刷透明度 * @param {Number} amount 增加量 * @returns {Number} 新的笔刷大小 */ increaseBrushOpacity(amount = 0.01) { const currentSize = this.brushStore.state.opacity; return this.setBrushOpacity(currentSize + amount); } /** * 减少笔刷大小 * @param {Number} amount 减少量 * @returns {Number} 新的笔刷大小 */ decreaseBrushOpacity(amount = 0.01) { const currentSize = this.brushStore.state.opacity; return this.setBrushOpacity(currentSize - amount); } /** * 设置笔刷透明度 * @param {Number} opacity 透明度 (0-1) */ setBrushOpacity(opacity) { if (!this.canvas.freeDrawingBrush) return; // 限制透明度范围 const brushOpacity = Math.max(0.05, Math.min(1, opacity)); // 不再设置fabric笔刷的opacity属性,而是通过颜色的RGBA值来实现透明度 // this.canvas.freeDrawingBrush.opacity = brushOpacity; // 更新活动笔刷配置,使用当前颜色和新的透明度 if (this.activeBrush) { const currentColor = this.brushStore.state.color; this.activeBrush.configure(this.canvas.freeDrawingBrush, { color: currentColor, opacity: brushOpacity, }); } // 确保上下文透明度始终为1,避免全局透明度问题 if (this.canvas.contextTop) { this.canvas.contextTop.globalAlpha = 1; } // 更新Store this.brushStore.setBrushOpacity(brushOpacity); return brushOpacity; } /** * 设置材质缩放 * @param {Number} scale 缩放比例 */ setTextureScale(scale) { // 限制缩放范围 const textureScale = Math.max(0.1, Math.min(10, scale)); // 更新活动笔刷 if (this.activeBrush && this.activeBrush.setTextureScale) { this.activeBrush.setTextureScale(textureScale); } // 更新Store this.brushStore.setTextureScale(textureScale); return textureScale; } /** * 增加材质缩放 * @param {Number} amount 增加量 */ increaseTextureScale(amount = 0.1) { const currentScale = this.brushStore.state.textureScale; return this.setTextureScale(currentScale + amount); } /** * 减少材质缩放 * @param {Number} amount 减少量 */ decreaseTextureScale(amount = 0.1) { const currentScale = this.brushStore.state.textureScale; return this.setTextureScale(currentScale - amount); } /** * 设置材质路径 * @param {String} path 材质图片路径 */ setTexturePath(path) { // 更新活动笔刷 if (this.activeBrush && this.activeBrush.setTexturePath) { this.activeBrush.setTexturePath(path); } // 更新Store this.brushStore.setTexturePath(path); return path; } /** * 启用/禁用材质 * @param {Boolean} enabled 是否启用 */ setTextureEnabled(enabled) { // 更新Store this.brushStore.setTextureEnabled(enabled); // 如果启用材质,且当前不是材质笔刷,需要切换 if (enabled && this.activeBrushId !== "texture") { this.setBrushType("texture"); } return enabled; } /** * 注册新笔刷 * @param {String} id 笔刷ID * @param {Class} brushClass 笔刷类 * @param {Object} metadata 笔刷元数据 * @returns {Boolean} 是否注册成功 */ registerBrush(id, brushClass, metadata = {}) { const success = brushRegistry.register(id, brushClass, metadata); if (success) { // 更新可用笔刷列表 this.initializeBrushes(); } return success; } /** * 设置依赖管理器 */ setManagers({ layerManager, commandManager }) { this.layerManager = layerManager; this.commandManager = commandManager; // 初始化橡皮擦状态管理器 if (this.canvas && this.layerManager) { this.eraserStateManager = new EraserStateManager( this.canvas, this.layerManager ); } } /** * 绑定橡皮擦事件处理器 * @private */ _bindEraserEvents() { if (!this.canvas || !this.eraserStateManager) return; // 监听擦除开始事件 this.canvas.on("erasing:start", this._handleErasingStart.bind(this)); // 监听擦除结束事件 this.canvas.on("erasing:end", this._handleErasingEnd.bind(this)); } /** * 解绑橡皮擦事件处理器 * @private */ _unbindEraserEvents() { if (!this.canvas) return; this.canvas.off("erasing:start", this._handleErasingStart.bind(this)); this.canvas.off("erasing:end", this._handleErasingEnd.bind(this)); } /** * 处理擦除开始事件 * @param {Object} e 事件对象 * @private */ _handleErasingStart(e) { console.log("橡皮擦开始擦除"); if (!this.eraserStateManager) return; // 标记擦除状态 this.isErasingActive = true; this.currentErasedObjects = []; // 捕获擦除前的状态 this.eraserStateManager.startErasing(); } /** * 处理擦除结束事件 * @param {Object} e 事件对象 * @private */ _handleErasingEnd(e) { console.log("橡皮擦擦除结束", e); if (!this.eraserStateManager || !this.isErasingActive) return; // 获取被擦除的对象 const affectedObjects = e.targets || []; // 创建橡皮擦命令 const eraserCommand = this.eraserStateManager.endErasing(affectedObjects); // 如果有有效的命令且有命令管理器,执行命令 if (eraserCommand && this.commandManager) { // 注意:不需要调用 execute(),因为擦除操作已经完成 // 只需要将命令添加到历史记录中以支持撤销 this.commandManager.addToHistory(eraserCommand); console.log("橡皮擦操作已添加到命令历史"); } // 重置状态 this.isErasingActive = false; this.currentErasedObjects = []; } /** * 取消当前擦除操作 */ cancelErasing() { if (!this.isErasingActive) return; if (this.eraserStateManager) { this.eraserStateManager.cancelErasing(); } this.isErasingActive = false; this.currentErasedObjects = []; console.log("当前擦除操作已取消"); } /** * 获取当前笔刷类型 * @returns {String} 当前笔刷类型ID */ getCurrentBrushType() { return this.activeBrushId; } /** * 获取当前笔刷大小 * @returns {Number} 当前笔刷大小 */ getBrushSize() { return this.brushStore.state.size; } /** * 获取当前笔刷颜色 * @returns {String} 当前笔刷颜色 */ getBrushColor() { return this.brushStore.state.color; } /** * 获取当前笔刷透明度 * @returns {Number} 当前笔刷透明度 */ getBrushOpacity() { return this.brushStore.state.opacity; } /** * 获取材质缩放 * @returns {Number} 材质缩放比例 */ getTextureScale() { return this.brushStore.state.textureScale; } /** * 创建材质笔刷 * 这个方法保留用于向下兼容 * @deprecated 请使用setBrushType('texture')代替 * @returns {Object} 材质笔刷实例 */ createTextureBrush() { console.warn('createTextureBrush方法已废弃,请使用setBrushType("texture")'); return this.setBrushType("texture"); } /** * 更新笔刷 * 根据当前设置应用笔刷属性到画布 */ updateBrush() { if (!this.canvas) return; // 如果有活动的笔刷实例,重新配置它 if (this.activeBrush && this.canvas.freeDrawingBrush) { this.activeBrush.configure(this.canvas.freeDrawingBrush, { color: this.brushStore.state.color, width: this.brushStore.state.size, opacity: this.brushStore.state.opacity, }); } else { // 如果没有活动笔刷,创建一个默认的 this.setBrushType(this.activeBrushId || "pencil"); } // 更新画布状态 this?.canvas?.renderAll?.(); return this.canvas.freeDrawingBrush; } /** * 更新笔刷阴影设置 */ updateShadow() { if (this.activeBrush && this.activeBrush.updateShadow) { this.activeBrush.updateShadow(); } } // /** // * 创建橡皮擦 // * @param {Object} options 橡皮擦选项 // */ // createEraser(options = {}) { // if (!this.canvas) { // console.error("画布未初始化"); // return null; // } // try { // // 直接使用 fabric-with-erasing 库提供的 EraserBrush // this.brush = new fabric.EraserBrush(this.canvas); // // 应用配置 // this.configure(this.brush, { // width: this.brushSize.value, // color: this.brushColor.value, // opacity: this.brushOpacity.value, // inverted: options.inverted || false, // ...options, // }); // // 设置画布为绘图模式 // this.canvas.isDrawingMode = true; // this.canvas.freeDrawingBrush = this.brush; // // 绑定橡皮擦事件处理器 // // this._bindEraserEvents(); // console.log("橡皮擦创建成功"); // return this.brush; // } catch (error) { // console.error("创建橡皮擦失败:", error); // return null; // } // } /** * 创建橡皮擦 * @returns {Object} 橡皮擦笔刷 */ createEraser() { return this.setBrushType("eraser"); } /** * 创建吸色工具 * @param {Function} callback 选择颜色后的回调函数 */ createEyedropper(callback) { // 保存当前状态 const previousBrushId = this.activeBrushId; // 一次性事件处理程序 const handleMouseDown = (event) => { const pointer = this.canvas.getPointer(event.e); const ctx = this.canvas.getContext(); // 获取点击位置的像素 const imageData = ctx.getImageData(pointer.x, pointer.y, 1, 1).data; // 将RGB转换为十六进制颜色 const color = `#${( (1 << 24) + (imageData[0] << 16) + (imageData[1] << 8) + imageData[2] ) .toString(16) .slice(1)}`; // 调用回调函数 if (typeof callback === "function") { callback(color); } // 恢复之前的笔刷 this.setBrushType(previousBrushId); // 移除事件监听器 this.canvas.off("mouse:down", handleMouseDown); }; // 添加事件监听器 this.canvas.on("mouse:down", handleMouseDown); // 设置吸色光标 this.canvas.defaultCursor = "crosshair"; console.log("吸色工具已激活,点击画布选择颜色"); } /** * 销毁笔刷管理器 */ dispose() { // 解绑事件 // this._unbindEraserEvents(); // 取消进行中的擦除操作 this.cancelErasing(); // 清理状态管理器 if (this.eraserStateManager) { this.eraserStateManager = null; } // 销毁当前笔刷 if (this.activeBrush) { this.activeBrush.destroy(); this.activeBrush = null; } this.canvas = null; } } // 导出单例 export default BrushManager;