fabric.js:如何用笔画制作独特的透明形状?

时间:2016-11-29 18:31:38

标签: javascript transparency fabricjs opacity outline

我想用fabric.js自由绘制形状。例如,轮廓是20px(这样用户可以清楚地看到它)。

用户绘制完成后,应使用与轮廓相同的颜色填充形状。

整个事情应该是半透明的。不幸的是,这会导致轮廓和填充之间的重叠不那么透明,并为形状绘制一个奇怪的“内部轮廓”。

有没有办法让形状独特地半透明?

也许一个技巧是:在用户绘制形状之后,将形状“加宽”一半的轮廓厚度并将轮廓厚度设置为1.这可能吗?

请参阅此https://jsfiddle.net/4ypdwe9o/或以下的示例。

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>

3 个答案:

答案 0 :(得分:2)

这有点棘手,但可以使用临时画布解决。因此,首先使用临时画布上的纯色填充渲染路径,然后将其复制到主画布,如下所示:

//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);

  }
});

请在此处查看plunker:https://plnkr.co/edit/r1Gs2wIoWSB0nSS32SrL?p=preview

答案 1 :(得分:2)

在fabric.js 1.7.3中,他们有另一个实现。当我使用

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

而不是

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

边界绘制正确,没有重叠。因此,不再需要来自Janusz答案的临时画布。对于我以前的fabric.js 1.5.0,Janusz的答案解决了这个问题。

答案 2 :(得分:1)

Jetic,

你几乎完成了你的逻辑。而不是使用“不透明度”使用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();