Fabric.js inner shadow (improvise)
2 min readApr 2, 2021
Demo/sample:
Explanation
// -----const createObjectInnerShadow = () => {let offset = 10;
let object = canvas.getActiveObject();// set first object
if( object === undefined || object === null ){
window.alert('add and select a object');
return;
}const setAngle = ( elements, angle, multiplier ) => {
if( angle > 0 ){
const group = new fabric.Group(elements);
group.rotate( angle === undefined ? 0 : angle * multiplier ); // 1|-1
group.destroy()
canvas.renderAll();
}
}// step 1const { angle, scaleX, scaleY } = object;
// set to angle = 0 (reset)
setAngle( [object], angle, -1 );
// set to scale 1 (reset)
if( scaleX != 1 || scaleY != 1 ){
offset = 0;
object.set({
scaleX: 1,
scaleY: 1,
});
}// step 2const { width, height, left, top } = object;
const rect = new fabric.Rect({
typeName: 'Rect',
width: width + ( offset * 2 ),
height: height + ( offset * 2 ),
left: left - offset,
top: top - offset,
fill: "black",
shadow: {
color: "rgba(0,0,0,1)",
blur: 10,
offsetX: 0,
offsetY: 0,
},
});// step 3 - apply inverted maskvar clipOfObject = clone( object );
rect.clipPath = clipOfObject;
rect.clipPath.set({
typeName: 'ClipPath',
inverted: true, // THE MAGIC
left: ( rect.clipPath.width / 2 ) * -1,
top: ( rect.clipPath.height / 2 ) * -1,
});
// step 4 - apply another mask to maker inner shadowvar clipOfObjectFinal = clone( object );
const clipFinal = new fabric.Group([rect]);
clipFinal.typeName = 'GroupShadow';
clipFinal.clipPath = clipOfObjectFinal;
clipFinal.clipPath.set({
typeName: 'ClipPath',
left: ( rect.clipPath.width / 2 ) * -1,
top: ( rect.clipPath.height / 2 ) * -1,
});// add
canvas.add(clipFinal);// set back scale
if( scaleX != 1 || scaleY != 1 ){
[object,clipFinal].map( (el) => {
el.set({
scaleX: scaleX,
scaleY: scaleY,
});
});
}
// set back angle
setAngle( [object,clipFinal], angle, 1 );// render all
canvas.renderAll();}const clone = (object) => {if (object === undefined || object === null || typeof object !== "object")
return object
else
return Object.assign(Object.create(Object.getPrototypeOf(object)), object);}
See demo: https://github.com/natancabral/fabric-js-inner-shadow