101 lines
3.0 KiB
JavaScript
101 lines
3.0 KiB
JavaScript
|
|
import { isArray } from "lodash-es";
|
|||
|
|
import { optimizeCanvasRendering } from "../utils/helper";
|
|||
|
|
import { restoreObjectLayerAssociations } from "../utils/layerUtils";
|
|||
|
|
import { Command } from "./Command";
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 橡皮擦操作命令
|
|||
|
|
* 支持橡皮擦操作的撤销和重做
|
|||
|
|
*/
|
|||
|
|
export class EraserCommand extends Command {
|
|||
|
|
/**
|
|||
|
|
* 构造函数
|
|||
|
|
* @param {Object} options 命令选项
|
|||
|
|
* @param {Object} options.canvas Fabric画布实例
|
|||
|
|
* @param {Object} options.layerManager 图层管理器
|
|||
|
|
* @param {Object} options.beforeSnapshot 擦除前的状态快照
|
|||
|
|
* @param {Object} options.afterSnapshot 擦除后的状态快照
|
|||
|
|
* @param {Array} options.affectedObjects 擦除影响的对象列表(可选)
|
|||
|
|
*/
|
|||
|
|
constructor(options) {
|
|||
|
|
super({
|
|||
|
|
name: "橡皮擦操作",
|
|||
|
|
description: `擦除`,
|
|||
|
|
...options,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
this.canvas = options.canvas;
|
|||
|
|
this.layerManager = options.layerManager;
|
|||
|
|
this.beforeSnapshot = options.beforeSnapshot;
|
|||
|
|
this.afterSnapshot = options.afterSnapshot;
|
|||
|
|
this.affectedObjects = options.affectedObjects || [];
|
|||
|
|
this.fristLoad = true; // 是否是第一次加载
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 执行橡皮擦操作
|
|||
|
|
*/
|
|||
|
|
async execute() {
|
|||
|
|
if (!this.beforeSnapshot || !this.afterSnapshot) {
|
|||
|
|
console.warn("缺少状态快照,无法执行橡皮擦命令");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
if (!this.fristLoad)
|
|||
|
|
await this._restoreCanvasState(this.afterSnapshot); // 应用重做的状态
|
|||
|
|
else await this.layerManager?.updateLayersObjectsInteractivity?.(false);
|
|||
|
|
this.fristLoad = false; // 标记为非第一次加载
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 撤销橡皮擦操作
|
|||
|
|
*/
|
|||
|
|
async undo() {
|
|||
|
|
if (!this.beforeSnapshot) {
|
|||
|
|
console.warn("缺少擦除前的状态快照,无法撤销");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 恢复到擦除前的状态
|
|||
|
|
await this._restoreCanvasState(this.beforeSnapshot);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 恢复画布状态
|
|||
|
|
* @param {Object} snapshot 状态快照
|
|||
|
|
* @private
|
|||
|
|
*/
|
|||
|
|
async _restoreCanvasState(snapshot) {
|
|||
|
|
// 对比 eraser erasable 两个属性,如果当前对象的eraser属性和erasable属性不一致,则需要更新对象的eraser属性
|
|||
|
|
if (!snapshot || !snapshot.objects) return;
|
|||
|
|
// 优化渲染 - 统一批处理 支持异步回调 防止闪屏
|
|||
|
|
await optimizeCanvasRendering(this.canvas, async () => {
|
|||
|
|
return new Promise((resolve) => {
|
|||
|
|
this.canvas.loadFromJSON(snapshot, async () => {
|
|||
|
|
// 恢复图层关联
|
|||
|
|
this._restoreObjectLayerAssociations();
|
|||
|
|
// 确保所有对象的交互性正确设置
|
|||
|
|
await this.layerManager?.updateLayersObjectsInteractivity?.(false);
|
|||
|
|
resolve();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 恢复对象与图层的关联关系
|
|||
|
|
* @private
|
|||
|
|
*/
|
|||
|
|
_restoreObjectLayerAssociations() {
|
|||
|
|
if (!this.layerManager) return;
|
|||
|
|
|
|||
|
|
const canvasObjects = this.canvas.getObjects();
|
|||
|
|
restoreObjectLayerAssociations(
|
|||
|
|
this.layerManager?.layers?.value,
|
|||
|
|
canvasObjects
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|