Basically I'm trying to reproduce this behavior for locking/unlocking item in fabricjs:
https://www.dropbox.com/s/undtb1v4kxqcbi8/ScreenFlow-lock.mp4?dl=0
=> I want to be able to lock an item, but still be able to clic and drag a selection from it, but still being able to select it (but not moving/scaling,etc).
I can lock an item and be able to start a drag selection from it:
https://jsfiddle.net/og09g5ex/
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 150,
height: 150,
transparentCorners: false,
evented:false,
selectable:false});
But then I can't select it because I use "evented=false".
Does anyone has an idea?
Many thanks!
This is possible but it is not easy. There is a findTarget in the canvas.class.js file that you will need to modify so that when you are clicking on the object you select it but when you are clicking then dragging it does not select it. naively fabric does not have this concept and modifying this function is the only way to get it. Hope that helps!
Related
I want to add class to the textbox, how could I add that using fabric.js
canvas.set('class','textbox1');
Right now here i'm using canvas.set('class','textbox1'); for add any class.
Thanks In Advance.
I don't think it is necessary to use a class on a canvas element. Fabric.js has methods for their TextBox object with which you can style your component. The same goes for the Canvas object itself.
http://fabricjs.com/docs/fabric.Canvas.html
http://fabricjs.com/docs/fabric.Textbox.html
Fabric doesn't appear to have a Class option and CSS has no effect on canvas objects anyway.
So, if you wanted to set the background color of your TextBox you would do the following:
var t1 = new fabric.Textbox('My Text', {
width: 200,
top: 5,
left: 5,
fontSize: 16,
textAlign: 'center',
backgroundColor:'rgb(200,200,200)'
});
I am looking for a way to space (and move in general) objects inside a group regardless of their transformation.
In the small example i have made below, you will see 2 circles and I am attempting to space them by a certain factor.
It is ok until I rotate or resize the group and it is still ok the very first time the coordinates are changed after a transformation but calling the same function twice while the spacing is still correct, the group starts jumping all over the places..
I am using Fabric JS version: 1.7.7
Here is a sample:
https://jsfiddle.net/u0patgck/
console.clear();
var canvas = new fabric.Canvas('root');
var circles = [];
circles.push(new fabric.Circle({id: "circle1", radius: 20, fill: 'green', left: 150, top: 100}));
circles.push(new fabric.Circle({id: "circle2", radius: 20, fill: 'green', left: 200, top: 100}));
g = new fabric.Group(circles);
//once circles are added to group their coordinates change so I store their new original base coordinates in custom variables
g.forEachObject(function(obj){
obj.originalLeft = obj.getLeft();
obj.originalTop = obj.getTop();
}, g);
canvas.add(g);
canvas.renderAll();
function moveCircles(){
var space = parseFloat(document.getElementById("spacingPixels").value);
g.forEachObject(function(obj){
switch (obj.id){
case "circle1":
obj.setLeft(obj.originalLeft - space)
break;
case "circle2":
obj.setLeft(obj.originalLeft + space)
break;
default:
}
})
g.addWithUpdate();
canvas.renderAll()
}
Steps to Reproduce:
Test 1 (ok):
Click the "Move Circles" button as many times you want (circles coordinates are recalculated and the group is not "misbehaving".
Test 2 (ok first time but not second time):
Rotate the group first.
Click the move circles button ONE time (all is still good)
Click the move circles button another time (you will see the group starts moving by itself around the canvas).
Expected Behaviour:
The group should not move around or change the order of the objects inside.
The group moves erratically.
At the moment I am caching the transformations manually and restoring them after changing the coordinates (like below)
https://jsfiddle.net/0tdg1dof/
var a = {scaleX: g.getScaleX(), scaleY: g.getScaleY(), skewX: g.getSkewX(), skewY: g.getSkewY(), flipX: g.getFlipX(), flipY:g.getFlipX(), angle: g.getAngle()};
fabric.util.resetObjectTransform(g);
g.addWithUpdate();
g.setScaleX(a.scaleX);
g.setScaleY(a.scaleY);
g.setSkewX(a.skewX);
g.setSkewY(a.skewY);
g.setFlipX(a.flipX);
g.setFlipY(a.flipY);
g.setAngle(a.angle);
Is there a better way to do this?
Thank you.
AlessandroDM, I believe you did right solution, because you are manipulating just only group object. If you will not manipulate (restore) group objects (parent) you will need to do manipulation each child inside the group like angle, scale, etc. Also, you have one minor bug, if you will rotate group, and after that resize it (not diagonal controls, scaleX should not be equal to scaleY) and then click "Move Circles" your group will behave as you described in Test 2. In order to fix that you will need to set scaleX and scaleY values after all your values which you want to set:
var a = {scaleX: g.getScaleX(), scaleY: g.getScaleY(), skewX: g.getSkewX(), skewY: g.getSkewY(), flipX: g.getFlipX(), flipY:g.getFlipX(), angle: g.getAngle()};
fabric.util.resetObjectTransform(g);
g.addWithUpdate();
g.setSkewX(a.skewX);
g.setSkewY(a.skewY);
g.setFlipX(a.flipX);
g.setFlipY(a.flipY);
g.setAngle(a.angle);
g.setScaleX(a.scaleX);
g.setScaleY(a.scaleY);
It is not a fabricjs bug setting scale after all manipulations, even native HTML5 canvas required scaling after all manipulations.
I have lines in fabricjs which may be at an angle. I want the user to be able to select them, but the selection outline is a rectangle with corners at the ends of the line. The user should only be able to select the line when the cursor is over the line, or at least within a few pixels of it. So I use the mousemove event to set the cursor when it's over the line and will do other things when he clicks on it.
But fabricjs only lets me set the cursor when selectable is true and then the user gets this blue rectangle around the line, which is not helpful. How can I get rid of this rectangle, or have the cursor change when selectable is false?
First, add perPixelTargetFind and targetFindTolerance to fabric.Canvas instance.
var canvas = new fabric.Canvas('canvas', {
perPixelTargetFind: true,
targetFindTolerance: 5
});
Then, add padding to fabric.Line instance.
var line = new fabric.Line([50, 50, 250, 250], {
padding: 5
});
canvas.add(line);
The targetFindTolerance numeric value is only respected by diagonal lines as far as I can tell. The padding numeric value is only respected by horizontal lines as far as I can tell. Both targetFindTolerance and padding must be set for either type of line to respect the rule. It's unclear whether this is buggy or intentional behavior.
This should get you fairly close, if I understood you correctly:
Here's the JavaScript code:
var canvas = new fabric.Canvas('canvas', {
width: 300,
height: 300,
perPixelTargetFind: true,
selection: false,
hoverCursor: 'default'
});
line = new fabric.Line([50, 50, 250, 250], {
strokeWidth: 5,
stroke: 'black',
originX: 'center',
originY: 'center',
hasControls: false,
hasBorders: false,
targetFindTolerance: 8
});
canvas.add(line);
And finally the all important JSFiddle, https://jsfiddle.net/rekrah/tvcufesq/.
Let me know if you have any more questions. Always happy to help!
try add padding and targetFindTolerance to line.
I was trying to add to canvas item which will be dragable but not selectable so I did like this
var canvas = new fabric.Canvas('root');
canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));
canvas.add(new fabric.Circle({ radius: 30, fill: '#5f5', top: 160, left: 100 }));
canvas.item(0).hasControls = canvas.item(0).hasBorders = false;
Now I'm not able to select as a group element 0 (this is ok!) but when I'm selecting group which contains also item 1 then item 0 is also selected (this is not good). How can I fix it?
I know this question is very old but:
canvas.item(0).hasControls = canvas.item(0).hasBorders = false;
Will make the object with invisible border and invisible controls, so it looks like you are not selecting it, but you are still doing and not drawing any controls.
There is no way to make an object unselectable BUT draggable.
If you cannot select it ( setting .selectable=false), you cannot drag it.
When an object is in a selection group its border get drawn anyway, whatever setting is on .hasBorders.
Currently, whenever I set the text of a fabric.Text object dynamically, using the set('text', 'some random text') function, the width seems to grow bi-directionally i.e from both the left and right side.
Is there any way to make it grow from either the left or right side only.
I have achieved this by explicitly calculating the top_left_x, top_left_y, top_right_x, top_right_y and using some arithmetic logic for the same.
But what is there any internal fabricJS property (or something similar) by which this can be achieved.
For ex: In the Kitchensink demo, if you add a new Text object and modify the text in the lower-right text area, you will see that the text grows from the right while its left side remains fixed. This is exactly what I wish to achieve.
Any suggestions anyone?
This happened because the default origin point is the center of object. So you need set the "originX" to "left". As you can see in the Kintchensink source file:
document.getElementById('add-text').onclick = function() {
var textSample = new fabric.Text(text.slice(0, getRandomInt(0, text.length)), {
left: getRandomInt(350, 400),
top: getRandomInt(350, 400),
fontFamily: 'helvetica',
angle: getRandomInt(-10, 10),
fill: '#' + getRandomColor(),
scaleX: 0.5,
scaleY: 0.5,
fontWeight: '',
originX: 'left',
hasRotatingPoint: true
});
canvas.add(textSample);
updateComplexity();
};