接入画布

This commit is contained in:
X1627315083
2025-06-09 10:25:54 +08:00
parent 87a08f5f8f
commit c266967f16
157 changed files with 43833 additions and 1571 deletions

View File

@@ -0,0 +1,582 @@
import { reactive, readonly } from "vue";
import texturePresetManager from "../managers/brushes/TexturePresetManager";
/**
* 笔刷数据存储
* 使用Vue 3的响应式API实现笔刷相关数据的全局状态管理
*/
const state = reactive({
// 笔刷基础属性
size: 5, // 笔刷大小
color: "#000000", // 笔刷颜色
opacity: 1, // 笔刷透明度
type: "pencil", // 当前笔刷类型
// 笔刷材质相关
textureScale: 1, // 材质缩放
textureEnabled: false, // 是否启用材质
texturePath: "", // 材质图片路径
textureOpacity: 1, // 材质透明度
textureRepeat: "repeat", // 材质重复模式
textureAngle: 0, // 材质旋转角度
selectedTextureId: null, // 当前选中的材质ID
// 可用笔刷类型列表 (由BrushManager初始化)
availableBrushes: [],
// 自定义笔刷列表
customBrushes: [],
// 笔刷预设
presets: [
{ name: "细线", size: 2, opacity: 1, color: "#000000", type: "pencil" },
{ name: "中粗", size: 5, opacity: 1, color: "#000000", type: "pencil" },
{ name: "粗线", size: 10, opacity: 1, color: "#000000", type: "pencil" },
{ name: "水彩", size: 15, opacity: 0.7, color: "#3366ff", type: "marker" },
{ name: "喷枪", size: 20, opacity: 0.5, color: "#ff6633", type: "spray" },
],
// 材质预设
texturePresets: [
{
name: "默认纹理",
textureId: "preset_texture_0",
scale: 1,
opacity: 1,
repeat: "repeat",
angle: 0,
},
{
name: "细纹理",
textureId: "preset_texture_1",
scale: 0.5,
opacity: 0.8,
repeat: "repeat",
angle: 0,
},
{
name: "粗纹理",
textureId: "preset_texture_2",
scale: 2,
opacity: 1,
repeat: "repeat",
angle: 45,
},
{
name: "水彩纹理",
textureId: "preset_texture_5",
scale: 1.5,
opacity: 0.6,
repeat: "no-repeat",
angle: 0,
},
],
// 最近使用的颜色
recentColors: ["#000000", "#ffffff", "#ff0000", "#00ff00", "#0000ff"],
// 最近使用的材质
recentTextures: [],
// 当前笔刷可配置属性(由当前选中笔刷动态设置)
currentBrushProperties: [],
// 当前笔刷实例的引用
currentBrushInstance: null,
// 笔刷属性值的映射存储可由UI修改的属性值
propertyValues: {},
});
// Actions - 修改状态的函数
const actions = {
setBrushSize(size) {
state.size = Math.max(0.5, Math.min(100, size));
},
setBrushColor(color) {
state.color = color;
// 添加到最近使用的颜色
if (!state.recentColors.includes(color)) {
state.recentColors.unshift(color);
if (state.recentColors.length > 10) {
state.recentColors.pop();
}
}
},
setBrushOpacity(opacity) {
state.opacity = Math.max(0.05, Math.min(1, opacity));
},
setBrushType(type) {
if (state.availableBrushes.some((brush) => brush.id === type)) {
state.type = type;
}
},
setTextureScale(scale) {
state.textureScale = Math.max(0.1, Math.min(10, scale));
},
setTextureEnabled(enabled) {
state.textureEnabled = enabled;
},
setTexturePath(path) {
state.texturePath = path;
},
setAvailableBrushes(brushes) {
state.availableBrushes = brushes;
},
addCustomBrush(brush) {
if (!brush.id) {
brush.id = `custom_${Date.now()}`;
}
state.customBrushes.push(brush);
return brush.id;
},
removeCustomBrush(brushId) {
const index = state.customBrushes.findIndex((b) => b.id === brushId);
if (index !== -1) {
state.customBrushes.splice(index, 1);
return true;
}
return false;
},
// 应用预设
applyPreset(presetIndex) {
const preset = state.presets[presetIndex];
if (preset) {
state.size = preset.size;
state.opacity = preset.opacity;
state.color = preset.color;
state.type = preset.type;
return true;
}
return false;
},
// 将当前设置保存为新预设
saveCurrentAsPreset(name) {
const newPreset = {
name: name || `预设 ${state.presets.length + 1}`,
size: state.size,
opacity: state.opacity,
color: state.color,
type: state.type,
textureEnabled: state.textureEnabled,
textureScale: state.textureScale,
texturePath: state.texturePath,
};
state.presets.push(newPreset);
return state.presets.length - 1; // 返回新预设的索引
},
/**
* 设置当前笔刷实例
* @param {Object} brushInstance BaseBrush实例
*/
setCurrentBrushInstance(brushInstance) {
state.currentBrushInstance = brushInstance;
// 获取并设置当前笔刷的可配置属性
if (brushInstance && brushInstance.getConfigurableProperties) {
const properties = brushInstance.getConfigurableProperties();
state.currentBrushProperties = properties;
// 初始化属性值
properties.forEach((prop) => {
// 如果是基础属性,使用已有值
if (prop.id === "size") {
state.propertyValues[prop.id] = state.size;
} else if (prop.id === "color") {
state.propertyValues[prop.id] = state.color;
} else if (prop.id === "opacity") {
state.propertyValues[prop.id] = state.opacity;
} else {
// 对于特殊属性,使用默认值
state.propertyValues[prop.id] = prop.defaultValue;
}
});
} else {
// 如果没有实例或方法,清空属性列表
state.currentBrushProperties = [];
}
},
/**
* 更新笔刷属性值
* @param {String} propId 属性ID
* @param {any} value 属性值
*/
updatePropertyValue(propId, value) {
// 更新Store中的值
state.propertyValues[propId] = value;
// 同步更新基础属性
if (propId === "size") {
state.size = value;
} else if (propId === "color") {
state.color = value;
} else if (propId === "opacity") {
state.opacity = value;
}
// 如果有当前笔刷实例且有更新方法,则调用
if (
state.currentBrushInstance &&
state.currentBrushInstance.updateProperty
) {
state.currentBrushInstance.updateProperty(propId, value);
}
},
/**
* 获取属性值
* @param {String} propId 属性ID
* @param {any} defaultValue 默认值
* @returns {any} 属性值
*/
getPropertyValue(propId, defaultValue) {
// 检查属性值是否存在
if (state.propertyValues.hasOwnProperty(propId)) {
return state.propertyValues[propId];
}
// 对于基础属性返回store中的值
if (propId === "size") {
return state.size;
} else if (propId === "color") {
return state.color;
} else if (propId === "opacity") {
return state.opacity;
}
// 否则返回默认值
return defaultValue;
},
/**
* 按分类获取当前笔刷可配置属性
* @returns {Object} 按分类分组的属性对象
*/
getPropertiesByCategory() {
const result = {};
state.currentBrushProperties.forEach((prop) => {
const category = prop.category || "默认";
if (!result[category]) {
result[category] = [];
}
result[category].push({
...prop,
value: this.getPropertyValue(prop.id, prop.defaultValue),
});
});
// 按order排序每个分类中的属性
Object.keys(result).forEach((category) => {
result[category].sort((a, b) => (a.order || 0) - (b.order || 0));
});
return result;
},
/**
* 材质相关方法
*/
setTextureOpacity(opacity) {
state.textureOpacity = Math.max(0, Math.min(1, opacity));
},
setTextureRepeat(repeat) {
const validModes = ["repeat", "repeat-x", "repeat-y", "no-repeat"];
if (validModes.includes(repeat)) {
state.textureRepeat = repeat;
}
},
setTextureAngle(angle) {
state.textureAngle = angle % 360;
},
setSelectedTextureId(textureId) {
state.selectedTextureId = textureId;
// 添加到最近使用的材质
if (textureId && !state.recentTextures.includes(textureId)) {
state.recentTextures.unshift(textureId);
if (state.recentTextures.length > 8) {
state.recentTextures.pop();
}
}
},
/**
* 应用材质预设
* @param {Number} presetIndex 预设索引
* @returns {Boolean} 是否应用成功
*/
applyTexturePreset(presetIndex) {
const preset = state.texturePresets[presetIndex];
if (preset) {
state.selectedTextureId = preset.textureId;
state.textureScale = preset.scale;
state.textureOpacity = preset.opacity;
state.textureRepeat = preset.repeat;
state.textureAngle = preset.angle;
// 添加到最近使用
this.setSelectedTextureId(preset.textureId);
return true;
}
return false;
},
/**
* 将当前材质设置保存为新预设
* @param {String} name 预设名称
* @returns {Number} 新预设的索引
*/
saveCurrentTextureAsPreset(name) {
const newPreset = {
name: name || `材质预设 ${state.texturePresets.length + 1}`,
textureId: state.selectedTextureId,
scale: state.textureScale,
opacity: state.textureOpacity,
repeat: state.textureRepeat,
angle: state.textureAngle,
};
state.texturePresets.push(newPreset);
return state.texturePresets.length - 1;
},
/**
* 删除材质预设
* @param {Number} presetIndex 预设索引
* @returns {Boolean} 是否删除成功
*/
removeTexturePreset(presetIndex) {
if (presetIndex >= 0 && presetIndex < state.texturePresets.length) {
state.texturePresets.splice(presetIndex, 1);
return true;
}
return false;
},
/**
* 获取所有可用材质(预设+自定义)
* @returns {Array} 材质列表
*/
getAllTextures() {
return texturePresetManager.getAllTextures();
},
/**
* 根据ID获取材质信息
* @param {String} textureId 材质ID
* @returns {Object|null} 材质对象
*/
getTextureById(textureId) {
return texturePresetManager.getTextureById(textureId);
},
/**
* 按分类获取材质
* @param {String} category 分类名称
* @returns {Array} 材质列表
*/
getTexturesByCategory(category) {
return texturePresetManager.getTexturesByCategory(category);
},
/**
* 获取材质分类列表
* @returns {Array} 分类名称数组
*/
getTextureCategories() {
return texturePresetManager.getCategories();
},
/**
* 搜索材质
* @param {String} keyword 搜索关键词
* @returns {Array} 匹配的材质列表
*/
searchTextures(keyword) {
return texturePresetManager.searchTextures(keyword);
},
/**
* 添加自定义材质
* @param {Object} textureData 材质数据
* @returns {String} 材质ID
*/
addCustomTexture(textureData) {
const textureId = texturePresetManager.addCustomTexture(textureData);
// 保存到本地存储
texturePresetManager.saveCustomTexturesToStorage();
return textureId;
},
/**
* 删除自定义材质
* @param {String} textureId 材质ID
* @returns {Boolean} 是否删除成功
*/
removeCustomTexture(textureId) {
const success = texturePresetManager.removeCustomTexture(textureId);
if (success) {
// 如果删除的是当前选中的材质,清空选择
if (state.selectedTextureId === textureId) {
state.selectedTextureId = null;
}
// 从最近使用中移除
const recentIndex = state.recentTextures.indexOf(textureId);
if (recentIndex !== -1) {
state.recentTextures.splice(recentIndex, 1);
}
// 保存到本地存储
texturePresetManager.saveCustomTexturesToStorage();
}
return success;
},
/**
* 从文件上传自定义材质
* @param {File} file 图片文件
* @param {String} name 材质名称(可选)
* @returns {Promise<String>} 材质ID
*/
uploadCustomTexture(file, name) {
return new Promise((resolve, reject) => {
// 验证文件
if (!texturePresetManager.validateTextureFile(file)) {
reject(new Error("无效的材质文件"));
return;
}
// 读取文件
const reader = new FileReader();
reader.onload = (e) => {
try {
const textureData = {
name: name || file.name.replace(/\.[^/.]+$/, ""),
path: e.target.result,
preview: e.target.result,
description: `用户上传的材质: ${file.name}`,
};
const textureId = this.addCustomTexture(textureData);
resolve(textureId);
} catch (error) {
reject(error);
}
};
reader.onerror = () => {
reject(new Error("文件读取失败"));
};
reader.readAsDataURL(file);
});
},
/**
* 导出材质预设配置
* @returns {String} JSON格式的配置
*/
exportTexturePresets() {
const config = {
texturePresets: state.texturePresets,
customTextures: texturePresetManager.exportCustomTextures(),
};
return JSON.stringify(config, null, 2);
},
/**
* 导入材质预设配置
* @param {String} configJson JSON格式的配置
* @returns {Boolean} 是否导入成功
*/
importTexturePresets(configJson) {
try {
const config = JSON.parse(configJson);
// 导入材质预设
if (config.texturePresets && Array.isArray(config.texturePresets)) {
state.texturePresets = [
...state.texturePresets,
...config.texturePresets,
];
}
// 导入自定义材质
if (config.customTextures) {
texturePresetManager.importCustomTextures(config.customTextures);
}
return true;
} catch (error) {
console.error("导入材质预设失败:", error);
return false;
}
},
/**
* 初始化材质预设管理器
*/
initializeTexturePresets() {
// 从本地存储加载自定义材质
texturePresetManager.loadCustomTexturesFromStorage();
// 确保预设材质引用的是有效的材质ID
state.texturePresets.forEach((preset, index) => {
const texture = texturePresetManager.getTextureById(preset.textureId);
if (!texture) {
console.warn(
`材质预设 "${preset.name}" 引用的材质 ${preset.textureId} 不存在`
);
// 可以选择使用默认材质替换或删除该预设
if (texturePresetManager.getAllTextures().length > 0) {
preset.textureId = texturePresetManager.getAllTextures()[0].id;
}
}
});
},
};
// 暴露给组件使用的Store对象
export const BrushStore = {
// 只读状态,防止直接修改
state: readonly(state),
// 可调用的Actions
...actions,
// 辅助方法
getRGBAColor() {
// 解析十六进制颜色并添加透明度
const hex = state.color.replace("#", "");
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${state.opacity})`;
},
};