javascriptarraysfabricjsjavascript-objectsfabricjs2

fabricjs: retain the correct indexes of an object's image filters after loadFromJSON


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...

enter image description here

But after I load the canvas (using loadFromJSON), the object's 'filters' array looks like this, with the indexes reset...

enter image description here

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...

enter image description here

But when it is loaded, the false indexes are removed and its the same result...

enter image description here


Solution

  • 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();
    }