Zoom issue with latest version of library - fabricjs

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.

Related

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
});

Setting Control Visibility for Drawn Objects

I have a fabricjs canvas with a button that toggles drawing on and off. How can I apply the custom controls to any/all drawn objects that I draw; for example, I'd like to select any of the lines that I draw and only be able to rotate them. I've read the example but must be missing something. How would I accomplish this?
JSFiddle of what I'm working with now
Use cornerStyle to change corner style(rect/circle) and setControlsVisibility to set visibility of controls.
DEMO
var canvas = this.__canvas = new fabric.Canvas('canvas', {
backgroundColor: 'white',
centeredScaling: true,
isDrawingMode: true
});
fabric.Object.prototype.cornerStyle = 'circle';//default rect
fabric.Object.prototype.setControlsVisibility({
tl:false, //top-left
mt:false, // middle-top
tr:false, //top-right
ml:false, //middle-left
mr:false, //middle-right
bl:false, // bottom-left
mb:false, //middle-bottom
br:false //bottom-right
})
$("#drawButton").click(function() {
canvas.isDrawingMode = !canvas.isDrawingMode;
var val = canvas.isDrawingMode ? 'selection' : 'pen_tool';
$("#select").text(val);
});
canvas {
border:1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js"></script>
<canvas id="canvas" height="400" width="400"></canvas>
<button class="btn" id='drawButton' value="True"><span><i id="select" class="material-icons">selection</i></span></button>

Fabricjs textbox for large text content stuck in first line

In fabricjs textbox if text content(no space) is larger than the textbox width it won't go to next line, it stuck at first line. So that I get the content width using text:changed event and try to press enter programmatically if content is greater than textbox width but its not working. Is there any other way?
I don't want to override fabricjs default method for breakwords it has other conflicts and cursor get misplaced.
var canvas = new fabric.Canvas('c');
var text1 = new fabric.Textbox('Text', {
left: 10,
top: 20,
width: 300
})
canvas.add(text1);
canvas.on('text:changed', function(e) {
if (e.target.width > 300) {
console.log("text over width");
$('#canvas').trigger(jQuery.Event('keypress', {
keyCode: 87,
which: 13
}));
}
});
canvas{
border:1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/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>

Fabric JS canvas objects below remote image not selectable

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

Resources