721 lines
19 KiB
JavaScript
721 lines
19 KiB
JavaScript
|
|
//import { fabric } from "fabric-with-all";
|
|||
|
|
import { BrushStore } from "../../store/BrushStore";
|
|||
|
|
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 { SketchyBrush } from "./types/SketchyBrush";
|
|||
|
|
import { SpraypaintBrush } from "./types/SpraypaintBrush";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 笔刷管理器
|
|||
|
|
* 负责管理和切换不同的笔刷类型
|
|||
|
|
*/
|
|||
|
|
export class BrushManager {
|
|||
|
|
/**
|
|||
|
|
* 构造函数
|
|||
|
|
* @param {Object} options 配置选项
|
|||
|
|
* @param {Object} options.canvas fabric.js画布实例
|
|||
|
|
* @param {Object} options.brushStore 笔刷数据存储(可选)
|
|||
|
|
* @param {Object} options.layerManager 图层管理器实例(可选)
|
|||
|
|
*/
|
|||
|
|
constructor(options = {}) {
|
|||
|
|
this.canvas = options.canvas;
|
|||
|
|
this.brushStore = options.brushStore || BrushStore;
|
|||
|
|
this.layerManager = options.layerManager; // 添加图层管理器引用
|
|||
|
|
|
|||
|
|
// 当前活动笔刷
|
|||
|
|
this.activeBrush = null;
|
|||
|
|
this.activeBrushId = null;
|
|||
|
|
|
|||
|
|
// 初始化笔刷注册
|
|||
|
|
this._registerDefaultBrushes();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 注册默认笔刷
|
|||
|
|
* @private
|
|||
|
|
*/
|
|||
|
|
_registerDefaultBrushes() {
|
|||
|
|
// 注册铅笔笔刷
|
|||
|
|
brushRegistry.register("pencil", PencilBrush, {
|
|||
|
|
name: "铅笔",
|
|||
|
|
description: "基础铅笔工具,适合精细线条绘制",
|
|||
|
|
category: "基础笔刷",
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 注册材质笔刷
|
|||
|
|
brushRegistry.register("texture", TextureBrush);
|
|||
|
|
|
|||
|
|
// 注册集成的笔刷类型
|
|||
|
|
brushRegistry.register("crayon", CrayonBrush);
|
|||
|
|
brushRegistry.register("fur", FurBrush);
|
|||
|
|
brushRegistry.register("ink", InkBrush);
|
|||
|
|
brushRegistry.register("longfur", LongfurBrush);
|
|||
|
|
brushRegistry.register("writing", WritingBrush);
|
|||
|
|
brushRegistry.register("marker", MarkerBrush);
|
|||
|
|
brushRegistry.register("pen", CustomPenBrush);
|
|||
|
|
brushRegistry.register("ribbon", RibbonBrush);
|
|||
|
|
brushRegistry.register("shaded", ShadedBrush);
|
|||
|
|
brushRegistry.register("sketchy", SketchyBrush);
|
|||
|
|
brushRegistry.register("spraypaint", SpraypaintBrush);
|
|||
|
|
|
|||
|
|
// 注册喷枪笔刷
|
|||
|
|
brushRegistry.register(
|
|||
|
|
"spray",
|
|||
|
|
class SprayBrush extends PencilBrush {
|
|||
|
|
constructor(canvas, options = {}) {
|
|||
|
|
super(canvas, {
|
|||
|
|
id: "spray",
|
|||
|
|
name: "喷枪",
|
|||
|
|
description: "模拟喷枪效果,创建散点效果",
|
|||
|
|
category: "基础笔刷",
|
|||
|
|
...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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
);
|
|||
|
|
// 注册橡皮擦笔刷
|
|||
|
|
brushRegistry.register(
|
|||
|
|
"eraser",
|
|||
|
|
class EraserBrush extends PencilBrush {
|
|||
|
|
constructor(canvas, options = {}) {
|
|||
|
|
super(canvas, {
|
|||
|
|
id: "eraser",
|
|||
|
|
name: "橡皮擦",
|
|||
|
|
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,
|
|||
|
|
}));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 初始化笔刷列表并更新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,
|
|||
|
|
|
|||
|
|
// 材质笔刷特有配置
|
|||
|
|
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 });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新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,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新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));
|
|||
|
|
|
|||
|
|
// 更新笔刷透明度
|
|||
|
|
this.canvas.freeDrawingBrush.opacity = brushOpacity;
|
|||
|
|
|
|||
|
|
// 更新活动笔刷
|
|||
|
|
if (this.activeBrush) {
|
|||
|
|
this.activeBrush.configure(this.canvas.freeDrawingBrush, {
|
|||
|
|
opacity: brushOpacity,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取当前笔刷类型
|
|||
|
|
* @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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建橡皮擦
|
|||
|
|
* @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() {
|
|||
|
|
// 销毁当前笔刷
|
|||
|
|
if (this.activeBrush) {
|
|||
|
|
this.activeBrush.destroy();
|
|||
|
|
this.activeBrush = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.canvas = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 导出单例
|
|||
|
|
export default BrushManager;
|