fabricjs:在从JSON加载后保留对象图像过滤器的正确索引

7
我正在对对象应用过滤器(如 image filters demo 所示),一切正常,但在保存和加载画布后,图像过滤器的索引会改变。
目前,我有四个过滤器,并且它们是按索引应用的(如演示所示)。

0:灰度

1:反相

2:去色

3:混合颜色

因此,如果我应用灰度和去色,则“filters”数组看起来像这样,具有正确的索引0和2...

enter image description here

但是在我加载画布(使用loadFromJSON)之后,对象的“filters”数组看起来像这样,索引被重置了...

enter image description here

有没有办法在加载对象时保留筛选器索引?由于存在依赖此功能的代码,因此在加载具有筛选器对象的画布时会导致错误。

我已尝试在创建对象时应用以下方法...

   oImg.filters = [
     false,
     false,
     false,
     false
   ];;

当对象创建时,它可以正常工作...

enter image description here

但是当它被加载时,虚假的索引将被移除,结果将是相同的...

enter image description here


我已经成功地通过按类型而非索引应用函数来使其工作。 - Serks
2个回答

3

我通过改变应用和检索过滤器的方式(按类型而不是索引)来使这个工作。我只是检查过滤器是否存在(按“类型”而不是索引),然后在所需的索引处拼接过滤器。

将此函数更改为...

getFilter(index) { 
   var obj = canvas.getActiveObject();
   return obj.filters[index];
}

转换为...

getFilter(type) { 
  var obj = canvas.getActiveObject();
  if (obj) {
    filter = null;
    obj.filters.forEach(function(f) {
      if (f.type == type) {
        filter = f;
      }
    });
    return filter;
  }
}

修改了这个函数...

applyFilter(index, filter) {
  var object = canvas.getActiveObject();
  object.filters[index] = filter;
  object.applyFilters();
  canvas.renderAll();
}

转换为...

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

修改了这个函数...

applyFilterValue(index, prop, value) {
  var obj = canvas.getActiveObject();
  if (obj.filters[index]) {
    obj.filters[index][prop] = value;
    obj.applyFilters();
    canvas.renderAll();
  }
}

到这个...

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

1
在我的当前项目中,我需要有能力自定义过滤器的顺序。由于canvas.toDatalessJSON()之后索引丢失的问题,我想出了一个简单的解决方案。每次加载画布时,我只需构建一个新的过滤器名称数组即可。
const filterNamesDefault = ['Contrast', 'Saturation', 'Sharpen', 'Tint', 'invert', 'grayscale', 'Sepia'];

var filterNames = [];
var canvasLoaded = false;

canvasLoaded 是一个布尔值,当画布加载完成时必须设置为 true。 然后在 applyFilterTypeapplyFilterValue 函数中,我提供了用于过滤类型的函数而不是索引:

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);
     ...
}

假设我添加了一些过滤器['Sharpen','Tint'],它们像往常一样存储在canvas.filters对象中,并且在保存/加载画布后重新定位。 然后,当我想要为图像图层显示过滤器编辑框时,我执行以下操作:
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]);
}

现在 filterNames 的新顺序为:
['Sharpen', 'Tint', 'Contrast', 'Saturation', 'invert', 'grayscale', 'Sepia']

而且它也能与新的筛选顺序配合使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接