当 "objectCaching" 为 false 时,使用 "globalCompositionOperation" 设置为 'source-atop' 的屏蔽不起作用

Masking using "globalCompositionOperation" set to 'source-atop' not working when "objectCaching" is false

我希望你能帮助我解决我遇到的这个问题。在我的应用程序中,我使用 globalCompositionOperation 设置为 'source-atop' 来将图像和 svg 对象屏蔽到基础对象。基础对象是添加到 canvas 的第一个对象,所有其他对象都应剪辑到它。

当我将 svg 添加到 canvas 并将其 属性 objectCaching 设置为 false 时出现问题。然后该对象不会剪辑到基础对象,并且 globalCompositionOperation 设置为 'source-atop' 没有任何效果。只要我将 objectCaching 设置为 true ,那么 globalCompositionOperation 就可以正常工作。

    fabric.loadSVGFromString(svgString, function(objects, opts) {

        var svg = fabric.util.groupSVGElements(objects, opts);

        svg.set({
          objectCaching : false, //  <--- PROBLEM HERE ! , change to true to see how globalCompositeOperation works fine when objectCaching is set to "true"
          globalCompositeOperation : 'source-atop'
        });

在我的例子中,我需要将 svg 对象的 objectCaching 设置为 false,因为稍后我需要更改 svg 的颜色,为此,它似乎只有在 objectCaching 为 false 时才有效。

如果有一种方法可以在操作对象后手动 "clear" 对象的缓存,那会很棒,但我认为当前的 api 不允许这样做。这样我就可以将 objectCaching 设置为 true,并且使用 globalCompositionOperation 进行剪辑将起作用,并且在更改 svgs 的颜色后,我可以 clear/refresh 它的缓存。

这里的例子: http://jsfiddle.net/josefano09/hk1on32n/

更新:

我将 objectCaching 设置为 false 的原因是我的 svg 在设置为 true 时无法正确呈现。我发现这是由于获取 svg 颜色时我的代码中存在错误。一旦我修复了这个错误,我就能够通过将 objectCaching 设置为 true 来获得更好的性能,并且使用 globalCompositionOperation 对对象进行剪辑也能正常工作。

在那之后,我所需要的就是能够在更改 svg 的某些路径的颜色后立即更新 svg。将 "dirty" 标志设置为 true 并执行 canvas.renderAll() 工作得很好。

为了更清楚一点

继续缓存。

svg.objectCaching = true; // default so dont need to set just here to show its val
svg.globalCompositeOperation = 'source-atop';

当您更改颜色时,只需将脏标记设置为 true。

svg.dirty = true;
canvas.renderAll();  // you can force rendering or if you are rendering
                     // already you only have to set dirty, it will be
                     // re rendered the next time it is displayed

将以下内容添加到您的 fiddle 中,看看它会发生什么。

svg.objectCaching = true;
svg.globalCompositeOperation = 'source-atop';

const cols = ["red","green","blue","yellow","black","orange"];
var colCount = 0;
setInterval(()=>{
  svg.paths.forEach(p=>{ p.fill = cols[colCount % cols.length] })
  colCount += 1;
  svg.dirty = true;
  canvas.renderAll();
},500)