I am applying filters to objects (following image filters demo) and everything is ok but after I save and load the canvas, the image filters change index.
At the moment I have four filters and they are applied by index (as shown in the demo).
0 : Grayscale
1 : Invert
2 : Remove Color
3 :- Blend Color
So if I apply Grayscale, and Remove Color, the 'filters' array looks like this , with indexes 0 and 2 which is correct...
But after I load the canvas (using loadFromJSON), the object's 'filters' array looks like this, with the indexes reset...
Is there any way that I can load the object and retain the filter indexes? There is code that is dependant on this and it is causing errors when I load a canvas that has objects with filters.
I have tried applying the following upon creation of the object...
oImg.filters = [
false,
false,
false,
false
];;
It works ok when the object is created...
But when it is loaded, the false indexes are removed and its the same result...
I managed to get this working by changing the way I applied and retrieved the filters (by type rather than index). I simply checked to see if the filter existed (by 'type' not index), then spliced the filter at the desired index.
Changed this function...
getFilter(index) {
var obj = canvas.getActiveObject();
return obj.filters[index];
}
to this...
getFilter(type) {
var obj = canvas.getActiveObject();
if (obj) {
filter = null;
obj.filters.forEach(function(f) {
if (f.type == type) {
filter = f;
}
});
return filter;
}
}
Changed this function...
applyFilter(index, filter) {
var object = canvas.getActiveObject();
object.filters[index] = filter;
object.applyFilters();
canvas.renderAll();
}
to this...
applyFilter(type, filterIndex, filter) {
var obj = canvas.getActiveObject();
var indexExists = false;
var filterFound = false;
if (obj) {
obj.filters.forEach(function(f, i) {
if (f.type == type) {
filterFound = true;
obj.filters[i] = filter;
}
if (filterIndex == i) {
indexExists = true;
}
});
if (!filterFound && indexExists) {
obj.filters.splice(filterIndex, 0, filter);
} else if (!filterFound && !indexExists) {
obj.filters[filterIndex] = filter;
}
}
obj.applyFilters();
canvas.renderAll();
}
Changed this function...
applyFilterValue(index, prop, value) {
var obj = canvas.getActiveObject();
if (obj.filters[index]) {
obj.filters[index][prop] = value;
obj.applyFilters();
canvas.renderAll();
}
}
to this...
applyFilterValue(type, filterIndex, prop, value) {
var obj = canvas.getActiveObject();
if (obj) {
obj.filters.forEach(function(f, i) {
if (f.type == type) {
obj.filters[i][prop] = value;
}
});
}
obj.applyFilters();
canvas.renderAll();
}
In my current project i need to have the ability to customize the order of the filters. The problem with lost indexing after canvas.toDatalessJSON()
gave me the idea to make a simple solution for that.
I simply build a new array of filternames every time og load the canvas.
const filterNamesDefault = ['Contrast', 'Saturation', 'Sharpen', 'Tint', 'invert', 'grayscale', 'Sepia'];
var filterNames = [];
var canvasLoaded = false;
canvasLoaded
is a boolean that has to be set to true when a canvas has been loaded.
Then in the applyFilterType
and applyFilterValue
functions i provide the functions with the filter type instead of the index:
function filterIndex(filterType) {
if (canvasLoaded) { return filterNames.indexOf(filterType); } else { return filterNamesDefault.indexOf(filterType); }
}
function applyFilterType(type, filter) {
var index=filterIndex(type);
...
}
function applyFilterValue(type, prop, value) {
var index=filterIndex(type);
...
}
Let's say i add some filters ['Sharpen','Tint']
that are stored in the canvas.filters
object as usual, and after canvas save/load are repositioned.
Then when i want to display the filter edit box for a image layer i execute this:
var obj = canvas.getActiveObject();
filterNames = [];
obj.filters.forEach(function(f,i){
filterNames.push(f.type);
});
for (var i=0;i<filterNamesDefault.length;i++){
if (!filterNames.includes(filterNamesDefault[i])) filterNames.push(filterNamesDefault[i]);
}
Now the new order for filterNames
is:
['Sharpen', 'Tint', 'Contrast', 'Saturation', 'invert', 'grayscale', 'Sepia']
And it works as well with the new order of the filters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With