我正在尝试使用 Fabric.js 实现撤消功能。我有这个代码:
let groupObjects = lastAction.before._objects;
if (groupObjects) {
let selectionGroup = new fabric.ActiveSelection(groupObjects, { canvas: canvas });
selectionGroup.set({ ...lastAction.before });
selectionGroup.setCoords();
canvas.setActiveObject(selectionGroup);
}
canvas.renderAll();
lastAction.before
包含对象或多选对象在修改之前的值。基本上是这样的:
lastAction = { before: fabric.util.object.clone(canvas.getActiveObjects()) }
此代码在执行撤消定位时有效,但是当重新缩放对象时,此代码仅调整选择框的大小,而不调整其中的对象的大小。我尝试添加它来恢复单个对象的大小,但它保持不变:
groupObjects.forEach((obj, index) => {
let objectToRevert = canvas.getObjects().find(o => o.objectId === obj.objectId);
objectToRevert.set({
left: obj.left,
top: obj.top,
scaleX: obj.scaleX,
scaleY: obj.scaleY,
angle: obj.angle,
width: obj.width,
height: obj.height,
flipX: obj.flipX,
flipY: obj.flipY,
skewX: obj.skewX,
skewY: obj.skewY
});
objectToRevert.setCoords();
});
您所采取的方法是在正确的轨道上。看起来主要问题在于您如何尝试恢复单个对象的比例。用于恢复定位和角度的代码似乎很好,但 Fabric.js 以特定方式处理缩放、宽度和高度,这就是为什么简单地设置这些属性可能无法给出所需的结果。
以下是它可能无法按预期工作的原因以及如何修复它的详细信息:
问题: 当您尝试通过设置宽度、高度、scaleX 和scaleY 来恢复单个对象的大小时,Fabric.js 以更加相互依赖的方式处理这些属性。具体来说:
对象创建后,宽度和高度通常是固定的。如果您稍后尝试更改它们,尤其是与缩放结合使用,可能会导致不正确的结果,因为 Fabric.js 使用缩放值(scaleX、scaleY)来确定对象相对于其原始宽度/高度的大小。 解决方案: 与其同时修改宽度/高度和scaleX/scaleY,不如专注于恢复缩放而不触及对象的宽度和高度。此外,您需要通过调用 setCoords() 并随后重新渲染画布来确保这些更改正确传播。
以下是调整代码的方法:
更新的解决方案:
groupObjects.forEach((obj, index) => {
// Find the current object in the canvas that matches the one you want to revert
let objectToRevert = canvas.getObjects().find(o => o.objectId === obj.objectId);
// Restore position, scale, and other transformations
objectToRevert.set({
left: obj.left,
top: obj.top,
scaleX: obj.scaleX, // Restore scaling
scaleY: obj.scaleY, // Restore scaling
angle: obj.angle, // Restore rotation
flipX: obj.flipX, // Restore flipping
flipY: obj.flipY, // Restore flipping
skewX: obj.skewX, // Restore skewing
skewY: obj.skewY // Restore skewing
});
// Important: Do not modify `width` and `height`, as scale already takes care of it
// Recalculate object boundaries and coordinates
objectToRevert.setCoords();
});
// Re-render the canvas to apply all changes
canvas.renderAll();