From 6eda04a81eb0ef9be2f3b03a89927ca7295d95ee 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, 13 Jan 2026 14:41:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B9=B3=E9=93=BA=E5=85=83=E7=B4=A0ui=E6=9B=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/CPart.svg | 68 ++ src/assets/images/icon/xyz.png | Bin 0 -> 3801 bytes .../components/PartSelectorPanel.vue | 855 ++++++++++++++++++ .../SelectMenuPanel/RepeatSetting.vue | 59 +- .../components/SelectMenuPanel/index.vue | 2 +- .../CanvasEditor/components/ToolsSidebar.vue | 13 + .../components/tools/AngleTool.vue | 60 +- .../CanvasEditor/components/tools/MyInput.vue | 67 ++ .../components/tools/OffsetTool.vue | 285 +++--- .../CanvasEditor/components/tools/Slider.vue | 36 +- src/component/Canvas/CanvasEditor/index.vue | 13 + .../CanvasEditor/managers/ToolManager.js | 78 +- .../Canvas/CanvasEditor/utils/helper.js | 89 ++ .../Canvas/CanvasEditor/utils/layerHelper.js | 7 + src/component/Canvas/canvasExample.vue | 2 +- src/component/Canvas/test.vue | 139 ++- src/lang/cn.ts | 1 + src/lang/en.ts | 3 +- 18 files changed, 1544 insertions(+), 233 deletions(-) create mode 100644 src/assets/icons/CPart.svg create mode 100644 src/assets/images/icon/xyz.png create mode 100644 src/component/Canvas/CanvasEditor/components/PartSelectorPanel.vue create mode 100644 src/component/Canvas/CanvasEditor/components/tools/MyInput.vue diff --git a/src/assets/icons/CPart.svg b/src/assets/icons/CPart.svg new file mode 100644 index 00000000..931b5358 --- /dev/null +++ b/src/assets/icons/CPart.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/icon/xyz.png b/src/assets/images/icon/xyz.png new file mode 100644 index 0000000000000000000000000000000000000000..a09a06d8c8e5ec1b30fdb80524f9d3e5e88a0669 GIT binary patch literal 3801 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 + + + + + + + {{ t("Canvas.GarmentPartSelector") }} + + + + + + + {{ $t("Canvas.freehandSketching") }} + + + + {{ $t("Canvas.rectangle") }} + + + + {{ $t("Canvas.ellipse") }} + + + + + + + + + + + {{ $t("Canvas.creation") }} + + + + {{ $t("Canvas.CreateAndCopy") }} + + + + {{ $t("Canvas.TheClearlySelectedContent") }} + + + + + + + + + + + {{ $t("羽化") }} + × + + + + + {{ featherAmount }}px + + + + {{ $t("Canvas.close") }} + + + {{ $t("Canvas.confirmEdit") }} + + + + + + + + + + + {{ $t("Canvas.SelectFillColor") }} + + × + + + + + + + {{ $t("Canvas.close") }} + + + {{ $t("Canvas.confirmEdit") }} + + + + + + + + + + + + diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue index dfd96563..e8ad87ca 100644 --- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue +++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue @@ -1,14 +1,15 @@ + {{ t("Canvas.repeatSetting") }} {{ t("Canvas.angle") }} emit('inputFillAngle', e)" @change="(e) => emit('changeFillAngle', e)" + style-type="2" /> - {{ t("Canvas.scale") }} - Gap X emit('changeFill_Gap', e, gapY)" /> - Gap Y emit('changeFill_Gap', gapX, e)" /> - {{ t("Canvas.offset") }} emit('inputFillOffset', e)" @change="(e) => emit('changeFillOffset', e)" + :show-dish="false" + /> + + + emit('inputFillOffset', e)" + @change="(e) => emit('changeFillOffset', e)" + :show-input="false" /> @@ -88,6 +96,12 @@ }); const gapX = computed(() => props.object.fill_?.gapX || 0); const gapY = computed(() => props.object.fill_?.gapY || 0); + const offsetX = computed( + () => (props.object.fill?.offsetX / props.object.width) * 100 + ); + const offsetY = computed( + () => (props.object.fill?.offsetY / props.object.height) * 100 + ); const emit = defineEmits([ "inputFillAngle", "changeFillAngle", @@ -111,23 +125,36 @@ diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue index 83a4ff36..f7ab1ecc 100644 --- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue +++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue @@ -132,7 +132,6 @@ v-if="v.type === 'rect'" trigger="click" destroyTooltipOnHide - :title="t('Canvas.repeatSetting')" > .list { display: flex; + > div { display: flex; align-items: center; diff --git a/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue b/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue index 583a4cf9..b1f29cb0 100644 --- a/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue +++ b/src/component/Canvas/CanvasEditor/components/ToolsSidebar.vue @@ -166,6 +166,19 @@ const normalToolsList = ref([ icon: { name: "CFont", size: "20" }, class: "text-btn", }, + { + id: OperationType.PART, + title: t("Canvas.GarmentPartSelector"), + action: () => selectTool(OperationType.PART), + icon: { name: "CPart", size: "28" }, + class: "part-btn", + activeList: [ + OperationType.PART, + OperationType.PART_RECTANGLE, + OperationType.PART_BRUSH, + OperationType.PART_ERASER, + ], + }, { id: "help", title: t("Canvas.help"), diff --git a/src/component/Canvas/CanvasEditor/components/tools/AngleTool.vue b/src/component/Canvas/CanvasEditor/components/tools/AngleTool.vue index 5fa56c70..d924525d 100644 --- a/src/component/Canvas/CanvasEditor/components/tools/AngleTool.vue +++ b/src/component/Canvas/CanvasEditor/components/tools/AngleTool.vue @@ -1,32 +1,53 @@ - - - + + + + + - - - - + + + + + + + diff --git a/src/component/Canvas/CanvasEditor/components/tools/OffsetTool.vue b/src/component/Canvas/CanvasEditor/components/tools/OffsetTool.vue index 00288da3..822c05fb 100644 --- a/src/component/Canvas/CanvasEditor/components/tools/OffsetTool.vue +++ b/src/component/Canvas/CanvasEditor/components/tools/OffsetTool.vue @@ -1,84 +1,100 @@ + + + + - + + + X: {{ left }}% + Y: {{ top }}% + + + - - - x:{{ tofix(data.left) }}% y:{{ tofix(data.top) }}%