feat: 裁剪组裁剪跟随选择组移动

This commit is contained in:
bighuixiang
2025-07-14 01:00:23 +08:00
parent 96e13cb22a
commit 24e9ba8ae5
80 changed files with 2052 additions and 4292 deletions

View File

@@ -1,7 +1,5 @@
import { fabric } from "fabric-with-all";
import initAligningGuidelines, {
initCenteringGuidelines,
} from "../utils/helperLine";
import initAligningGuidelines, { initCenteringGuidelines } from "../utils/helperLine";
import { ThumbnailManager } from "./ThumbnailManager";
import { ExportManager } from "./ExportManager";
import {
@@ -16,11 +14,7 @@ import { CanvasEventManager } from "./events/CanvasEventManager";
import CanvasConfig from "../config/canvasConfig";
import { RedGreenModeManager } from "./RedGreenModeManager";
import { EraserStateManager } from "./EraserStateManager";
import {
deepClone,
generateId,
optimizeCanvasRendering,
} from "../utils/helper";
import { deepClone, generateId, optimizeCanvasRendering } from "../utils/helper";
import { ChangeFixedImageCommand } from "../commands/ObjectLayerCommands";
import { isFunction } from "lodash-es";
import {
@@ -155,10 +149,7 @@ export class CanvasManager {
return false;
};
this.eraserStateManager = new EraserStateManager(
this.canvas,
this.layerManager
);
this.eraserStateManager = new EraserStateManager(this.canvas, this.layerManager);
// 监听擦除开始事件
this.canvas.on("erasing:start", () => {
@@ -179,17 +170,12 @@ export class CanvasManager {
}
// 更新交互性
command &&
(await this.layerManager?.updateLayersObjectsInteractivity?.());
command && (await this.layerManager?.updateLayersObjectsInteractivity?.());
this.thumbnailManager?.generateLayerThumbnail(
this.layerManager?.activeLayerId?.value
);
this.thumbnailManager?.generateLayerThumbnail(this.layerManager?.activeLayerId?.value);
// 固定图层 的擦除也需要重新生成缩略图 要判断 当前固定图层是否锁定
const fixedLayer = this.layers?.value?.find(
(layer) => layer.isFixed && !layer.locked
);
const fixedLayer = this.layers?.value?.find((layer) => layer.isFixed && !layer.locked);
// 如果有固定图层且未锁定,则生成缩略图
fixedLayer &&
this.isFixedErasable &&
@@ -378,9 +364,7 @@ export class CanvasManager {
// 设置固定图层的可擦除状态
layer.locked = flag;
// 更新画布对象的erasable属性
const fabricObject = this.canvas
.getObjects()
.find((obj) => obj.id === layer.id);
const fabricObject = this.canvas.getObjects().find((obj) => obj.id === layer.id);
if (fabricObject) {
fabricObject.erasable = flag;
fabricObject.set("erasable", flag);
@@ -492,9 +476,7 @@ export class CanvasManager {
const deltaY = backgroundObject.top - backgroundOldTop;
// 将相同的偏移量应用到所有其他对象上
const otherObjects = visibleObjects.filter(
(obj) => obj !== backgroundObject
);
const otherObjects = visibleObjects.filter((obj) => obj !== backgroundObject);
otherObjects.forEach((obj) => {
obj.set({
@@ -597,8 +579,7 @@ export class CanvasManager {
if (!backgroundLayerObject) return;
const bgWidth = backgroundLayerObject.width * backgroundLayerObject.scaleX;
const bgHeight =
backgroundLayerObject.height * backgroundLayerObject.scaleY;
const bgHeight = backgroundLayerObject.height * backgroundLayerObject.scaleY;
const left = backgroundLayerObject.left;
const top = backgroundLayerObject.top;
@@ -659,9 +640,7 @@ export class CanvasManager {
return obj.isBackground || obj.id === backgroundLayerId;
});
if (!backgroundLayerByBgLayer) {
console.warn(
"CanvasManager.js = >getBackgroundLayer 方法没有找到背景层"
);
console.warn("CanvasManager.js = >getBackgroundLayer 方法没有找到背景层");
}
return backgroundLayerByBgLayer;
@@ -671,8 +650,7 @@ export class CanvasManager {
* @param {Object} backgroundLayerObject 背景层对象
*/
updateMaskPosition(backgroundLayerObject) {
if (!backgroundLayerObject || !this.maskLayer || !this.canvas.clipPath)
return;
if (!backgroundLayerObject || !this.maskLayer || !this.canvas.clipPath) return;
const left = backgroundLayerObject.left;
const top = backgroundLayerObject.top;
@@ -737,8 +715,7 @@ export class CanvasManager {
...options,
});
command.undoable =
options.undoable !== undefined ? options.undoable : false; // 默认不可撤销 undoable = true 为可撤销
command.undoable = options.undoable !== undefined ? options.undoable : false; // 默认不可撤销 undoable = true 为可撤销
const result = (await command?.execute?.()) || {
success: false,
@@ -785,9 +762,7 @@ export class CanvasManager {
...options,
// 如果没有明确指定,则根据当前模式自动设置
restoreOpacityInRedGreen:
options.restoreOpacityInRedGreen !== undefined
? options.restoreOpacityInRedGreen
: true, // 默认在红绿图模式下恢复透明度
options.restoreOpacityInRedGreen !== undefined ? options.restoreOpacityInRedGreen : true, // 默认在红绿图模式下恢复透明度
};
// 如果在红绿图模式下且没有指定具体的图层,自动包含所有普通图层
@@ -801,9 +776,7 @@ export class CanvasManager {
// 获取所有非背景、非固定的普通图层ID
const normalLayerIds =
this.layers?.value
?.filter(
(layer) => !layer.isBackground && !layer.isFixed && layer.visible
)
?.filter((layer) => !layer.isBackground && !layer.isFixed && layer.visible)
?.map((layer) => layer.id) || [];
if (normalLayerIds.length > 0) {
@@ -912,9 +885,11 @@ export class CanvasManager {
// });
// };
try {
const simplifyLayersData = simplifyLayers(
JSON.parse(JSON.stringify(this.layers.value))
);
// 清除画布中选中状态
this.canvas.discardActiveObject();
this.canvas.renderAll();
const simplifyLayersData = simplifyLayers(JSON.parse(JSON.stringify(this.layers.value)));
console.log("获取画布JSON数据...", simplifyLayersData);
return JSON.stringify({
canvas: this.canvas.toJSON([
@@ -962,6 +937,7 @@ export class CanvasManager {
this.canvasHeight.value = parsedJson.canvasHeight || this.height;
this.canvasColor.value = parsedJson.canvasColor || this.backgroundColor;
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
const tempLayers = JSON.parse(parsedJson?.layers) || [];
const canvasData = parsedJson?.canvas;
@@ -1023,10 +999,7 @@ export class CanvasManager {
// 重置画布数据
this.setCanvasSize(this.canvas.width, this.canvas.height);
// 重新构建对象关系
restoreObjectLayerAssociations(
this.layers.value,
this.canvas.getObjects()
);
restoreObjectLayerAssociations(this.layers.value, this.canvas.getObjects());
// 验证图层关联关系 - 稳定后可以注释
const isValidate = validateLayerAssociations(
this.layers.value,
@@ -1038,8 +1011,7 @@ export class CanvasManager {
// 使用LayerSort工具重新排列画布对象如果可用
await this?.layerManager?.layerSort?.rearrangeObjects();
this.layerManager.activeLayerId.value = this.layers.value[0]
.children?.length
this.layerManager.activeLayerId.value = this.layers.value[0].children?.length
? this.layers.value[0].children[0].id
: this.layers.value[0]?.id || parsedJson?.activeLayerId || null;
@@ -1052,9 +1024,7 @@ export class CanvasManager {
await calllBack?.();
// 确保所有对象的交互性正确设置
await this.layerManager?.updateLayersObjectsInteractivity?.(
false
);
await this.layerManager?.updateLayersObjectsInteractivity?.(false);
console.log(this.layerManager.layers.value);
// 更新所有缩略图
@@ -1211,9 +1181,7 @@ export class CanvasManager {
if (!this.layers || !this.layers.value) return [];
// 查找所有非背景、非固定的普通图层
const normalLayers = this.layers.value.filter(
(layer) => !layer.isBackground && !layer.isFixed
);
const normalLayers = this.layers.value.filter((layer) => !layer.isBackground && !layer.isFixed);
// 收集所有普通图层中的对象
const objects = [];
@@ -1250,15 +1218,9 @@ export class CanvasManager {
// 比较尺寸允许5%的误差)
const sizeMatch =
Math.abs(
obj.width * obj.scaleX -
fixedLayerObject.width * fixedLayerObject.scaleX
) <
Math.abs(obj.width * obj.scaleX - fixedLayerObject.width * fixedLayerObject.scaleX) <
fixedLayerObject.width * fixedLayerObject.scaleX * 0.05 &&
Math.abs(
obj.height * obj.scaleY -
fixedLayerObject.height * fixedLayerObject.scaleY
) <
Math.abs(obj.height * obj.scaleY - fixedLayerObject.height * fixedLayerObject.scaleY) <
fixedLayerObject.height * fixedLayerObject.scaleY * 0.05;
// 比较位置(允许一定的偏差)