how to make a hole through only overlay Rectangle using fabric js? - fabricjs

I am working on image cropper using fabric js version 1.7.22.
As usually, every cropper display black transparent overlay over the image (where image look like dull), and also display one Rect. (crop Area where image look full with color).
we can create this functionality using fabric js with background image and fabric.Rect object.
My problem is that when I use GlobalCompositeOperation with destination-out property to fabric.Rect object. It will make hole through canvas.
In simple word :
when I add globalCompositeOperation to destination-out, it will make hole through canvas also.
Expected result of canvas:
Current Result of canvas:
I have made one codepen for demonstration :
https://codepen.io/mayurkukadiya0/pen/zYYWOGL?editors=0110
I have found one codepen also for do same but they are add multiple canvas for display image in separate layer and rect and overlay in separate layer
Is there any way to do this without add external any canvas or css image behind canvas ?
Here is that reference : https://codepen.io/s0nnyv123/pen/eravaN

try using setOverlayImage
here'a demonstration, based on your codepen
var canvas = new fabric.Canvas('canvas', {preserveObjectStacking: 'true'});
canvas.setHeight(300);
canvas.setWidth(300);
canvas.setOverlayImage('https://images.pexels.com/videos/856973/free-video-856973.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500', canvas.renderAll.bind(canvas), {
top: 0,
left: 0,
width: 300,
height:300,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
selectable: false,
globalCompositeOperation: 'destination-atop',
});
var overlay = new fabric.Rect({
left: 0,
top: 0,
width: 300,
height: 300,
fill: '#00000050',
selectable: false,
globalCompositeOperation: 'source-over'
});
canvas.add(overlay);
var rect = new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
fill: '#451245',
globalCompositeOperation: 'destination-out'
});
canvas.add(rect);
canvas.renderAll();

Related

Fabric.js: dashed line with clipping looks different on large canvas size

I use a clipping area with fabric.js to create a graph. However, the grid lines look different on a canvas size bigger than about 1000px. It only occurs with imageSmoothingEnabled: false. See the image. Note: the size of the frames have nothing to do with the size of the canvas.
To create the grid lines, I create one original that is wider than the area, and then clone them. The cloned lines are added to the clipArea object. Here is the relevant code.
HTML:
<canvas id="canvas" width="966" height="520"></canvas>
Javascript:
var canvas = new fabric.StaticCanvas('canvas', {
imageSmoothingEnabled: false
});
var rect = new fabric.Rect({
originX: 'left',
originY: 'top',
fill: 'transparent',
width: x1-x0,
height: y1-y0
});
var clipArea = new fabric.Group([rect], {
originX: 'left',
originY: 'top',
width: canvas.width*2,
height: canvas.height*2,
left: -canvas.width,
top: -canvas.height
});
rect=clipArea.item(0)
rect.set({left: x0,top: y0});
clipArea.clipPath = rect;
canvas.add(clipArea);
var yline = new fabric.Line([0, 0, 1200, 0], {
originX: 'left',
originY: 'center',
stroke: myFrameColor,
strokeWidth: 2,
strokeDashArray: [1, 3.4]
});
// clipArea.add(yline)
Of course I could draw the gridlines in a different way without using clipping, but I need a clipping area anyway. And I'd like to understand why this is happening.

How to force proportional scaling using Fabricjs?

