import { Command } from "./Command"; import { findLayerRecursively } from "../utils/layerHelper"; import { fabric } from "fabric-with-all"; import { findObjectById, generateId, insertObjectAtZIndex, removeCanvasObjectByObject, } from "../utils/helper"; import { restoreFabricObject } from "../utils/objectHelper"; /** * 填充图层背景命令 */ export class FillLayerBackgroundCommand extends Command { constructor(options) { super({ name: "填充图层背景", saveState: true }); this.canvas = options.canvas; this.layers = options.layers; this.canvasManager = options.canvasManager; this.layerId = options.layerId; this.fillColor = options.fillColor; this.oldFill = null; this.oldFillColor = null; this.newFill = null; const { layer } = findLayerRecursively(this.layers.value, this.layerId); this.layer = layer; this.group = null; this.isGroupLayer = layer.isGroup || !!layer.children?.length || false; // 是否为组图层 this.originalfabricObjects = this._collectOriginalObjects(); // 记录所有的原始对象 } async execute() { const layer = this.layer; // 只允许填充背景层或普通图层 // if (!layer.isBackground && !layer.isFixed && !layer.fabricObjects?.length) return false; // 记录原填充色 this.oldFill = layer.fill ?? null; this.oldFillColor = layer.oldFillColor ?? null; // 更新fabric对象填充 // 判断是否有遮罩层 有遮罩使用遮罩层大小 否则使用第一个大小 const { object } = findObjectById(this.canvas, layer.fabricObjects?.[0]?.id); if (object) { const originalInfo = object?.getBoundingRect?.(true, true); this.newFill = new fabric.Rect({ width: originalInfo.width, height: originalInfo.height, left: originalInfo.left || 0, top: originalInfo.top || 0, fill: this.fillColor, layerId: this.layerId, id: generateId("fill-"), selectable: false, evented: false, originX: object.originX || "center", originY: object.originY || "center", scaleX: object.scaleX || 1, scaleY: object.scaleY || 1, }); } if (layer.clippingMask) { // 反序列化 clippingMask const clippingMaskFabricObject = await restoreFabricObject(layer.clippingMask, this.canvas); clippingMaskFabricObject.clipPath = null; clippingMaskFabricObject.set({ // 设置绝对定位 // ...getOriginObjectInfo(layer.clippingMask), // 恢复原定位 absolutePositioned: true, }); this.newFill = new fabric.Rect({ width: clippingMaskFabricObject.width, height: clippingMaskFabricObject.height, left: clippingMaskFabricObject.left || 0, top: clippingMaskFabricObject.top || 0, fill: this.fillColor, layerId: this.layerId, id: generateId("fill-"), selectable: false, evented: false, originX: clippingMaskFabricObject.originX || "center", originY: clippingMaskFabricObject.originY || "center", scaleX: clippingMaskFabricObject.scaleX || 1, scaleY: clippingMaskFabricObject.scaleY || 1, }); this.newFill.clipPath = clippingMaskFabricObject; // 设置填充的遮罩 this.newFill.dirty = true; // 标记为脏,以便重新渲染 this.newFill.setCoords(); } // 判断fabricObjects是否是组,是组则添加填充到最前面,否则创建组 if (layer.fabricObjects && layer.fabricObjects.length > 0) { // 如果是组,直接添加到组中 // 否则创建一个新的组 插入到原本的图层对象前面 // const layerObjects = this.canvas // .getObjects() // .reverse() // .filter((obj) => obj.layerId === this.layerId); let insertIndex = this.canvas.getObjects()?.findIndex((obj) => obj.id === layer.fabricObjects?.[0]?.id) || 0; insertIndex = insertIndex == -1 ? 0 : insertIndex; // this.group = new fabric.Group([this.newFill, ...layerObjects]); // this.group.set({ // id: layerObjects[0]?.id || generateId("group-"), // layerId: layerObjects[0]?.layerId, // }); // this.group.setCoords(); layer.fabricObjects = [this.newFill?.toObject?.(["id", "layerId"]) || this.newFill]; // removeCanvasObjectByObject(this.canvas, layer.fabricObjects[0]); insertObjectAtZIndex(this.canvas, this.newFill, insertIndex, false); // 插入到画布的指定位置 // 将新填充对象添加到画布 } else if (layer.children && layer.children.length > 0) { // 如果是组图层,直接添加到组中 let insertIndex = this.canvas .getObjects() .findIndex( (obj) => obj.id === this.originalfabricObjects[this.originalfabricObjects.length - 1]?.id ) || 0; insertIndex = insertIndex == -1 ? 0 : insertIndex; insertObjectAtZIndex(this.canvas, this.newFill, insertIndex, false); // 插入到画布的指定位置 } this.canvas.renderAll(); layer.fill = this.newFill.toObject(["id", "layerId"]); layer.fillColor = this.fillColor; // 重新排序 // 使用LayerSort工具重新排列画布对象(如果可用) await this?.canvasManager?.layerManager?.layerSort?.rearrangeObjects?.(); this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id); return true; } async undo() { this.layer.fillColor = this.oldFillColor; this.layer.fill = this.oldFill; this.group.removeWithUpdate(this.newFill); this.canvas.remove(this.newFill); this.canvas.renderAll(); this.canvasManager.thumbnailManager?.generateLayerThumbnail(this.layer.id); return true; } _collectOriginalObjects() { if (this.layer.children && this.layer.children.length > 0) { // 如果是组图层,收集所有子图层的fabric对象 return this.layer.children .flatMap((child) => child.fabricObjects || []) .map((obj) => { return findObjectById(this.canvas.value, obj.id)?.object || obj; }); } else if (this.layer.fabricObjects && this.layer.fabricObjects.length > 0) { // 如果是普通图层,直接返回其fabric对象 return this.layer.fabricObjects.map((obj) => { return findObjectById(this.canvas.value, obj.id)?.object || obj; }); } else { // 如果没有fabric对象,返回空数组 return []; } } }