Fabric.js inner shadow (improvise)

Natan Cabral
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 shadow
var 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

--

--

Natan Cabral

Full Stack Developer | Dev Java, Node.js, TypeScript, React.js, Vue.js, Express.js, Next.js, Rest API, Laravel, Databases, MongoDB, Unix distro and Open Source