From 416a9476efb3caf7174e54c59bf28653f03f6939 Mon Sep 17 00:00:00 2001 From: lzp Date: Wed, 1 Apr 2026 10:10:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=B1=E5=BA=A6=E7=94=BB=E5=B8=83=E7=B2=98?= =?UTF-8?q?=E8=B4=B4=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/details-panel/basic-info.vue | 45 ++++++++++-------- .../Canvas/DepthCanvas/depth-canvas.vue | 12 +---- .../DepthCanvas/manager/LayerManager.ts | 12 +++++ .../manager/events/KeyEventManager.ts | 47 +++++++++++++++---- .../Canvas/DepthCanvas/tools/layerHelper.js | 16 ++++--- 5 files changed, 85 insertions(+), 47 deletions(-) diff --git a/src/components/Canvas/DepthCanvas/components/details-panel/basic-info.vue b/src/components/Canvas/DepthCanvas/components/details-panel/basic-info.vue index 3ad1bba..5265498 100644 --- a/src/components/Canvas/DepthCanvas/components/details-panel/basic-info.vue +++ b/src/components/Canvas/DepthCanvas/components/details-panel/basic-info.vue @@ -85,6 +85,7 @@ import { ref, inject, computed, nextTick, onBeforeUnmount, reactive, watch } from 'vue' import DepthInput from '../tools/depth-input.vue' import DepthSelect from '../tools/depth-select.vue' + import { BlendMode } from '../../tools/layerHelper' import { useI18n } from 'vue-i18n' const { t } = useI18n() const objectManager = inject('objectManager') as any @@ -104,7 +105,7 @@ height: 0, scaleX: 1, scaleY: 1, - globalCompositeOperation: 'source-over' + globalCompositeOperation: BlendMode.NORMAL }) const updateData = async () => { await nextTick() @@ -139,87 +140,91 @@ const layerCompositeOptions = ref([ { - value: 'source-over', + value: BlendMode.NORMAL, label: t('DepthCanvas.compositeNormal'), tip: t('DepthCanvas.compositeNormalTip') }, // 正常 { - value: 'darken', + value: BlendMode.DARKEN, label: t('DepthCanvas.compositeDarken'), tip: t('DepthCanvas.compositeDarkenTip') }, // 变暗 { - value: 'multiply', + value: BlendMode.MULTIPLY, label: t('DepthCanvas.compositeMultiply'), tip: t('DepthCanvas.compositeMultiplyTip') }, // 正片叠底 { - value: 'color-burn', + value: BlendMode.COLOR_BURN, label: t('DepthCanvas.compositeColorBurn'), tip: t('DepthCanvas.compositeColorBurnTip') }, // 颜色加深 { - value: 'lighten', + value: BlendMode.LIGHTEN, label: t('DepthCanvas.compositeLighten'), tip: t('DepthCanvas.compositeLightenTip') - }, // 颜色减淡 + }, // 变亮 { - value: 'screen', + value: BlendMode.SCREEN, label: t('DepthCanvas.compositeScreen'), tip: t('DepthCanvas.compositeScreenTip') }, // 滤色 { - value: 'color-dodge', + value: BlendMode.COLOR_DODGE, label: t('DepthCanvas.compositeColorDodge'), tip: t('DepthCanvas.compositeColorDodgeTip') }, // 颜色减淡 { - value: 'lighter', + value: BlendMode.LIGHTER, label: t('DepthCanvas.compositeLighter'), tip: t('DepthCanvas.compositeLighterTip') - }, // 颜色减淡 + }, // 颜色减淡(添加) { - value: 'overlay', + value: BlendMode.OVERLAY, label: t('DepthCanvas.compositeOverlay'), tip: t('DepthCanvas.compositeOverlayTip') }, // 叠加 { - value: 'soft-light', + value: BlendMode.SOFT_LIGHT, label: t('DepthCanvas.compositeSoftLight'), tip: t('DepthCanvas.compositeSoftLightTip') }, // 柔光 { - value: 'hard-light', + value: BlendMode.HARD_LIGHT, label: t('DepthCanvas.compositeHardLight'), tip: t('DepthCanvas.compositeHardLightTip') }, // 强光 { - value: 'difference', + value: BlendMode.DIFFERENCE, label: t('DepthCanvas.compositeDifference'), tip: t('DepthCanvas.compositeDifferenceTip') }, // 差值 { - value: 'exclusion', + value: BlendMode.EXCLUSION, label: t('DepthCanvas.compositeExclusion'), tip: t('DepthCanvas.compositeExclusionTip') }, // 排除 - { value: 'hue', label: t('DepthCanvas.compositeHue'), tip: t('DepthCanvas.compositeHueTip') }, // 色相 { - value: 'saturation', + value: BlendMode.HUE, + label: t('DepthCanvas.compositeHue'), + tip: t('DepthCanvas.compositeHueTip') + }, // 色相 + { + value: BlendMode.SATURATION, label: t('DepthCanvas.compositeSaturation'), tip: t('DepthCanvas.compositeSaturationTip') }, // 饱和度 { - value: 'color', + value: BlendMode.COLOR, label: t('DepthCanvas.compositeColor'), tip: t('DepthCanvas.compositeColorTip') }, // 颜色 { - value: 'luminosity', + value: BlendMode.LUMINOSITY, label: t('DepthCanvas.compositeLuminosity'), tip: t('DepthCanvas.compositeLuminosityTip') } // 亮度 diff --git a/src/components/Canvas/DepthCanvas/depth-canvas.vue b/src/components/Canvas/DepthCanvas/depth-canvas.vue index 2bbd79e..ac2d630 100644 --- a/src/components/Canvas/DepthCanvas/depth-canvas.vue +++ b/src/components/Canvas/DepthCanvas/depth-canvas.vue @@ -88,7 +88,7 @@ provide('toolManager', toolManager) //键盘事件管理器 - const keyEventManager = new KeyEventManager({ stateManager, onWorkbench }) + const keyEventManager = new KeyEventManager({ stateManager, onWorkbench, layerManager }) stateManager.setManager({ keyEventManager }) provide('keyEventManager', keyEventManager) @@ -163,15 +163,7 @@ input.addEventListener('change', (e: any) => { const file = e.target.files[0] if (!file) return - const reader = new FileReader() - reader.readAsDataURL(file) - reader.onload = () => { - toolManager.setTool(OperationType.SELECT) - const url = reader.result as string - layerManager - .createImageLayer(url, { info: { name: file.name } }, isRecord) - .then((v) => resolve(v)) - } + layerManager.createFileImageLayer(file, isRecord).then((v) => resolve(v)) }) }) } diff --git a/src/components/Canvas/DepthCanvas/manager/LayerManager.ts b/src/components/Canvas/DepthCanvas/manager/LayerManager.ts index 552c9bc..1f00146 100644 --- a/src/components/Canvas/DepthCanvas/manager/LayerManager.ts +++ b/src/components/Canvas/DepthCanvas/manager/LayerManager.ts @@ -419,6 +419,18 @@ export class LayerManager { if (isActive) this.setActiveID(imageObject.info.id) return imageObject } + createFileImageLayer(file: File, isRecord = true) { + return new Promise((resolve) => { + const reader = new FileReader() + reader.readAsDataURL(file) + reader.onload = () => { + this.stateManager.toolManager.setTool(OperationType.SELECT) + const url = reader.result as string + this.createImageLayer(url, { info: { name: file.name } }, isRecord) + .then((v) => resolve(v)) + } + }) + } /** 合并图层 */ async imageMergeToLayer(targetLayer: fabric.Object, fabricImage: fabric.Object) { diff --git a/src/components/Canvas/DepthCanvas/manager/events/KeyEventManager.ts b/src/components/Canvas/DepthCanvas/manager/events/KeyEventManager.ts index a0ea419..ac707ea 100644 --- a/src/components/Canvas/DepthCanvas/manager/events/KeyEventManager.ts +++ b/src/components/Canvas/DepthCanvas/manager/events/KeyEventManager.ts @@ -1,24 +1,37 @@ export class KeyEventManager { stateManager: any + layerManager: any onWorkbench: any constructor(options) { this.stateManager = options.stateManager; + this.layerManager = options.layerManager; this.onWorkbench = options.onWorkbench; this._handleKeyDown = this.handleKeyDown.bind(this) + this._handlePaste = this.handlePaste.bind(this) } onMounted() { } + /** 注册事件 */ + registerEvents() { + document.addEventListener('keydown', this._handleKeyDown) + document.addEventListener("paste", this._handlePaste); + } + /** 删除事件 */ + removeEvents() { + document.removeEventListener('keydown', this._handleKeyDown) + document.removeEventListener("paste", this._handlePaste) + } /** 处理键盘事件 */ _handleKeyDown: any handleKeyDown(event: any) { - const activeID = this.stateManager.layerManager.activeID.value + const activeID = this.layerManager.activeID.value const ctrl = event.ctrlKey ? 'ctrl-' : ""; const shift = event.shiftKey ? 'shift-' : ""; const key = event.key; const reg = new RegExp(`^${ctrl}${shift}${key}$`, 'i') const list = [ - { key: "ctrl-c", handler: () => this.stateManager.layerManager.copyLayerById(activeID) }, - { key: "delete", handler: () => this.stateManager.layerManager.deleteLayerById(activeID) }, + { key: "ctrl-c", handler: () => this.layerManager.copyLayerById(activeID) }, + { key: "delete", handler: () => this.layerManager.deleteLayerById(activeID) }, { key: "ctrl-z", handler: () => this.stateManager.undoState() }, { key: "ctrl-s", handler: () => this.onWorkbench() }, { key: "ctrl-shift-z", handler: () => this.stateManager.redoState() }, @@ -28,14 +41,28 @@ export class KeyEventManager { if (reg.test(v.key)) v.handler(event) }) } - /** 注册事件 */ - registerEvents() { - document.addEventListener('keydown', this._handleKeyDown) - } - /** 删除事件 */ - removeEvents() { - document.removeEventListener('keydown', this._handleKeyDown) + /** 处理粘贴事件 */ + _handlePaste: any + handlePaste(event: any) { + event.preventDefault(); // 阻止默认粘贴行为 + const text = event.clipboardData?.getData("text/plain") || ""; + if (/^aida_copy_canvas_layer/.test(text)) return; + const items = event.clipboardData?.items || []; + for (const item of items) { + if (item.type.indexOf("text/plain") !== -1) { + item.getAsString((text) => { + console.log('粘贴文本', text); + }); + } else if (item.type.indexOf("image") !== -1) { + const file = item.getAsFile(); + this.layerManager.createFileImageLayer(file, false).then(layer => { + const id = layer?.info?.id + this.stateManager.objectManager.setFillRepeat(id) + }) + } + } } + /** 销毁事件管理器 */ dispose() { this.removeEvents() } diff --git a/src/components/Canvas/DepthCanvas/tools/layerHelper.js b/src/components/Canvas/DepthCanvas/tools/layerHelper.js index 86fb6ce..a7fd61e 100644 --- a/src/components/Canvas/DepthCanvas/tools/layerHelper.js +++ b/src/components/Canvas/DepthCanvas/tools/layerHelper.js @@ -29,7 +29,7 @@ export const OperationType = { PAN: "pan", // 拖拽模式 DRAW: "draw", // 绘画模式 ERASER: "eraser", // 橡皮擦模式 - + AISELECT_ADD: "aiSelectAdd",// 智能框选添加模式 AISELECT_REMOVE: "aiSelectRemove",// 智能框选删除模式 AISELECT_DRAW: "aiSelectDraw",// 智能框选绘制模式 @@ -54,21 +54,23 @@ export const OperationTypes = Object.values(OperationType); */ export const BlendMode = { NORMAL: "source-over", // 正常模式 - MULTIPLY: "multiply", // 正片叠底 - SCREEN: "screen", // 滤色 - OVERLAY: "overlay", // 叠加 DARKEN: "darken", // 变暗 - LIGHTEN: "lighten", // 变亮 - COLOR_DODGE: "color-dodge", // 颜色减淡 + MULTIPLY: "multiply", // 正片叠底 COLOR_BURN: "color-burn", // 颜色加深 - HARD_LIGHT: "hard-light", // 强光 + LIGHTEN: "lighten", // 变亮 + SCREEN: "screen", // 滤色 + COLOR_DODGE: "color-dodge", // 颜色减淡 + LIGHTER: "lighter", // 颜色减淡(添加) + OVERLAY: "overlay", // 叠加 SOFT_LIGHT: "soft-light", // 柔光 + HARD_LIGHT: "hard-light", // 强光 DIFFERENCE: "difference", // 差值 EXCLUSION: "exclusion", // 排除 HUE: "hue", // 色相 SATURATION: "saturation", // 饱和度 COLOR: "color", // 颜色 LUMINOSITY: "luminosity", // 明度 + DESTINATION_IN: "destination-in", // 目标内 DESTINATION_OUT: "destination-out", // 目标外 };