7

I just started with fabric.js and I have a (probably beginner) error:

I am using fabric with jquery with the following code:

$(document).ready(function () {

canvas = new fabric.StaticCanvas('scroller');

canvas.add(
  new fabric.Rect({ top: 0, left: 0, width: 140, height: 100, fill: '#f55' })
);

});

This code should draw a 140x100 Rectangle on the canvas. Sadly, only a quarter of the Rectangle appears. If I change the top and left values to higher numbers, more of the Rectangle appears on the canvas.

So it seems, that the canvas origin is not at 0/0, but at sth. higher.

Does someone know how to fix this or what I am doing wrong?

Thanks in advance, McFarlane

kangax
  • 38,898
  • 13
  • 99
  • 135
McFarlane
  • 1,777
  • 2
  • 22
  • 39
  • Hi McFarlane =) Welcome to SO. Whenever posting code you will always get quicker answer if you post the full (or a minimal example of the) code on jsfiddle.net just go there, paste your code, save it, and paste the link back here =) – puk Jan 10 '12 at 23:45
  • what size is your canvas? maybe it's smaller than `140x100`. Try drawing something else like a circle or a picture so you better know which quadrant is being clipped – puk Jan 10 '12 at 23:47

3 Answers3

9

Here is a jsfiddle link with some examples http://jsfiddle.net/pukster/sdQ7U/2/

My guess is that fabric.js calculates everything from the origin (middle point) since it is drawing exactly one quarter of a rectangle even with a canvas 10 times the size of the rectangle. My guess is that top and left actually refer to the origin and not the top and left sides of the imaginary bounding box. Trouble is there is very little documentation on fabricjs. Is there any reason you are using fabricjs and not easeljs

EDIT Here's the same fiddle but with squares instead of rectangles (it is more clear) http://jsfiddle.net/pukster/sdQ7U/3/

EDIT OK I am now almost absolutely certain that fabric.js uses the center as the top/left. I ripped their example off of their site and overlayed it with the transparent couterpart to those shapes had they been coded in pure canvas http://jsfiddle.net/pukster/uathZ/2/ (blue border is the limit of the canvas element).

Overlayed Pure Canvas images

What you see is that the boxes are exactly offset by half but the circle (I only drew a semi circle otherwise it would not have been discernable) is perfectly overlapped. This is b/c in HTML Canvas, the circle coordinates (x,y) refer to the origin and not the top left. I did not bother with the triangle b/c my trigonometry is a bit rusty. I personally think it's misleading to use the terms top and left, when x and y would have been more representative and shorter.

Community
  • 1
  • 1
puk
  • 16,318
  • 29
  • 119
  • 199
  • 1
    Thank you for your detailed answer. Your are right, fabricJS Object Origins are in the middle of the object. I am currently using fabricJS because it is an all-in-one Framework with a bunch of great features (e.g. SVG support, which I will be using later on). Maybe I will switch to processingjs. I will try and compare the two later. – McFarlane Jan 11 '12 at 08:17
  • @McFarlane: did you proceed with this and what was the outcome? I would be interested in a follow-up, including the comparison you mention. – Per Quested Aronsson Mar 11 '13 at 20:21
  • 3
    FWIW, we're planning to switch to originX/originY being left/top by default in the upcoming 1.4 release. Most of the users find this to be more intuitive. – kangax Oct 24 '13 at 14:17
5

Yes, this is highly unexpected and even more undocumented.

Workaround:

Set

originX: "left"
originY: "top"

for each created object.

edit: or use kangax simpler solution in the comment below.

citykid
  • 9,916
  • 10
  • 55
  • 91
  • 4
    You don't have to set it for each object. Fabric takes great advantage of inheritance, so you could just do `fabric.Object.prototype.originX = true; fabric.Object.prototype.originY = true;` – kangax Oct 24 '13 at 14:18
  • 2
    I hate to nitpick the author of a library about his own comment, but shouldn't that be `fabric.Object.prototype.originX = "left"; fabric.Object.prototype.originY = "top";` ? – markerikson Nov 19 '13 at 22:52
  • 1
    kangax, respect for the project and the hint. let me put another constructive rant: light weight objects like drawing objects should be the last that use inheritance for performance reasons. – citykid Nov 20 '13 at 21:51
  • @markerikson - kangax comment about the inherited property works like a charm! – softvar Dec 30 '13 at 12:12
2

I want to comment but lack the reputation to do so. So anyway, here is what happens when I do the following:

fabric.Object.prototype.originX = "left";
fabric.Object.prototype.originY = "top";

The shape gets rendered fine but when I select it for resizing or moving, it gets offset to a different location. The best approach seems to be to set the coordinates for every object separately using the set() method.

StAR_161
  • 658
  • 2
  • 8
  • 19