Search code examples
javascripttransparencyfabricjsopacityoutline

fabric.js: How to make a unique, transparent shape with stroke?


I want to free-draw shapes with fabric.js. The outline is, say, 20px (such that the user sees it clearly).

After the user has drawn it, the shape should been filled with the same color as the outline.

The whole thing should be semi-transparent. Unfortunately, this causes the overlap between outline and fill to be less transparent and draws a strange "inner outline" to the shape.

Is there a way to make shape uniquely semi-transparent?

Maybe a trick would be: after the user has drawn the shape, "widen" the shape by half of outline thickness and set outline thickness to 1. Would that be possible?

See this https://jsfiddle.net/4ypdwe9o/ or below for an example.

var canvas = new fabric.Canvas('c', {
    isDrawingMode: true,
    
 });
 
 canvas.freeDrawingBrush.width = 10;
 canvas.freeDrawingBrush.color = 'rgb(255, 0, 0)';

canvas.on('mouse:up', function() {

  canvas.getObjects().forEach(o => {
    o.fill = 'rgb(255, 0, 0)';
    o.opacity = 0.5;
   });
  canvas.renderAll();
})
canvas {
    border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>


Solution

  • In fabric.js 1.7.3, they have another implementation. When I use

    fabricCanvasObject.getObjects('path').slice(-1)[0].setFill("red");
    fabricCanvasObject.getObjects('path').slice(-1)[0].setOpacity(0.5);
    

    instead of

    fabricCanvasObject.getObjects('path').slice(-1)[0].fill = "red";
    fabricCanvasObject.getObjects('path').slice(-1)[0].opacity = 0.5;
    

    The boundary is painted correctly, without overlap. So, the temporary canvas from Janusz's answer is not needed anymore. For my former fabric.js 1.5.0, the answer from Janusz solved the problem.