简体   繁体   中英

FabricJS - Canvas blend mode in free drawing mode

When using fabrics free drawing mode I want to add different lines to the canvas with an opacity. These lines should not add up their opacity when drawn on each other. Therefore I'm changing the canvas blend mode to xor . Anyway, when drawing lines over each other the opacity still adds up. What am I doing wrong here?

 var canvas = new fabric.Canvas("a", { isDrawingMode : true }); document.getElementById("cbFreeDrawing").onchange = function () { canvas.isDrawingMode = this.checked; }; canvas.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas.renderAll.bind(canvas)); canvas.freeDrawingBrush.width = 25; canvas.freeDrawingBrush.color = "rgba(255,0,0,.5)"; //this seems not to work canvas.getContext().globalCompositeOperation = 'xor'; 
 canvas { border: 1px solid; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.min.js"></script> Drawing Mode: <input id="cbFreeDrawing" type="checkbox" checked="true"/><br/> <canvas id="a" width="400" height="300"></canvas> 

During the freeDrawing you are drawing on the upperCanvasEl , a canvas element placed over the lowerCanvasEl . The contexts for those elements are always ready to get in the properties: canvas.contextTop and canvas.contextContainer .

What you can do is to set the single path globalCompositeOperation to 'xor' when it gets passed to lowerCanvas. There is an event (path:created) that you can use. I moved the background in a separate canvas ( but it can be just an image placed down the canvas ) so that the lines does not xor with background itself.

 var canvas = new fabric.Canvas("a", { isDrawingMode : true }); var canvas2 = new fabric.StaticCanvas("b"); canvas.lowerCanvasEl.parentNode.appendChild(canvas2.lowerCanvasEl) document.getElementById("cbFreeDrawing").onchange = function () { canvas.isDrawingMode = this.checked; }; canvas.on('path:created', function(opt) { opt.path.globalCompositeOperation = 'xor'; canvas.renderAll(); }); canvas2.setBackgroundImage('http://fabricjs.com/assets/jail_cell_bars.png', canvas2.renderAll.bind(canvas2)); canvas.freeDrawingBrush.width = 25; canvas.freeDrawingBrush.color = "rgba(255,0,0,.5)"; //this seems not to work canvas.contextTop.globalCompositeOperation = 'xor'; 
 canvas { border: 1px solid; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.min.js"></script> Drawing Mode: <input id="cbFreeDrawing" type="checkbox" checked="true"/><br/> <canvas id="a" width="400" height="300"></canvas> <canvas id="b" width="400" height="300"></canvas> 

+AndreaBogazzi just found out the answer provided only works when opacity is .5 if its set to another value opacities are overlapped / combined / behave in another way.

Fiddle (simplified for better understanding): https://jsfiddle.net/c8mf391q/

var canvas = new fabric.Canvas("a", {
        isDrawingMode : true
});



canvas.on('path:created', function(opt) {
  opt.path.globalCompositeOperation = 'xor';
  canvas.renderAll();
});


canvas.freeDrawingBrush.width = 25;
canvas.freeDrawingBrush.color = "rgba(255,0,0,.3)";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM