Fabric JS canvas objects below remote image not selectable - fabricjs

I'm trying to setup FabricJS but canvas become unselectable below remote images.
I figured it out, that selection area is calculated before images are loaded and then canvas is "pushed" below images, so its objects becomes unselectable. This only occurs when you refresh page. When you enter new link everything is fine.
<body>
<div class="product thumbnail">
<a href="remoteimage">
<img src="remoteimage" alt="1232g" />
1232g
</a>
</div>
<div>
<canvas id="canvas-id"></canvas>
</div>
<script>
$(function() {
var canvas = new fabric.Canvas('canvas-id');
// create a rectangle with angle=45
var circle = new fabric.Circle({
radius: 20, fill: 'red', left: 100, top: 100
});
var triangle = new fabric.Triangle({
width: 20, height: 30, fill: 'blue', left: 50, top: 50
});
canvas.add(circle, triangle);
});
</script>
</body>
How to setup FabricJS properly in this scenario ?

I think this is what you are talking about
var canvas = new fabric.Canvas('c');
var imgElement = document.getElementById('my-img');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 100,
angle: 30,
opacity: 0.85
});
canvas.add(imgInstance);
You can check the documentation here : http://fabricjs.com/fabric-intro-part-1/ in the Images Section

Related

Updating font size from an input to fabric js canvas generated text