There has been multiple changes in the Fabricjs API that affect the way scaling points behave. One of the latest changes in version 4 (http://fabricjs.com/v4-breaking-changes) states that uniformScaling is now the way to go to force proportional scaling.
This is my test canvas:
<canvas id="c" width="400" height="400" style="border:1px solid #ccc"></canvas>
And this is my simple code snippet:
const canvas = (this.__canvas = new fabric.Canvas("c"));
canvas.uniformScaling = true;
const Add = () => {
const rect = new fabric.Rect({
left: 100,
top: 100,
fill: "yellow",
width: 200,
height: 100,
stroke: "lightgreen",
});
canvas.add(rect);
canvas.setActiveObject(rect);
};
Add();
See a codepen illustrating the issue.
Why are the control points for resizing horizontally and vertically still there? What am I doing wrong?
The uniformScaling property only determines the behavior of the corner resize controls. You can hide the side controls using the setControlsVisibility method.
http://fabricjs.com/docs/fabric.Object.html#setControlsVisibility
fabric.Rect.prototype.setControlsVisibility({
ml: false,
mt: false,
mr: false,
mb: false
});

Create a clipping mask using an object in Fabric.js

I'm trying to create a T-Shirt editor using Fabric. I set a shirt as a background image on the canvas. Now I'm trying to get an area in the middle of the T-shirt that will act as a clipping mask. I only want objects that are inside this area to be visible.
Here's my code: http://jsfiddle.net/mtb2p3Lx/4/
var canvas = new fabric.Canvas('c');
// set background
fabric.Image.fromURL('https://qstomizr.s3.amazonaws.com/11102-9LDAQLKA1585254870.5083.jpg', (img) => {
canvas.setBackgroundImage(img, null, {
originX: 'center',
originY: 'center',
top: canvas.getCenter().top,
left: canvas.getCenter().left,
stroke: 'black',
strokeWidth: 1,
});
canvas.renderAll();
});
// set masking area
var area = new fabric.Rect({
originX: 'center',
originY: 'center',
top: this.canvas.getCenter().top,
left: this.canvas.getCenter().left + 10,
width: 250,
height: 300,
selectable: false,
fill: 'transparent',
stroke: 'black',
strokeWidth: 2,
});
canvas.add(area)
// set example rect
var rect = new fabric.Rect({
originX: 'center',
originY: 'center',
top: this.canvas.getCenter().top + 50,
left: this.canvas.getCenter().left + 150,
height: 100,
width: 100,
fill: 'pink',
});
canvas.add(rect)
I tried adding a clip path to the area rect, also tried playing around with globalCompositeOperation, but I couldn't get anything to work without having to sacrifice the background image.
Is there a way to get the transparent area rect to act as a clipping mask for the other objects in the canvas?
As you can see on this site https://printio.ru/tees/new_v2. For implementing background image was used img tag without setBackgroundImage. And I make an example for you here
https://jsfiddle.net/RamanNikitsenka/4suna7yo/1/

Image clipping with visible overflow in Fabricjs

I want to clip image, BUT default clipping behaviour just hiding a part of image which out of border. Is there a way to make it visible and set less opacity for overflowed content?
There's one of old clipping examples I told about. It also using lodash to bind clip name to object:
return _.bind(clipByName, pug)(ctx)
Is there a way to replace this functionality with vanilla es5?
I found unclear solution. Again.
Background color of canvas could make an opacity and background image could be clipping object (w/o clipping by itself).
Also, loaded image shoul define globalCompositeOperation set to source-atop.
var canvas = new fabric.Canvas('c');
var clipingRect = new fabric.Rect({
originX: 'left',
originY: 'top',
top: 50,
left: 50,
height: 300,
width: 300,
fill: 'white',
selectable: false
});
canvas.backgroundColor = 'rgba(255,255,0,0.5)';
canvas.setBackgroundImage(clipingRect);
fabric.Image.fromURL('http://placeimg.com/640/480/any', function(fimg) {
canvas.add(fimg.set({
left: 0,
top: 0,
width: canvas.getWidth(),
height: canvas.getHeight(),
globalCompositeOperation: 'source-atop'
}));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.12/fabric.min.js"></script>
<canvas id="c" width="400" height="400"></canvas>

Detect fabric js object edges and avoid overlap

I have a fabric triangle
var fabObj = new fabric.Triangle({
left: 250,
top: 250,
fill: 'white',
width: 60,
height: 60,
name:'triangle',
borderColor: '#f0000',
cornerSize: 8,
transparentCorners: true,
hasControls:true,
lockScalingX:true,
lockScalingY:true
});
$scope.canvas.add(fabObj);
$scope.canvas.setActiveObject(fabObj);
$scope.canvas.renderAll();
It creates the triangle like following
I want another triangle to fit on either side but could not overlap each other
Have tried this code but it only detect corners (square boundary of triangle )
https://stackoverflow.com/a/31153459/3377733
Please refer to this following fiddle
http://jsfiddle.net/m0jjc23v/23/
Fabric.js is not build to handle such scenarios. It's better to use Matter JS http://brm.io/matter-js/
They do handle all physics properties.

Resources