fabric.js: 如何用笔画画出独特的透明形状?
fabric.js: How to make a unique, transparent shape with stroke?
我想用 fabric.js 自由绘制形状。轮廓是,比如说,20px(这样用户就可以清楚地看到它)。
用户绘制完成后,形状应填充与轮廓相同的颜色。
整个东西应该是半透明的。不幸的是,这会导致轮廓和填充之间的重叠变得不那么透明,并在形状上绘制出奇怪的 "inner outline"。
有没有办法让形状独特的半透明?
也许一个技巧是:在用户绘制完形状后,"widen" 将形状减去轮廓粗细的一半并将轮廓粗细设置为 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>
杰蒂奇,
你的逻辑差不多完成了。而不是使用 "opacity" 使用 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();
这有点棘手,但可以使用临时 canvas 解决。因此,您首先在临时 canvas 上使用纯色填充渲染路径,然后像这样将其复制到主要 canvas:
//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
在 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 的回答中的临时 canvas 。对于我以前的 fabric.js 1.5.0,Janusz 的回答解决了这个问题。
我想用 fabric.js 自由绘制形状。轮廓是,比如说,20px(这样用户就可以清楚地看到它)。
用户绘制完成后,形状应填充与轮廓相同的颜色。
整个东西应该是半透明的。不幸的是,这会导致轮廓和填充之间的重叠变得不那么透明,并在形状上绘制出奇怪的 "inner outline"。
有没有办法让形状独特的半透明?
也许一个技巧是:在用户绘制完形状后,"widen" 将形状减去轮廓粗细的一半并将轮廓粗细设置为 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>
杰蒂奇,
你的逻辑差不多完成了。而不是使用 "opacity" 使用 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();
这有点棘手,但可以使用临时 canvas 解决。因此,您首先在临时 canvas 上使用纯色填充渲染路径,然后像这样将其复制到主要 canvas:
//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
在 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 的回答中的临时 canvas 。对于我以前的 fabric.js 1.5.0,Janusz 的回答解决了这个问题。