aico-image-editor
Version:
Combine multiple image into and create single combined image
137 lines (116 loc) • 5.06 kB
JavaScript
/**
* TransormCommand for other properties undo and redo
*/
export class TransformCommand {
constructor(object,canvas, options = {}) {
this.object = object;
this.canvas = canvas;
this._initStateProperties(options);
this.state = {};
this.prevState = {};
this._saveState(options);
this._savePrevState(options);
}
_initStateProperties(options) {
this.stateProperties = this.object.stateProperties;
//check if custom passed property's name already exists in the list of this.stateProperties
// and if not then add that name in this.stateProperties array to save it for undo/redo
// if(options.stateProperties && options.stateProperties.length) {
// options.stateProperties.forEach(prop => {
// if(!this.stateProperties.includes(prop.name)) {
// this.stateProperties.push(prop.name);
// }
// })
// }
}
execute() {
this._restoreState();
this.object.setCoords();
}
undo() {
this._restorePrevState();
this.object.setCoords();
}
_restoreState() {
this._restore(this.state);
}
_restorePrevState() {
this._restore(this.prevState);
}
_restore(state) {
this.stateProperties.forEach((prop) => {
if(prop !== 'clipPath') {
this.object.set(prop, state[prop]);
}
// if(prop === 'symbolSVGColor') {
// //console.log(state[prop]);
// var filter = new fabric.Image.filters.ReplaceColor({
// color: state[prop].prev, // Set the color you want to replace (black)
// replace: state[prop].next // Set the color you want to replace it with (red)
// });
// this.object.filters.push(filter);
// this.object.applyFilters();
// }
if(prop === 'svgPathColor') {
this.object._objects?.filter(object => object.type === 'path').forEach(function(object) {
if(object.fill !== '#fff' || object.fill === '#ffffff' || object.fill === 'rgb(255,255,255)') {
object.set({fill: state[prop]})
}
})
}
if(prop === 'filters') {
this.object.applyFilters();
}
//while doing restore operation(aka undo/redo), you will also call savestate incase you need to update
// history from that point/ rewriting history from middle of history array
})
this.object.saveState();
if(this.object.filters) {
Alpine.store('canvas').saveStateForFilters(this.object);
}
let self = this;
window.dispatchEvent(new CustomEvent('object-restored-via-undo-redo', {
detail: {
object: self.object
}
}))
this.canvas.renderAll()
}
_saveState(options) {
this.stateProperties.forEach((prop) => {
if(prop !== 'filters') {
this.state[prop] = this.object.get(prop)
}
if(prop === 'filters') {
//console.log(this.state[prop])
this.state[prop] = this.object.get(prop).slice()
}
})
}
_savePrevState(options) {
if(this.object._stateProperties) {
this.stateProperties.forEach((prop) => {
if(prop !== 'filters') {
this.prevState[prop] = this.object._stateProperties[prop];
}
if(prop === 'path' && this.prevState[prop] !== null) {
Object.setPrototypeOf(this.prevState[prop], fabric.Path.prototype)
}
//same thing for filters prototype except the change that filters is array hence it;s individual element
// needs to be updated with correct prototype when stored as prevState[prop] i.e. prevState['filters']
if(prop === 'filters') {
// _stateProperties does not work here properly for state properties
// if(this.object.filters.length) {
// this.prevState[prop] = this.object._stateProperties[prop].slice();
// this.prevState[prop].forEach((filterObject,filterObjectIndex) => {
// const originalFilterObjectPrototypeAtSameIndex = Object.getPrototypeOf(this.object.filters[filterObjectIndex])
// Object.setPrototypeOf(filterObject, originalFilterObjectPrototypeAtSameIndex)
// })
// }
//console.log(this.prevState[prop])
this.prevState[prop] = this.object.myOwnStateProps?.filters?.slice() || [];
}
})
}
}
}