无论如何在FabricJS中为透明对象添加阴影?我已经使用了set fill transparent和之后的sethadow。但通常无法看到阴影,因为对象是透明的。
答案 0 :(得分:1)
在绘制带有阴影的对象时,可以使用clip path完成此操作。为此,您可以使用FabricJS子类化生成阴影的对象类型,并重写_render
函数以设置一个剪切路径,该路径包括阴影掉落的区域,但不包括对象本身。理想情况下,这会重用实际绘制对象的代码。
fabric.BoxShadow = fabric.util.createClass(fabric.Rect, {
shadowColor: undefined,
shadowBlur: 0,
shadowOffsetX: 0,
shadowOffsetY: 0,
initialize(options) {
this.callSuper('initialize', options);
// Note: the way I have implemented this, the shadow settings cannot be changed after the object has been created.
this._shadow = new fabric.Shadow({
color: this.shadowColor,
blur: this.shadowBlur,
offsetX: this.shadowOffsetX,
offsetY: this.shadowOffsetY
});
},
_render: function(ctx) {
ctx.save();
// set clip path
let [offsetX, offsetY, blur] = [this.shadowOffsetX,
this.shadowOffsetY,
this.shadowBlur
];
let [top, left] = [this.width / -2, this.height / -2];
let region = new Path2D();
// The outer rectangle for our clipping path completely encompases the object and its shadow
let bounds = {
t: Math.min(top, top + offsetY - blur),
l: Math.min(left, left + offsetX - blur),
b: Math.max(top + this.height, top + this.height + offsetY + blur),
r: Math.max(left + this.width, left + this.width + offsetX + blur),
};
region.rect(bounds.l, bounds.t, bounds.r - bounds.l, bounds.b - bounds.t);
// now we subtract the actual object from our clipping path
// Note: we have to add beginPath function because the base class render code is going to treat this likc a CanvasRenderingContext2D instead of a Path2D
region.beginPath = function() { };
this.callSuper('_render', region);
ctx.clip(region, "evenodd");
// Fabric draws shadows, oddly enough, around the entire area rendered within this function. I haven't figured out the correct function to override to get our clip path to work with the normal fabric rendering pipeline
this.shadow = this._shadow;
// leverage the FabricJS shadow sizing logic
this._setShadow(ctx);
this.callSuper('_render', ctx);
this.shadow = undefined;
ctx.restore();
},
_renderPaintInOrder: function(ctx) {
if (ctx instanceof CanvasRenderingContext2D) {
this.callSuper('_renderPaintInOrder', ctx);
}
}
});
(function() {
let canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
canvas.add(new fabric.Rect({
top: 40,
left: 40,
width: 100,
height: 100,
fill: 'lightblue'
}));
canvas.add(
new fabric.BoxShadow({
rx: 10,
top: 10,
left: 10,
width: 100,
height: 100,
shadowColor: 'black',
shadowBlur: 4,
shadowOffsetX: 3,
shadowOffsetY: 3
})
);
canvas.setWidth(document.body.clientWidth);
canvas.setHeight(document.body.clientHeight);
})();
html {
height: 100%;
}
body {
height: 100%;
}
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.js"></script>
</head>
<body>
<canvas id="c"></canvas>
</body>
</html>
答案 1 :(得分:0)
我认为FabricJS API没有阴影 - 无形状选项。
但是您可以使用本机html5画布轻松创建阴影,然后使用该本机画布作为Fabric.Image对象的图像源。
使用原生html5画布,你可以创建一个没有它的源形状的阴影:
仅在本机html5画布上绘制阴影的示例代码:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var shadowBlur=8;
var x=shadowBlur;
var y=shadowBlur;
var width=100;
var height=65;
canvas.width=width+shadowBlur*2;
canvas.height=height+shadowBlur*2;
// draw the shadowed shape
ctx.shadowColor='black';
ctx.shadowBlur=8;
ctx.fillRect(x-ctx.shadowOffsetX,y,width,height);
// always clean up! -- undo shadowing
ctx.shadowColor='rgba(0,0,0,0';
// use compositing to remove the shape
// (leaving just the shadow);
ctx.globalCompositeOperation='destination-out';
ctx.fillRect(x,y,width,height);
// always clean up! -- set compositing to default
ctx.globalCompositeOperation='source-over';
&#13;
body{ background-color:white; }
#canvas{border:1px solid red; }
&#13;
<canvas id="canvas" width=512 height=512></canvas>
&#13;
使用原生html5画布作为图像源创建Fabric.Image的示例:
// where "canvas" is a reference to an html5 canvas element
var myFabricImage=new fabric.Image(canvas, { left:0, top:0 });