I am having a situation where I am drawing a ellipse in fabric.js from originX='right' and
afterwards changing it to originX='left'.
What I see is after changing the originX to left and adjusting the left by the following calculation :
ellipse.left -= ellipse.width
I still see a difference in the left positions.
To explain it , I added a fiddle where I added a timeout of 3 seconds before changing the originX. So, please open the fiddle and wait 3 seconds and see how the position changes which ideally shouldn't .
Any mistakes I am doing or any suggestions ?
Code :
var canvas = new fabric.Canvas('paper');
var ellipse = new fabric.Ellipse({
left: 300,
top: 10,
rx: 145,
ry: 65,
strokeWidth: 4,
stroke: 'blue',
fill: '',
originX: 'right',
originY: 'top'
});
canvas.add(ellipse);
canvas.renderAll();
var log = document.getElementById('log');
log.innerHTML = ellipse.left;
//changing the origin
setTimeout(function() {
ellipse.originX = 'left';
ellipse.left -= ellipse.width;
canvas.renderAll();
log.innerHTML += ', ' + ellipse.left;
}, 3000);
Since, the ellipse's stroke has some width to it, hence, you would also need to exclude that, from ellipse's left position, like so ...
ellipse.left -= ellipse.width + ellipse.strokeWidth;
or
ellipse.left = ellipse.left - ellipse.width - ellipse.strokeWidth;
Here is the revised version of your code ...
var canvas = new fabric.Canvas('paper', {
isDrawingMode: false
});
var ellipse = new fabric.Ellipse({
left: 300,
top: 10,
rx: 145,
ry: 65,
strokeWidth: 4,
stroke: 'blue',
fill: false,
originX: 'right',
originY: 'top'
});
canvas.add(ellipse);
canvas.renderAll();
var log = document.getElementById('log');
log.innerHTML = ellipse.left;
//changing the origin
setTimeout(function() {
ellipse.originX = 'left';
ellipse.left -= ellipse.width + ellipse.strokeWidth;
canvas.renderAll();
log.innerHTML += ', ' + ellipse.left;
}, 3000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.11/fabric.min.js"></script>
<canvas id="paper" width="400" height="400" style="border:1px solid #ccc"></canvas>
<div id='log'></div>
Related
I recently started to work with fabricjs, and I have a question about connectivity object. i do creating sample demo for connectivity from parent object to child object connect with arrow. I got sample demo http://kpomservices.com/HTML5CanvasCampaign/campaign.html. This code should work with fabric 1.4.2.A similar code is possible for the version 2.3.3 not work.
Error functions.js:963 Uncaught TypeError: c.setAngle is not a function
code
function makeArrow(centerpt, left, top, line) {
var c = new fabric.Triangle({
width: 10,
height: 10,
left: left,
top: top,
//selectable: false,
strokeWidth: 3,
fill: 'grey',
opacity: 1,
stroke: 'grey',
originX: 'center',
originY: 'center'
});
c.hasBorders = c.hasControls = false;
c.angle = 90;
c.line = line;
var dx = left - centerpt.x;
var dy = top - centerpt.y;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
c.setAngle(angle + 90);
c.setCoords();
c.name = 'ep';
line.ep = c;
c.line = line;
return c;
}
Build doesn't have setter/getter (optional). You can make your build here with Named accessors. If you want to set angle you can use
obj.angle = text;
//or
obj.set({
angle:angle
});
//or
obj.set('angle', angle);
DEMO
var canvas = new fabric.Canvas('c');
var triangle = new fabric.Triangle({
left: 150,
top: 50,
width: 300,
height:200,
fill:'',
stroke:'red'
})
canvas.add(triangle);
triangle.set('angle',40);
//triangle.angle = 40;
//triangle.set({angle : 40})
canvas{
border:1px solid #000;
}
<script type="text/javascript" src="
https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
My fiddle: http://jsfiddle.net/yeftc60v/1/
So I'm trying to get the obj.left to be based on the left side(wall) of the group instead of the center. So right now, when I try to get the left of an object, if it's on the left side, it will return a negative number.
I've tried both setOriginY and setOriginX but they don't have any effect.
I'm working around this by doing some maths based on the group's width.
Right now if you hit the "clone" button, the left values read negative values (-100.5 and -0.5). Instead they should be 0 and 99.5(I think), respectively.
Unfortunately, any active group's origin x and y will always be at center. This won't take originX and originY property into consideration, hence setting setOriginX and setOriginY won't have any effect.
To get around this, you need to manually calculate the object's top and left position respective to the selected group, like so ...
let objLeft = obj.left + (active.width / 2);
let objTop = obj.top + (active.height / 2);
ᴅᴇᴍᴏ
var canvas = new fabric.Canvas('c');
var rect = new fabric.Rect({
left: 50,
top: 50,
fill: "#FF0000",
stroke: "#000",
width: 100,
height: 100,
strokeWidth: 1,
opacity: .8
});
var rect1 = new fabric.Rect({
left: 150,
top: 150,
fill: "#FF0000",
stroke: "#000",
width: 100,
height: 100,
strokeWidth: 1,
opacity: .8
});
canvas.add(rect);
canvas.add(rect1);
function clone() {
let active = canvas.getActiveGroup();
if (active) {
active.forEachObject(obj => {
let clone = obj.clone();
// get object's left & top relative to the group
let objLeft = obj.left + (active.width / 2);
let objTop = obj.top + (active.height / 2);
clone.setLeft(objLeft + active.left);
clone.setTop(objTop + active.top);
canvas.add(clone);
});
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.11/fabric.min.js"></script>
<canvas id="c" width="300" height="300" style="border: 1px solid black;"></canvas>
<button onclick="clone()">
Clone
</button>
I am working on a fabricjs application & i need to set a inside stroke to object, it means apply stroke to a object without increase it's size.
eg if i apply strokeWidth 20 to 100*100 rect then it's size is also increase but i want if stroke is apply to object then size will also remain same
var recta = new fabric.Rect({
left: 10,
top: 10,
fill: '#000',
width: 100,
height: 100,
});
var rectb = new fabric.Rect({
left: 150,
top: 10,
fill: '#000',
width: 100,
height: 100,
});
canvas.add(recta, rectb);
rectb.set('stroke', '#f00');
rectb.set('strokeWidth', 20);
canvas.renderAll();
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas style="border:#000 1px solid" id="design-canvas" width="500" height="400">
<script type="text/javascript">
canvas = new fabric.Canvas('design-canvas');
</script>
Is there is any way or trick to apply stroke without increase size
Thanks in Advance
Assuming it'd just be for rectangles, The best way would likely be too attach 4 lines which you update the positions based off of that rectangles x, y, width and height. You can then set the stroked width of those lines separately.
The other way would be too simply resize the owning element. Look at this JSFiddle.
var canvas = new fabric.Canvas('c', { selection: false });
var circle, isDown, origX, origY;
canvas.on('mouse:down', function(o){
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
circle = new fabric.Circle({
left: pointer.x,
top: pointer.y,
radius: 1,
strokeWidth: 5,
stroke: 'red',
selectable: false,
originX: 'center', originY: 'center'
});
canvas.add(circle);
});
canvas.on('mouse:move', function(o){
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
circle.set({ radius: Math.abs(origX - pointer.x) });
canvas.renderAll();
});
canvas.on('mouse:up', function(o){
isDown = false;
});
I have got a lot of helps from this site and contributors here, thanks. Now I have a question about the Rectangle in Fabric.js with stroke, as I used it as kind of placeholder for images and text, when I scaled it, the border line width is scaled too, I think it's kind a problem as I want to keep the border width not changed.
var canvas = new fabric.Canvas("c1");
var el = new fabric.Rect({
originX: "left",
originY: "top",
left: 5,
top: 5,
stroke: "#ccc",
strokWidth: 1,
fill: 'transparent',
opacity: 1,
width: 200,
height: 200,
cornerSize: 6
});
canvas.add (el);
canvas.renderAll ();
See example here http://jsfiddle.net/9yb46/, try scale it horizontally. And a image is here too, and see the left border and right border width, supposed as same as top and bottom border, but not:
This can be done so that you can scale independently.
In the scaling event check the width, height and scale factors, set the height and width to the new effective values and reset the scaleX and scaleY.
This quite probably will break other things that are scaled with the object so you'd have to handle those attributes in a similar fashion.
Demo Fiddle.
var canvas = new fabric.Canvas("c1");
var el = new fabric.Rect({
originX: "left",
originY: "top",
left: 5,
top: 5,
stroke: "rgb(0,0,0)",
strokeWidth: 1,
fill: 'transparent',
opacity: 1,
width: 200,
height: 200,
cornerSize: 6
});
el.on({
'scaling': function(e) {
var obj = this,
w = obj.width * obj.scaleX,
h = obj.height * obj.scaleY,
s = obj.strokeWidth;
obj.set({
'height' : h,
'width' : w,
'scaleX' : 1,
'scaleY' : 1
});
}
});
canvas.add (el);
canvas.renderAll ();
First of all you have miss-typed the name of the property in your fiddle : strokWidth - e is missing. But this is not the cause of the problem since the default value for the strokeWidth is 1.
The scaled stroke issue is the expected behavior and what you ask to do is not. Anyway, before you check my code, read here and here and maybe some more here.
Then try this code to help with your needs, this will work perfectly only if you keep the scale ratio of your rectangle as 1:1 (scaleX = scaleY).
This is jsfiddle:
var canvas = new fabric.Canvas("c1");
var el = new fabric.Rect({
originX: "left",
originY: "top",
left: 5,
top: 5,
stroke: "rgb(0,0,0)",
strokeWidth: 1,
fill: 'transparent',
opacity: 1,
width: 200,
height: 200,
cornerSize: 6
});
el.myCustomOptionKeepStrokeWidth = 1;
canvas.on({
'object:scaling': function(e) {
var obj = e.target;
if(obj.myCustomOptionKeepStrokeWidth){
var newStrokeWidth = obj.myCustomOptionKeepStrokeWidth / ((obj.scaleX + obj.scaleY) / 2);
obj.set('strokeWidth',newStrokeWidth);
}
}
});
canvas.add (el);
canvas.renderAll ();
Fabricjs now has a strokeUniform property on fabric.Rect that can be used to prevent the stroke width from mis-transforming.
When you set strokeUniform to false it will scale with the object if true it will match the pixel size of the stroke width.
var el = new fabric.Rect({
originX: "left",
originY: "top",
left: 5,
top: 5,
stroke: "#ccc",
strokWidth: 1,
fill: 'transparent',
opacity: 1,
width: 200,
height: 200,
cornerSize: 6,
strokeUniform: true
});
This Rectangle i have created on canvas using fabicjs , now on change of text box i want to set border width . i tried following but its not working.
image[img] = new fabric.Rect({
top : 100,
left : 100,
width : 50,
height : 50,
fill : '#f55',
stroke : 'black',
strokeWidth : 1
});
Changing Border Width ::
$('#shape_border_size').change(function() {
console.log(' size changed to ' + $(this).val());
var obj = canvas.getActiveObject();
if (!obj)
return;
//obj.set('strokeWidth', $(this).val());
canvas.renderAll();
});
I think your code is fine, don't know why it's not working.
Check this http://jsfiddle.net/hellomaya/kNEaX/3/
var rect = new fabric.Rect({
top: 100,
left: 100,
width: 50,
height: 50,
fill: '#f55',
stroke: 'white',
strokeWidth: 1
});
canvas.add(rect);
canvas.renderAll();
$('#a').click(function () {
rect.set('strokeWidth', 20);
canvas.renderAll();
});
$('#b').click(function () {
rect.set('strokeWidth', 20);
rect.width += 20;
rect.height += 20;
canvas.renderAll();
});