i want to update the font size from this
<input value="1" id="fontSize" type="text">
input to
$("#fontSize").on("change", () => {
let fontsize = document.querySelector("#fontSize");
sizeFromInput = fontsize.value;
canvas.getActiveObject().set("fontSize", sizeFromInput);
canvas.renderAll();
});
this is my text generation function in fabric js
$("#typeTool").click(() => {
var textEditable = new fabric.Textbox("ASR Textbox", {
width: 500,
editable: true,
fontFamily: "Delicious_500",
left: 100,
top: 100,
fontSize: 18,
fill: "#000",
});
canvas.add(textEditable);
});
I think your code is working as expected.
Maybe you could use the input event for an instant update as the change event fires in most browsers when content is changed and the element loses focus.
It will not fire for every single change as in the case input event.
https://stackoverflow.com/a/17047588/5646527
var canvas = new fabric.Canvas('c');
canvas.renderAll.bind(canvas);
$("#fontSize").on("change", () => {
let fontsize = document.querySelector("#fontSize");
sizeFromInput = fontsize.value;
var activeObject = canvas.getActiveObject();
if (activeObject) {
activeObject.set("fontSize", sizeFromInput);
}
canvas.renderAll();
});
$("#typeTool").click(() => {
var textEditable = new fabric.Textbox("ASR Textbox", {
width: 50,
editable: true,
left: 10,
top: 10,
fontSize: 18,
fill: "#000",
});
canvas.add(textEditable);
canvas
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fabric#5.2.4-browser/dist/fabric.min.js"></script>
<button id="typeTool">Add Text</button>
<input type="text" id="fontSize" />
<br>
<canvas id="c" width="400" height="400"></canvas>
<br>
<p class="save">
</p>

Fabricjs, selection handles shown but not clickable before selected together with other shapes

I'm trying to develop a vue.js component to draw shapes with fabricjs.
After a rectangle been drawn, it is selectable, but can't be resized or rotated with the selection handle, which is not what I was expecting. I think it has something to do with vue.js 3, because everything works with vue.js 2.
In this demo at JSFiddle, corner handles won't work on rectangles, untill after you have selected the rectangle together with other shapes.
<div id="app">
<canvas ref="c"></canvas>
<div>
<button type="button" #click="add('red')">
Add
</button>
Select the blue rectangle. The corner handles are visible but not working.
Now, click "add“, then select both rectangles. Then just select any single item, now the corner handles are working.
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.2.0/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0/vue.global.js"></script>
var vm = Vue.createApp({
data: () => ({
canvas: null
}),
mounted: function() {
var c = this.$refs.c
this.canvas = new fabric.Canvas(c, {
width: c.clientWidth,
height: c.clientHeight
});
this.add('blue')
},
methods: {
add(color) {
this.canvas.add(new fabric.Rect({
top: 20,
left: 20,
width: 40,
height: 40,
fill: color
}))
}
}
}).mount('#app');
// Select the blue rectangle. The corner handles are visible but not working.
// Now, click "add", then select both rectangles.
// Then just select any single item, now the corner handles are working.
How do I work around this while sticking to vue.js 3?
Fabricjs does not like having the canvas converted to a proxy. One way to get around it is to use a global variable instead of using the data. You can also just remove canvas from the data() declaration, which will make it still accessible throughout the template and code, but not make it reactive.
Example:
var vm = Vue.createApp({
mounted: function() {
var c = this.$refs.c
this.canvas = new fabric.Canvas(c, {
width: c.clientWidth,
height: c.clientHeight
});
this.add('blue')
},
methods: {
add(color) {
this.canvas.add(new fabric.Rect({
top: 20,
left: 20,
width: 40,
height: 40,
fill: color
}))
}
}
}).mount('#app');
<div id="app">
<canvas ref="c"></canvas>
<div>
<button type="button" #click="add('red')">
Add
</button>
Select the blue rectangle. The corner handles are visible but not working.
Now, click "add“, then select both rectangles. Then just select any single item, now the corner handles are working.
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.1.0/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0/vue.global.prod.js"></script>
You can use toRaw(). The function can change proxy object to common object.
add(color) {
toRaw(this.canvas).add(new fabric.Rect({
top: 20,
left: 20,
width: 40,
height: 40,
fill: color
}))
}

How to make Group height same as textbox height in fabric JS while scaling

I have more than one textbox. When I group all textboxes and scale the group horizontally height of group is not increase dynamically and content of textbox get vanish unlike independent textbox which increase height till the content end.
Below code I tried to set same height of group as of textbox but not working. Any Suggestion ?
var canvas = new fabric.Canvas('c');
var text1 = new fabric.Textbox('Text', {
left: 10,
top: 20,
fontSize : 18,
width: 300
})
canvas.add(text1);
var text2 = new fabric.Textbox('If this textbox grouped with above textbox, height will not increase on scaling horizontally and content get vanished but if scalling independently height increase', {
left: 20,
top: 40,
fontSize : 18,
width: 300
})
canvas.add(text2);
canvas.on('object:scaling', function(e) {
/* if(e.target.type == "group"){
var obj=e.target;
obj.height=obj.item(0).height;
obj.width=obj.item(0).width;
}*/
});
canvas{
border:1px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.9/fabric.js"></script>
<canvas id="c" width="400" height="400" style="border:1px solid #000000;"></canvas>

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>

Zoom issue with latest version of library

The below code snippets are identical, except for the version of FabricJS being used.
The first one uses version 1.4.13, the second uses the latest (1.7.3).
When clicking Zoom In on the first version, the black square remains exactly top-left (0, 0). So far, so good.
When doing the same on the second version, the black square "drifts" where you can see the pink background above and to the left of the black square.
Does anyone why this behaviour has changed, is there a workaround or other fix?
var canvas = new fabric.Canvas('c');
canvas.setBackgroundImage('http://placehold.it/640x480/dd0055/?text=FabricJS Demo', canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 0.5,
backgroundImageStretch: false
});
canvas.add( new fabric.Rect({
left: 0,
top: 0,
width:100,
height:100,
fill:"rgb(0,0,0)"
}) );
canvas.renderAll();
$("#btnZoomIn").click(function(){
canvas.setZoom(canvas.getZoom()*1.3);
});
$("#btnZoomOut").click(function(){
canvas.setZoom(canvas.getZoom()/1.3);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.13/fabric.min.js"></script>
<button id="btnZoomIn">ZoomIn</button>
<button id="btnZoomOut">ZoomOut</button>
<br/>
<canvas id="c" width="640" height="480"></canvas>
var canvas = new fabric.Canvas('c');
canvas.setBackgroundImage('http://placehold.it/640x480/dd0055/?text=FabricJS Demo', canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 0.5,
backgroundImageStretch: false
});
canvas.add( new fabric.Rect({
left: 0,
top: 0,
width:100,
height:100,
fill:"rgb(0,0,0)"
}) );
canvas.renderAll();
$("#btnZoomIn").click(function(){
canvas.setZoom(canvas.getZoom()*1.3);
});
$("#btnZoomOut").click(function(){
canvas.setZoom(canvas.getZoom()/1.3);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.3/fabric.min.js"></script>
<button id="btnZoomIn">ZoomIn</button>
<button id="btnZoomOut">ZoomOut</button>
<br/>
<canvas id="c" width="640" height="480"></canvas>
Being the main difference after fabric 1.5 the inclusion of strokeWidth in the object bounding box, i guess that if you initialize the fabric.Rect with strokeWidth: 0 OR with a stroke: 'blue' you will se that the object is not drifting, simply is moving from is left top corner.
What cause the drift is a transparent border that is growing in size.

Resources