235 lines
5.8 KiB
JavaScript
235 lines
5.8 KiB
JavaScript
/**
|
||
* 笔刷基类
|
||
* 所有笔刷类型应继承此基类并实现必要的方法
|
||
*/
|
||
export class BaseBrush {
|
||
/**
|
||
* 构造函数
|
||
* @param {Object} canvas fabric画布实例
|
||
* @param {Object} options 笔刷配置选项
|
||
*/
|
||
constructor(canvas, options = {}) {
|
||
this.canvas = canvas;
|
||
this.options = options;
|
||
|
||
// 基本属性
|
||
this.id = options.id || this.constructor.name;
|
||
this.name = options.name || "未命名笔刷";
|
||
this.description = options.description || "";
|
||
this.icon = options.icon || null;
|
||
this.category = options.category || "默认";
|
||
|
||
// 笔刷实例
|
||
this.brush = null;
|
||
}
|
||
|
||
/**
|
||
* 创建笔刷实例(必须由子类实现)
|
||
* @returns {Object} fabric笔刷实例
|
||
*/
|
||
create() {
|
||
throw new Error("必须由子类实现create方法");
|
||
}
|
||
|
||
/**
|
||
* 配置笔刷(必须由子类实现)
|
||
* @param {Object} brush fabric笔刷实例
|
||
* @param {Object} options 配置选项
|
||
*/
|
||
configure(brush, options) {
|
||
throw new Error("必须由子类实现configure方法");
|
||
}
|
||
|
||
/**
|
||
* 获取笔刷的元数据
|
||
* @returns {Object} 笔刷元数据
|
||
*/
|
||
getMetadata() {
|
||
return {
|
||
id: this.id,
|
||
name: this.name,
|
||
description: this.description,
|
||
icon: this.icon,
|
||
category: this.category,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 获取笔刷预览
|
||
* @returns {String|null} 预览图URL或null
|
||
*/
|
||
getPreview() {
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 获取笔刷可配置属性
|
||
* 这个方法返回一个对象数组,每个对象描述一个可配置属性
|
||
* 每个属性对象包含:
|
||
* - id: 属性标识符
|
||
* - name: 属性显示名称
|
||
* - type: 属性类型(例如:'slider', 'color', 'checkbox', 'select')
|
||
* - defaultValue: 默认值
|
||
* - min/max/step: 对于slider类型的限制值
|
||
* - options: 对于select类型的选项
|
||
* - description: 属性描述
|
||
* - category: 属性分类
|
||
* - order: 显示顺序(越小越靠前)
|
||
* - visibleWhen: 函数或对象,定义何时显示该属性
|
||
* - dynamicOptions: 函数,返回动态的选项列表
|
||
* @returns {Array} 可配置属性描述数组
|
||
*/
|
||
getConfigurableProperties() {
|
||
// 返回基础属性,所有笔刷都有这些属性
|
||
return [
|
||
{
|
||
id: "size",
|
||
name: "笔刷大小",
|
||
type: "slider",
|
||
defaultValue: 5,
|
||
min: 0.5,
|
||
max: 100,
|
||
step: 0.5,
|
||
description: "笔刷的大小(像素)",
|
||
category: "基本",
|
||
order: 10,
|
||
},
|
||
{
|
||
id: "color",
|
||
name: "笔刷颜色",
|
||
type: "color",
|
||
defaultValue: "#000000",
|
||
description: "笔刷的颜色",
|
||
category: "基本",
|
||
order: 20,
|
||
},
|
||
{
|
||
id: "opacity",
|
||
name: "不透明度",
|
||
type: "slider",
|
||
defaultValue: 1,
|
||
min: 0.05,
|
||
max: 1,
|
||
step: 0.01,
|
||
description: "笔刷的不透明度",
|
||
category: "基本",
|
||
order: 30,
|
||
},
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 合并特有属性与基本属性
|
||
* 子类应该调用此方法来合并自身特有属性与基类提供的基本属性
|
||
* @param {Array} specificProperties 特有属性数组
|
||
* @returns {Array} 合并后的属性数组
|
||
*/
|
||
mergeWithBaseProperties(specificProperties) {
|
||
const baseProperties = super.getConfigurableProperties();
|
||
|
||
// 过滤掉同名属性(子类优先)
|
||
const basePropsFiltered = baseProperties.filter(
|
||
(baseProp) =>
|
||
!specificProperties.some(
|
||
(specificProp) => specificProp.id === baseProp.id
|
||
)
|
||
);
|
||
|
||
return [...basePropsFiltered, ...specificProperties];
|
||
}
|
||
|
||
/**
|
||
* 更新笔刷属性
|
||
* @param {String} propId 属性ID
|
||
* @param {any} value 属性值
|
||
* @returns {Boolean} 是否更新成功
|
||
*/
|
||
updateProperty(propId, value) {
|
||
// 基础实现,可以被子类覆盖以处理特殊属性
|
||
if (propId === "size") {
|
||
if (this.brush) {
|
||
this.brush.width = value;
|
||
return true;
|
||
}
|
||
} else if (propId === "color") {
|
||
if (this.brush) {
|
||
this.brush.color = value;
|
||
return true;
|
||
}
|
||
} else if (propId === "opacity") {
|
||
if (this.brush) {
|
||
this.brush.opacity = value;
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 检查属性是否可见
|
||
* @param {Object} property 属性对象
|
||
* @param {Object} currentValues 当前所有属性的值
|
||
* @returns {Boolean} 是否可见
|
||
*/
|
||
isPropertyVisible(property, currentValues) {
|
||
// 如果没有visibleWhen条件,则始终显示
|
||
if (!property.visibleWhen) {
|
||
return true;
|
||
}
|
||
|
||
// 如果visibleWhen是函数,则调用函数判断
|
||
if (typeof property.visibleWhen === "function") {
|
||
return property.visibleWhen(currentValues);
|
||
}
|
||
|
||
// 如果visibleWhen是对象,检查条件是否满足
|
||
if (typeof property.visibleWhen === "object") {
|
||
for (const [key, value] of Object.entries(property.visibleWhen)) {
|
||
if (currentValues[key] !== value) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 获取动态选项
|
||
* @param {Object} property 属性对象
|
||
* @param {Object} currentValues 当前所有属性的值
|
||
* @returns {Array} 选项数组
|
||
*/
|
||
getDynamicOptions(property, currentValues) {
|
||
if (
|
||
property.dynamicOptions &&
|
||
typeof property.dynamicOptions === "function"
|
||
) {
|
||
return property.dynamicOptions(currentValues);
|
||
}
|
||
return property.options || [];
|
||
}
|
||
|
||
/**
|
||
* 生命周期方法:笔刷被选中
|
||
*/
|
||
onSelected() {
|
||
// 可由子类覆盖
|
||
}
|
||
|
||
/**
|
||
* 生命周期方法:笔刷被取消选中
|
||
*/
|
||
onDeselected() {
|
||
// 可由子类覆盖
|
||
}
|
||
|
||
/**
|
||
* 销毁笔刷实例并清理资源
|
||
*/
|
||
destroy() {
|
||
this.brush = null;
|
||
}
|
||
}
|