From 8442412a3413490b7cafba73194e6277d6ff0ad7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com>
Date: Mon, 10 Nov 2025 16:19:05 +0800
Subject: [PATCH 1/4] =?UTF-8?q?=E7=94=BB=E5=B8=83=E9=80=89=E5=B7=A5?=
=?UTF-8?q?=E5=85=B7=E6=93=8D=E4=BD=9C=E9=9D=A2=E6=9D=BF=E6=9B=B4=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../components/SelectMenuPanel.vue | 115 +++++++++++-------
src/views/HomeView/history.vue | 2 +-
2 files changed, 72 insertions(+), 45 deletions(-)
diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
index e5396c59..1a6a76cf 100644
--- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
+++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
@@ -22,7 +22,7 @@
v-for="v in activeObjects"
:key="v.id"
>
-
W
@@ -53,7 +53,7 @@
changeAngle(e, v)"
/>
@@ -158,6 +158,9 @@
const getActiveObject = (e) => {
console.log("==========切换激活对象", e);
activeObjects.value = e.selected.map((v) => v);
+ activeObjects.value.forEach((v) => {
+ v.layer = props.layerManager.getLayerById(v.layerId);
+ });
if (activeObjects.value.length === 0) {
close();
} else {
@@ -166,46 +169,11 @@
};
const lastSelectLayerId = inject("lastSelectLayerId");
const layers = inject("layers");
- const changeAngle = (activeObj) => {
- // console.log("=====================", e.target.value);
- // const finalState = TransformCommand.captureTransformState(activeObj);
- // const { xPrime, yPrime } = compute(
- // activeObj.left,
- // activeObj.top,
- // activeObj.width,
- // activeObj.height,
- // activeObj.angle
- // );
- // finalState.left = xPrime;
- // finalState.top = yPrime;
- // const transformCmd = new TransformCommand({
- // canvas: props.canvas,
- // objectId: activeObj.id,
- // initialState: null,
- // finalState,
- // objectType: activeObj.type,
- // name: `变换 ${activeObj.type || "对象"}`,
- // layerManager: props.layerManager,
- // layers: layers,
- // lastSelectLayerId: lastSelectLayerId,
- // });
- // props.layerManager.commandManager.execute(transformCmd, {
- // name: "对象修改",
- // });
- };
-
- const flipObject = (activeObj, type) => {
- const initialState = TransformCommand.captureTransformState(activeObj);
- const finalState = { ...initialState };
- if (type === "h") {
- finalState.flipX = !finalState.flipX;
- } else if (type === "v") {
- finalState.flipY = !finalState.flipY;
- }
+ const transformObject = (activeObj, initialState, finalState) => {
const transformCmd = new TransformCommand({
canvas: props.canvas,
objectId: activeObj.id,
- initialState: initialState,
+ initialState,
finalState,
objectType: activeObj.type,
name: `变换 ${activeObj.type || "对象"}`,
@@ -217,13 +185,72 @@
name: "对象修改",
});
};
- const clickflipHorizontal = (obj) => {
- console.log("水平翻转");
- flipObject(obj, "h");
+
+ /**
+ * 根据左上角坐标计算旋转后的新坐标
+ * @param {number} W - 宽度
+ * @param {number} H - 高度
+ * @param {number} currentX - 当前左上角x坐标
+ * @param {number} currentY - 当前左上角y坐标
+ * @param {number} currentAngleDeg - 当前角度(度)
+ * @param {number} newAngleDeg - 新角度(度)
+ * @returns {Object} 旋转后的左上角坐标 {x, y}
+ */
+ function calculateRotatedTopLeftDeg(
+ W,
+ H,
+ currentX,
+ currentY,
+ currentAngleDeg,
+ newAngleDeg
+ ) {
+ const currentAngle = (currentAngleDeg * Math.PI) / 180;
+ const newAngle = (newAngleDeg * Math.PI) / 180;
+ // 1. 用当前角度计算中心点位置
+ const cosCurrent = Math.cos(currentAngle);
+ const sinCurrent = Math.sin(currentAngle);
+ const Cx = currentX + (W / 2) * cosCurrent - (H / 2) * sinCurrent;
+ const Cy = currentY + (W / 2) * sinCurrent + (H / 2) * cosCurrent;
+
+ // 2. 用新角度计算旋转后的左上角位置
+ const cosNew = Math.cos(newAngle);
+ const sinNew = Math.sin(newAngle);
+ const newX = Cx + (-W / 2) * cosNew - (-H / 2) * sinNew;
+ const newY = Cy + (-W / 2) * sinNew + (-H / 2) * cosNew;
+
+ return { x: newX, y: newY };
+ }
+ // 改变角度
+ const changeAngle = (e, obj) => {
+ const initialState = TransformCommand.captureTransformState(obj);
+ const finalState = { ...initialState };
+ const angle = e.target.value;
+ const { x, y } = calculateRotatedTopLeftDeg(
+ obj.width,
+ obj.height,
+ obj.left,
+ obj.top,
+ obj.angle,
+ angle
+ );
+ finalState.left = x;
+ finalState.top = y;
+ finalState.angle = angle;
+ transformObject(obj, initialState, finalState);
};
+ // 水平翻转
+ const clickflipHorizontal = (obj) => {
+ const initialState = TransformCommand.captureTransformState(obj);
+ const finalState = { ...initialState };
+ finalState.flipX = !finalState.flipX;
+ transformObject(obj, initialState, finalState);
+ };
+ // 垂直翻转
const clickflipVertical = (obj) => {
- console.log("垂直翻转");
- flipObject(obj, "v");
+ const initialState = TransformCommand.captureTransformState(obj);
+ const finalState = { ...initialState };
+ finalState.flipY = !finalState.flipY;
+ transformObject(obj, initialState, finalState);
};
const updateActiveObjects = (arrs, keys) => {
diff --git a/src/views/HomeView/history.vue b/src/views/HomeView/history.vue
index 4b30f338..38a4b3f5 100644
--- a/src/views/HomeView/history.vue
+++ b/src/views/HomeView/history.vue
@@ -771,7 +771,7 @@ export default defineComponent({
padding: 0 1rem;
.operate_item {
- font-size: 1.4rem;
+ // font-size: 1.4rem;
font-family: Roboto;
font-weight: 400;
color: #007ee5;
From 804040d9fd6f9034ea49d57788af193b5066e412 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com>
Date: Mon, 10 Nov 2025 16:59:28 +0800
Subject: [PATCH 2/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9B=BE=E5=B1=82?=
=?UTF-8?q?=E9=80=89=E6=8B=A9=E6=BF=80=E6=B4=BB=E5=AF=B9=E8=B1=A1=E6=96=B9?=
=?UTF-8?q?=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Canvas/CanvasEditor/components/SelectMenuPanel.vue | 5 +++--
src/component/Canvas/CanvasEditor/managers/LayerManager.js | 4 ++++
src/lang/cn.ts | 2 ++
src/lang/en.ts | 2 ++
4 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
index 1a6a76cf..c83ce2fc 100644
--- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
+++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
@@ -58,11 +58,11 @@
-
水平翻转
+
{{ t('Canvas.flipHorizontal') }}
-
垂直翻转
+
{{ t('Canvas.flipVertical') }}
@@ -271,6 +271,7 @@
} else {
arrs.push(e.target);
}
+ console.log(e.target);
updateActiveObjects(arrs, ["angle"]);
};
diff --git a/src/component/Canvas/CanvasEditor/managers/LayerManager.js b/src/component/Canvas/CanvasEditor/managers/LayerManager.js
index c2fe3941..e70a6b70 100644
--- a/src/component/Canvas/CanvasEditor/managers/LayerManager.js
+++ b/src/component/Canvas/CanvasEditor/managers/LayerManager.js
@@ -1219,6 +1219,10 @@ export class LayerManager {
}
// 切换到选择模式
this?.toolManager?.setTool(OperationType.SELECT);
+ if(objects.length === 1) {
+ this.canvas.setActiveObject(objects[0]);
+ return objects[0];
+ }
// 创建一个新的活动选择组
const activeSelection = new fabric.ActiveSelection(objects, {
canvas: this.canvas,
diff --git a/src/lang/cn.ts b/src/lang/cn.ts
index 8cc1cddc..71224767 100644
--- a/src/lang/cn.ts
+++ b/src/lang/cn.ts
@@ -1217,6 +1217,8 @@ export default {
Rough: '粗糙',
Smooth: '平滑',
basic: '基础',
+ flipHorizontal: '水平翻转',
+ flipVertical: '垂直翻转',
//长毛笔
FurSettings: '长毛笔设置',
FurLength: '毛发长度',
diff --git a/src/lang/en.ts b/src/lang/en.ts
index 013326c6..054b3b13 100644
--- a/src/lang/en.ts
+++ b/src/lang/en.ts
@@ -1252,6 +1252,8 @@ export default {
Rough: 'Rough',
Smooth: 'Smooth',
basic: 'Basic',
+ flipHorizontal: 'Horizontal Flip',
+ flipVertical: 'Vertical Flip',
//长毛笔
FurSettings: 'FurSettings',
FurLength: 'Fur Length',
From 4365b810dbf8810fb48dbd90f0c1d28490a5c2d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com>
Date: Mon, 10 Nov 2025 17:07:05 +0800
Subject: [PATCH 3/4] fix
---
.../Canvas/CanvasEditor/components/SelectMenuPanel.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
index c83ce2fc..917d0816 100644
--- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
+++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
@@ -226,8 +226,8 @@
const finalState = { ...initialState };
const angle = e.target.value;
const { x, y } = calculateRotatedTopLeftDeg(
- obj.width,
- obj.height,
+ obj.width * obj.scaleX,
+ obj.height * obj.scaleY,
obj.left,
obj.top,
obj.angle,
From 5f3c4b5ac9a0bce96c7a94106e89c87879b9f334 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 10:13:59 +0800
Subject: [PATCH 4/4] =?UTF-8?q?=E7=94=BB=E5=B8=83=E5=8F=8C=E5=87=BB?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=86=85=E9=83=A8=E5=9B=BE=E7=89=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../CanvasEditor/commands/LayerCommands.js | 2 +-
.../components/SelectMenuPanel.vue | 42 ++++++++++++-------
.../Canvas/ExistsImageList/index.vue | 11 +++--
src/component/common/SelectImages.vue | 15 +++++--
4 files changed, 49 insertions(+), 21 deletions(-)
diff --git a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js
index 66880184..0380638e 100644
--- a/src/component/Canvas/CanvasEditor/commands/LayerCommands.js
+++ b/src/component/Canvas/CanvasEditor/commands/LayerCommands.js
@@ -2595,7 +2595,7 @@ export class CreateImageLayerCommand extends Command {
// 生成图层名称
const fileName =
- this.layerName || `图片 ${new Date().toLocaleTimeString()}`;
+ this.layerName || `${new Date().toLocaleString()}`;
this.fabricImage.set({
id: this.imageId,
diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
index 917d0816..d02015c8 100644
--- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
+++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel.vue
@@ -58,11 +58,15 @@