From e5fc07e5e36a6f81666bc2b1f25ee905123634d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Tue, 11 Nov 2025 17:35:00 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E7=B2=98=E8=B4=B4=E5=A4=96=E9=83=A8=E6=96=87=E5=AD=97=E5=92=8C?= =?UTF-8?q?=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CanvasEditor/commands/TextCommands.js | 7 ++-- .../components/TextEditorPanel.vue | 3 ++ src/component/Canvas/CanvasEditor/index.vue | 17 ++++++++-- .../CanvasEditor/managers/LayerManager.js | 10 ++++-- .../CanvasEditor/managers/ToolManager.js | 22 ++++++++++-- .../managers/events/KeyboardManager.js | 34 +++++++++++++++++-- src/component/Canvas/canvasExample.vue | 8 ----- src/lang/cn.ts | 1 + src/lang/en.ts | 1 + 9 files changed, 84 insertions(+), 19 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/commands/TextCommands.js b/src/component/Canvas/CanvasEditor/commands/TextCommands.js index c9c464ef..8e6c80c0 100644 --- a/src/component/Canvas/CanvasEditor/commands/TextCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/TextCommands.js @@ -321,6 +321,7 @@ export class CreateTextCommand extends Command { this.x = options.x; this.y = options.y; this.textOptions = options.textOptions || {}; + this.options = options; // 生成唯一ID this.textId = options?.textId || generateId("text_"); this.layerId = options?.layerId || generateId("text_layer_"); @@ -331,7 +332,7 @@ export class CreateTextCommand extends Command { // 默认文本属性 this.defaultOptions = { - text: t('Canvas.DoubleClickText'), + text: options.text || t('Canvas.DoubleClickText'), fontFamily: "Arial", fontSize: 24, fontWeight: "normal", @@ -373,8 +374,8 @@ export class CreateTextCommand extends Command { originY: "center", }); - // 创建文本图层 - const layerName = this.textOptions.layerName || "文本图层"; + // 创建文本图层 取15 + const layerName = this.options.text?.substring(0, 25) || t('Canvas.TextLayer'); const layer = createLayer({ id: this.layerId, name: layerName, diff --git a/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue b/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue index 09637373..33a0c17c 100644 --- a/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/TextEditorPanel.vue @@ -619,10 +619,13 @@ export default { onMounted(() => { // 监听显示文本编辑面板事件 document.addEventListener("showTextEditor", showEditor); + document.addEventListener("hideTextEditor", close); + }); onUnmounted(() => { document.removeEventListener("showTextEditor", showEditor); + document.removeEventListener("hideTextEditor", close); }); // 返回所有需要在模板中使用的数据和方法 diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index c1ca84c9..33ccd3f1 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -303,6 +303,19 @@ onMounted(async () => { commandManager, layerManager, toolManager, + pasteText: (text) => { + // console.log("粘贴的文本:", text); + handleAddText(text); + }, + pasteImage: (file) => { + // console.log("粘贴的图片:", file); + uploadImageAndCreateLayer({ + file, + layerManager, + toolManager, + canvas: canvasManager.canvas, + }); + }, }); // 绑定快捷键事件 @@ -786,11 +799,11 @@ function triggerLibrary() { } } -function handleAddText() { +function handleAddText(text) { if (toolManager && canvasManager && canvasManager.canvas) { // 在画布中央创建文本 const canvasCenter = canvasManager.canvas.getCenter(); - toolManager.createText(canvasCenter.left, canvasCenter.top); + toolManager.createText(canvasCenter.left, canvasCenter.top, text); } } diff --git a/src/component/Canvas/CanvasEditor/managers/LayerManager.js b/src/component/Canvas/CanvasEditor/managers/LayerManager.js index 9e524e91..c885c2ac 100644 --- a/src/component/Canvas/CanvasEditor/managers/LayerManager.js +++ b/src/component/Canvas/CanvasEditor/managers/LayerManager.js @@ -1818,7 +1818,12 @@ export class LayerManager { // 存储到剪贴板 this.clipboardData = layerCopy; - + const input = document.createElement("input"); + input.value = "aida_copy_canvas_layer: " + layer.name; + document.body.appendChild(input); + input.select(); + document.execCommand("copy"); + document.body.removeChild(input); console.log(`已复制图层:${layer.name}`); return this.clipboardData; @@ -1917,7 +1922,8 @@ export class LayerManager { * 粘贴图层 * @returns {string} 新创建的图层ID */ - async pasteLayer() { + async pasteLayer(event) { + console.log("剪贴板数据:", this.clipboardData,event); if (!this.clipboardData) { console.error("剪贴板中没有图层数据"); return null; diff --git a/src/component/Canvas/CanvasEditor/managers/ToolManager.js b/src/component/Canvas/CanvasEditor/managers/ToolManager.js index 0a4d0f25..263e0260 100644 --- a/src/component/Canvas/CanvasEditor/managers/ToolManager.js +++ b/src/component/Canvas/CanvasEditor/managers/ToolManager.js @@ -357,6 +357,9 @@ export class ToolManager { this.canvasManager?.layerManager?.updateLayersObjectsInteractivity?.(); this.canvas?.renderAll(); + // 隐藏文本编辑面板 + this.hideTextEditor(); + // 如果切换到非画笔工具,禁用笔刷指示器 if (!this._shouldShowBrushIndicator(toolId)) { this._disableBrushIndicator(); @@ -1014,9 +1017,10 @@ export class ToolManager { * 创建文字对象并添加到画布 * @param {Number} x 文本位置x坐标 * @param {Number} y 文本位置y坐标 - * @param {Object} options 文本选项 + * @param {String} [text] 文本内容 + * @param {Object} [options] 文本选项 */ - async createText(x, y, options = {}) { + async createText(x, y, text, options = {}) { // 使用命令模式创建文本 if (!this.canvas || !this.layerManager) return null; if (this.commandManager) { @@ -1025,6 +1029,7 @@ export class ToolManager { layerManager: this.layerManager, x, y, + text, textOptions: options, }); // 执行命令 @@ -1179,6 +1184,19 @@ export class ToolManager { }) ); } + /** + * 隐藏文本编辑面板 + */ + hideTextEditor() { + // 这个方法将在TextEditorPanel组件实现后调用 + console.log("隐藏文本编辑面板"); + // 将发出一个事件,让Vue组件捕获并隐藏编辑面板 + document.dispatchEvent( + new CustomEvent("hideTextEditor", { + detail: {}, + }) + ); + } /** * 清理资源 diff --git a/src/component/Canvas/CanvasEditor/managers/events/KeyboardManager.js b/src/component/Canvas/CanvasEditor/managers/events/KeyboardManager.js index b2fd6364..d1298dbf 100644 --- a/src/component/Canvas/CanvasEditor/managers/events/KeyboardManager.js +++ b/src/component/Canvas/CanvasEditor/managers/events/KeyboardManager.js @@ -10,6 +10,8 @@ export class KeyboardManager { * @param {Object} options.toolManager 工具管理器实例 * @param {Object} options.commandManager 命令管理器实例 * @param {Object} options.layerManager 图层管理器实例 + * @param {Function} options.pasteText 粘贴文本回调函数 + * @param {Function} options.pasteImage 粘贴图片回调函数 * @param {HTMLElement} options.container 容器元素,用于添加事件监听 */ constructor(options = {}) { @@ -17,6 +19,8 @@ export class KeyboardManager { this.commandManager = options.commandManager; this.layerManager = options.layerManager; this.container = options.container || document; + this.pasteText = options.pasteText || (() => {}); + this.pasteImage = options.pasteImage || (() => {}); // 检测平台类型 this.platform = this.detectPlatform(); @@ -63,6 +67,7 @@ export class KeyboardManager { // 事件绑定 this._handleKeyDown = this.handleKeyDown.bind(this); this._handleKeyUp = this.handleKeyUp.bind(this); + this._handlePaste = this.handlePaste.bind(this); this._handleTouchStart = this.handleTouchStart.bind(this); this._handleTouchMove = this.handleTouchMove.bind(this); this._handleTouchEnd = this.handleTouchEnd.bind(this); @@ -112,7 +117,7 @@ export class KeyboardManager { // 复制/粘贴 [`${cmdOrCtrl}+c`]: { action: "copy", description: "复制" }, - [`${cmdOrCtrl}+v`]: { action: "paste", description: "粘贴" }, + [`${cmdOrCtrl}+v`]: { action: "paste", description: "粘贴", noStop: true }, [`${cmdOrCtrl}+x`]: { action: "cut", description: "剪切" }, // 删除 @@ -196,6 +201,28 @@ export class KeyboardManager { }; } + /** + * 处理粘贴事件 + * @param {ClipboardEvent} event 粘贴事件 + */ + handlePaste(event) { + event.preventDefault(); // 阻止默认粘贴行为 + const text = event.clipboardData?.getData("text/plain") || ""; + if(/^aida_copy_canvas_layer/.test(text)) return; + const items = event.clipboardData?.items || []; + console.log(this); + for (const item of items) { + if (item.type.indexOf("text/plain") !== -1) { + item.getAsString((text) => { + this.pasteText(text); + }); + } else if (item.type.indexOf("image") !== -1) { + const blob = item.getAsFile(); + this.pasteImage(blob); + } + } + } + /** * 初始化并开始监听键盘事件 */ @@ -203,6 +230,7 @@ export class KeyboardManager { // 添加键盘事件监听 this.container.addEventListener("keydown", this._handleKeyDown); this.container.addEventListener("keyup", this._handleKeyUp); + this.container.addEventListener("paste", this._handlePaste); // 如果是触摸设备,添加触摸事件监听 if (this.isTouchDevice) { @@ -222,6 +250,7 @@ export class KeyboardManager { // 移除键盘事件监听 this.container.removeEventListener("keydown", this._handleKeyDown); this.container.removeEventListener("keyup", this._handleKeyUp); + this.container.removeEventListener("paste", this._handlePaste); // 如果是触摸设备,移除触摸事件监听 if (this.isTouchDevice) { @@ -251,7 +280,7 @@ export class KeyboardManager { const shortcut = this.shortcuts[shortcutKey]; if (shortcut) { // 阻止默认行为,例如浏览器的保存对话框等 - if (shortcutKey.includes(`${this.modifierKeys.cmdOrCtrl}+`)) { + if (shortcutKey.includes(`${this.modifierKeys.cmdOrCtrl}+`) && !shortcut.noStop) { event.preventDefault(); } @@ -701,6 +730,7 @@ export class KeyboardManager { // 移除事件监听 this.container.removeEventListener("keydown", this._handleKeyDown); this.container.removeEventListener("keyup", this._handleKeyUp); + this.container.removeEventListener("paste", this._handlePaste); // 如果有触摸事件,也移除它们 if (this.isTouchDevice) { diff --git a/src/component/Canvas/canvasExample.vue b/src/component/Canvas/canvasExample.vue index e0b82da9..c32ee911 100644 --- a/src/component/Canvas/canvasExample.vue +++ b/src/component/Canvas/canvasExample.vue @@ -278,14 +278,6 @@ const isShowLeft = ref(true);
更换底图
-
- -
保存画布
-
-
- -
读取画布
-
导出JSON
diff --git a/src/lang/cn.ts b/src/lang/cn.ts index ba944cda..3559564a 100644 --- a/src/lang/cn.ts +++ b/src/lang/cn.ts @@ -1367,6 +1367,7 @@ export default { liquefactionEnvironment: '准备液化环境', liquefactionEnvironmentLoading: '正在准备液化环境,请稍候...', LiqueficationFailed: '液化工具启动失败', + TextLayer: '文本图层', DoubleClickText: '双击编辑文本', LiquidationcuoError: '未选择有效图像或图层不适合液化操作', ErrorMessage: '错误提示', diff --git a/src/lang/en.ts b/src/lang/en.ts index 3dea1eea..627cadab 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -1409,6 +1409,7 @@ export default { liquefactionEnvironmentLoading: 'The liquefaction environment is being prepared. Please wait a moment...', LiqueficationFailed: 'Liquefication tool failed to start.', + TextLayer: 'Text Layer', DoubleClickText: 'Double-click to edit the text', LiquidationError: 'No valid image selected or the layer does not fit the liquefaction operation.', From 29d835aeb3c99a3e8c50dd836612d83f821f3b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Wed, 12 Nov 2025 09:47:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E9=80=89?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=9B=BE=E5=B1=82=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Canvas/CanvasEditor/commands/LayerCommands.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js index 692b16ea..67cb05e4 100644 --- a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js +++ b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js @@ -528,6 +528,7 @@ export class RemoveLayerCommand extends Command { this.layerIndex = this.layers.value.findIndex( (layer) => layer.id === this.layerId ); + this.removedLayer = this.layers.value[this.layerIndex]; this.isActiveLayer = this.layerId === this.activeLayerId.value; @@ -593,6 +594,9 @@ export class RemoveLayerCommand extends Command { } }); + this.layerIndex = this.layers.value.findIndex( + (layer) => layer.id === this.layerId + ); // 从图层列表中删除 this.layers.value.splice(this.layerIndex, 1);