Question: 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.

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

```css
canvas {
    border: 1px solid #ccc;
}
```

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script>
<canvas id="c" width="600" height="600"></canvas>
```

Answer: 
It's a bit tricky but can be solved using a temporary canvas. So you first render the path using a solid color fill on the temporary canvas, then copy it to the main canvas like this:

```
//create temporary canvas
var tmpCanvas = document.createElement("canvas");
tmpCanvas.width = canvas.width;
tmpCanvas.height = canvas.height;
var tmpCtx = tmpCanvas.getContext("2d");

//remember the original render function
var pathRender = fabric.Path.prototype.render;

//override the Path render function
fabric.util.object.extend(fabric.Path.prototype, {
  render: function(ctx, noTransform) {

    var opacity = this.opacity; 

    //render the path with solid fill on the temp canvas
    this.opacity = 1;
    tmpCtx.clearRect(0, 0, tmpCanvas.width, tmpCanvas.height);
    pathRender.apply(this, [tmpCtx]);
    this.opacity = opacity;

    //copy the path from the temp canvas
    ctx.globalAlpha = opacity;
    ctx.drawImage(tmpCanvas, 0, 0);

  }
});

```

See plunker here: <https://plnkr.co/edit/r1Gs2wIoWSB0nSS32SrL?p=preview>
Jetic,

You are almost finished your logic. Instead of using "opacity" use rgba:

```
 canvas.getObjects().forEach(o => {
    o.fill = 'rgba(255, 0, 0, 0.5)';
    o.stroke = 'rgba(255, 0, 0, 0)';
  //  o.opacity = 0.5;
   });
  canvas.renderAll();

```