Javascript fabric.js:如何使用笔划制作独特、透明的形状?

Javascript fabric.js:如何使用笔划制作独特、透明的形状?,javascript,transparency,fabricjs,opacity,outline,Javascript,Transparency,Fabricjs,Opacity,Outline,我想用fabric.js自由绘制形状。比如说,轮廓是20px(这样用户就能清楚地看到) 用户绘制后,形状应填充与轮廓相同的颜色 整个事情应该是半透明的。不幸的是,这会导致轮廓和填充之间的重叠变得不那么透明,并在形状上绘制一个奇怪的“内部轮廓” 有没有一种方法可以使形状独特地半透明 也许有一个技巧是:用户绘制形状后,将形状“加宽”为轮廓厚度的一半,并将轮廓厚度设置为1。那可能吗 有关示例,请参见本章或下文 var canvas=newfabric.canvas('c'{ isDrawingMod

我想用fabric.js自由绘制形状。比如说,轮廓是20px(这样用户就能清楚地看到)

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

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

有没有一种方法可以使形状独特地半透明

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

有关示例,请参见本章或下文

var canvas=newfabric.canvas('c'{
isDrawingMode:true,
});
canvas.freeDrawingBrush.width=10;
canvas.freeDrawingBrush.color='rgb(255,0,0)';
on('mouse:up',function(){
canvas.getObjects().forEach(o=>{
o、 填充='rgb(255,0,0)';
o、 不透明度=0.5;
});
canvas.renderAll();
})
画布{
边框:1px实心#ccc;
}

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();
杰蒂克

你的逻辑差不多完成了。使用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();

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

//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:

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

//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:

在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的答案解决了这个问题。

在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的答案解决了这个问题。

谢谢,我也考虑过同样的问题,但这样,在绘制形状后轮廓消失了(笔划alpha 0)。这个形状看起来比用户预期的要“小”。谢谢,我也这么认为,但这样,在绘制形状后轮廓消失了(笔划alpha 0)。这个形状看起来比用户预期的“小”。非常感谢!这正是我的意思。非常感谢!这正是我的意思。