This commit is contained in:
X1627315083
2025-06-30 18:03:36 +08:00
5 changed files with 208 additions and 75 deletions

View File

@@ -137,6 +137,10 @@ export class UpdateBackgroundCommand extends Command {
// 查找背景图层
this.bgLayer = this.layers.value.find((layer) => layer.isBackground);
this.oldBackgroundColor = this.bgLayer.backgroundColor;
this.backgroundObject = findObjectById(
this.canvas,
this.bgLayer.fabricObject.id
).object;
}
execute() {
@@ -149,12 +153,9 @@ export class UpdateBackgroundCommand extends Command {
this.bgLayer.backgroundColor = this.backgroundColor;
// 更新背景对象属性
if (this.bgLayer.fabricObject) {
const { object } = findObjectById(
this.canvas,
this.bgLayer.fabricObject.id
);
object.set("fill", this.backgroundColor);
if (this.backgroundObject) {
// const { object } = findObjectById(this.canvas, this.backgroundObject.id);
this.backgroundObject.set("fill", this.backgroundColor);
this.canvas.renderAll();
}
this.backgroundColorValue.value = this.backgroundColor; // 设置背景颜色
@@ -170,12 +171,9 @@ export class UpdateBackgroundCommand extends Command {
this.bgLayer.backgroundColor = this.oldBackgroundColor;
// 恢复背景对象属性
if (this.bgLayer.fabricObject) {
const { object } = findObjectById(
this.canvas,
this.bgLayer.fabricObject.id
);
object.set("fill", this.oldBackgroundColor);
if (this.backgroundObject) {
// const { object } = findObjectById(this.canvas, this.backgroundObject.id);
this.backgroundObject.set("fill", this.oldBackgroundColor);
this.canvas.renderAll();
}
this.backgroundColorValue.value = this.oldBackgroundColor; // 恢复背景颜色
@@ -212,8 +210,13 @@ export class BackgroundSizeCommand extends Command {
this.bgLayer = this.layers.value.find((layer) => layer.isBackground);
// 记录原尺寸
this.oldWidth = this.bgLayer.fabricObject.width;
this.oldHeight = this.bgLayer.fabricObject.height;
this.backgroundObject = findObjectById(
this.canvas,
this.bgLayer.fabricObject.id
).object;
this.oldWidth = this.backgroundObject.width;
this.oldHeight = this.backgroundObject.height;
// 查找背景图层
this.bgLayer = this.layers.value.find((layer) => layer.isBackground);
@@ -221,30 +224,28 @@ export class BackgroundSizeCommand extends Command {
execute() {
// 调整画布大小
this.canvas.setWidth(this.newWidth);
this.canvas.setHeight(this.newHeight);
// this.canvas.setWidth(this.newWidth);
// this.canvas.setHeight(this.newHeight);
console.log(
`调整画布大小:${this.oldWidth}x${this.oldHeight} -> ${this.newWidth}x${this.newHeight}`
);
// 如果使用 CanvasManager通知它画布大小变化
if (
this.canvasManager &&
typeof this.canvasManager.updateCanvasSize === "function"
) {
this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight);
}
// if (
// this.canvasManager &&
// typeof this.canvasManager.updateCanvasSize === "function"
// ) {
// this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight);
// }
// 调整背景对象大小
if (this.bgLayer && this.bgLayer.fabricObject) {
if (this.bgLayer && this.backgroundObject) {
// 保持原有的背景颜色,如果没有设置则使用白色
const currentFill =
this.bgLayer.fabricObject.fill ||
this.bgLayer.backgroundColor ||
"#ffffff";
this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff";
this.bgLayer.fabricObject.set({
this.backgroundObject.set({
width: this.newWidth,
height: this.newHeight,
fill: currentFill, // 保持原有颜色
@@ -267,16 +268,16 @@ export class BackgroundSizeCommand extends Command {
this.canvas.setHeight(this.oldHeight);
// 如果使用 CanvasManager通知它画布大小恢复
if (
this.canvasManager &&
typeof this.canvasManager.updateCanvasSize === "function"
) {
this.canvasManager.updateCanvasSize(this.oldWidth, this.oldHeight);
}
// if (
// this.canvasManager &&
// typeof this.canvasManager.updateCanvasSize === "function"
// ) {
// this.canvasManager.updateCanvasSize(this.oldWidth, this.oldHeight);
// }
// 恢复背景对象大小
if (this.bgLayer && this.bgLayer.fabricObject) {
this.bgLayer.fabricObject.set({
if (this.bgLayer && this.backgroundObject) {
this.backgroundObject.set({
width: this.oldWidth,
height: this.oldHeight,
});
@@ -329,6 +330,11 @@ export class BackgroundSizeWithScaleCommand extends Command {
// 查找背景图层
this.bgLayer = this.layers.value.find((layer) => layer.isBackground);
this.backgroundObject = findObjectById(
this.canvas,
this.bgLayer.fabricObject.id
).object;
// 计算缩放比例
const scaleXRatio = this.newWidth / this.oldWidth;
const scaleYRatio = this.newHeight / this.oldHeight;
@@ -433,26 +439,24 @@ export class BackgroundSizeWithScaleCommand extends Command {
this.canvas.setHeight(this.newHeight);
// 如果使用 CanvasManager通知它画布大小变化
if (
this.canvasManager &&
typeof this.canvasManager.updateCanvasSize === "function"
) {
this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight);
}
// if (
// this.canvasManager &&
// typeof this.canvasManager.updateCanvasSize === "function"
// ) {
// this.canvasManager.updateCanvasSize(this.newWidth, this.newHeight);
// }
// 调整背景对象大小和位置
if (this.bgLayer && this.bgLayer.fabricObject) {
if (this.bgLayer && this.backgroundObject) {
// 保持原有的背景颜色,如果没有设置则使用白色
const currentFill =
this.bgLayer.fabricObject.fill ||
this.bgLayer.backgroundColor ||
"#ffffff";
this.backgroundObject.fill || this.bgLayer.backgroundColor || "#ffffff";
this.bgLayer.fabricObject.set({
this.backgroundObject.set({
width: this.newWidth,
height: this.newHeight,
left: this.newWidth / 2,
top: this.newHeight / 2,
left: this.canvas.width / 2,
top: this.canvas.height / 2,
fill: currentFill, // 保持原有颜色
});
@@ -528,12 +532,12 @@ export class BackgroundSizeWithScaleCommand extends Command {
}
// 恢复背景对象大小和位置
if (this.bgLayer && this.bgLayer.fabricObject) {
this.bgLayer.fabricObject.set({
if (this.bgLayer && this.backgroundObject) {
this.backgroundObject.set({
width: this.oldWidth,
height: this.oldHeight,
left: this.oldWidth / 2,
top: this.oldHeight / 2,
left: this.canvas.width / 2,
top: this.canvas.height / 2,
});
// 恢复图层记录的尺寸

View File

@@ -156,11 +156,18 @@ export class LassoCutoutCommand extends CompositeCommand {
selectLayer.fabricObjects = [
this.fabricImage.toObject("id", "layerId", "layerName", "parentId"),
];
this.groupLayer.clippingMask = this.fabricImage.toObject(
"id",
"layerId",
"layerName",
"parentId"
); // 设置组图层的fabricObject为遮罩图像
this.groupLayer.children.push(selectLayer);
// 插入新组图层
this.layerManager.layers.value.splice(topLayerIndex, 1, this.groupLayer);
this.layerManager.updateLayersObjectsInteractivity();
await this.layerManager.updateLayersObjectsInteractivity();
this.canvas.discardActiveObject();
this.canvas.setActiveObject(this.fabricImage);
this.canvas.renderAll();

View File

@@ -41,13 +41,15 @@ export class AddLayerCommand extends Command {
this.oldActiveLayerId = this.activeLayerId.value;
// 执行添加图层操作
if (this.insertIndex !== undefined && this.insertIndex !== null) {
this.layers.value.splice(this.insertIndex, 0, this.newLayer);
} else {
this.layers.value.push(this.newLayer);
}
// 智能插入图层到合适位置
this._insertLayerAtCorrectPosition(this.newLayer);
// if (this.insertIndex !== undefined && this.insertIndex !== null) {
// this.layers.value.splice(this.insertIndex, 0, this.newLayer);
// } else {
// this.layers.value.push(this.newLayer);
// }
// 更新活动图层
// // 更新活动图层
if (!this.newLayer.isBackground) {
this.activeLayerId.value = this.newLayer.id;
}
@@ -63,6 +65,104 @@ export class AddLayerCommand extends Command {
this.activeLayerId.value = this.oldActiveLayerId;
}
/**
* 智能插入图层到正确位置
* 根据当前激活图层位置确定新图层插入位置
* @param {Object} newLayer 要插入的新图层
* @private
*/
_insertLayerAtCorrectPosition(newLayer) {
const layers = this.layers.value;
const currentActiveLayerId = this.activeLayerId?.value;
// 如果没有当前激活图层插入到顶部索引0
if (!currentActiveLayerId) {
layers.splice(0, 0, newLayer);
return;
}
// 查找当前激活图层的位置
const {
layer: activeLayer,
parent: parentLayer,
index: activeIndex,
} = this._findLayerPosition(currentActiveLayerId);
if (!activeLayer) {
// 没找到激活图层,插入到顶部
layers.splice(0, 0, newLayer);
return;
}
// 确定插入位置
let insertIndex = 0;
if (parentLayer) {
// 当前激活图层是子图层
// 在同一父图层内,插入到激活子图层之上
insertIndex = Math.max(0, activeIndex);
parentLayer.children = parentLayer.children || [];
parentLayer.children.splice(insertIndex, 0, newLayer);
console.log(
`新图层已插入到子图层位置: ${insertIndex} (父图层: ${parentLayer.name})`
);
} else {
// 当前激活图层是一级图层
// 在一级图层中,插入到激活图层之上
const activeLayerIndex = layers.findIndex(
(layer) => layer.id === currentActiveLayerId
);
insertIndex = Math.max(0, activeLayerIndex);
layers.splice(insertIndex, 0, newLayer);
console.log(`新图层已插入到一级图层位置: ${insertIndex}`);
}
}
/**
* 查找图层位置信息
* @param {String} layerId 图层ID
* @returns {Object} 包含图层、父图层和索引的对象
* @private
*/
_findLayerPosition(layerId) {
const layers = this.layers.value;
// 先在一级图层中查找
for (let i = 0; i < layers.length; i++) {
const layer = layers[i];
if (layer.id === layerId) {
return {
layer: layer,
parent: null,
index: i,
};
}
// 在子图层中查找
if (layer.children && Array.isArray(layer.children)) {
for (let j = 0; j < layer.children.length; j++) {
const childLayer = layer.children[j];
if (childLayer.id === layerId) {
return {
layer: childLayer,
parent: layer,
index: j,
};
}
}
}
}
return {
layer: null,
parent: null,
index: -1,
};
}
getInfo() {
return {
name: this.name,

View File

@@ -320,7 +320,7 @@ export class CreateTextCommand extends Command {
this.y = options.y;
this.textOptions = options.textOptions || {};
// 生成唯一ID
this.textId = options?.textId || this.generateId("text_");
this.textId = options?.textId || generateId("text_");
this.layerId = options?.layerId || generateId("text_layer_");
// 生成的对象和图层信息
@@ -526,14 +526,6 @@ export class CreateTextCommand extends Command {
};
}
/**
* 生成唯一ID
* @returns {String} 唯一ID
*/
generateId() {
return `text_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
}
getInfo() {
return {
name: this.name,

View File

@@ -286,12 +286,6 @@ export class LayerManager {
// 应用图层视觉属性
if (layer.opacity !== undefined) obj.opacity = layer.opacity;
if (layer.blendMode) obj.globalCompositeOperation = layer.blendMode;
if (layer.clippingMask) {
const { object } = findObjectById(this.canvas, layer.clippingMask?.id);
if (object) {
obj.clipPath = object;
}
}
}
// 私有方法:应用交互规则
@@ -337,6 +331,42 @@ export class LayerManager {
}
});
});
// 设置裁剪对象
layers.forEach((layer) => {
if (layer.clippingMask) {
// 如果是组图层 则给所有子对象设置裁剪对象
if (layer.type === LayerType.GROUP || layer.children?.length > 0) {
layer.children.forEach((childLayer) => {
const { object } = findObjectById(
this.canvas,
layer.clippingMask?.id
);
if (object) {
const tempClipPath = fabric.util.object.clone(object);
tempClipPath.set({
// 设置绝对定位
absolutePositioned: true,
});
const childObj = this.canvas
.getObjects()
.find((o) => o.layerId === childLayer.id);
if (childObj) {
childObj.clipPath = tempClipPath;
}
}
});
} else {
const { object } = findObjectById(
this.canvas,
layer.clippingMask?.id
);
if (object) {
obj.clipPath = object;
}
}
}
});
}
/**
* 创建新图层
@@ -393,7 +423,7 @@ export class LayerManager {
command.undoable = options.undoable;
// 如果是第一个图层或者普通图层数量小于等于3设置为不可撤销
if (this.layers.value.length === 3 || normalLayersCount < 1) {
if (normalLayersCount < 1) {
command.undoable = false;
}