Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I hope you can help me with this issue I'm having. In my app, I am using globalCompositionOperation set to 'source-atop' to mask images and svg objects to a base object. The base object is the first object added to the canvas and all other objects should clip to it.

The problem shows when I add an svg to the canvas, and set its property objectCaching to false. The object then doesnt clip to the base object, and globalCompositionOperation set to 'source-atop' has no effect. As soon as I set objectCaching to true , then globalCompositionOperation works fine.

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

In my case, I need to set objectCaching for svg objects to false, since I need to change the svg's colors later on, and for that, it seems to only work when objectCaching is false.

If there is a way to manually "clear" the object's cache after it has been manipulated, that would be awesome but I don't think the current api allows it. That way I could set objectCaching to true, and clipping using globalCompositionOperation will work, and after changing the svgs' colors, I could clear/refresh its cache.

Example here: http://jsfiddle.net/josefano09/hk1on32n/

UPDATE:

The reason I was using objectCaching set to false is because my svg wasn't rendering properly when it was set to true. I found out that it was due to a bug in my code when getting the svg colors. Once I fixed that bug I was able to get advantage of the better performance using objectCaching set to true and also the clipping of the object using globalCompositionOperation worked fine.

After that all I needed was to be able to update the svg right after I change the color for some paths of the svg. Setting the "dirty" flag to true and doing a canvas.renderAll() worked perfectly.

like image 973
faniva Avatar asked Jan 27 '26 01:01

faniva


1 Answers

To make it a little clearer

Keep caching on.

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

When you change the colour just set the dirty flag to 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

Add the following to your fiddle so see it happen.

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)
like image 192
Blindman67 Avatar answered Jan 29 '26 23:01

Blindman67