Skip to content
kangax edited this page Aug 28, 2011 · 8 revisions

Installing and setting up

AW: need some advice here on how to install the script. I found out after looking at a demo and cutting and pasting the linked to file. Downloaded and unzipped the whole file weighs 80mb+ – ouch, surely a record

The Canvas API requires that you add your Canvas tags first:

Declaratively

<canvas id="my-canvas" width="400" height="400">

If you don’t specify the width and height then the browser will set the measurements for you

Programmatically

var canvas_1;

canvas_1 = document.createElement("canvas");
canvas_1.width = "400";
canvas_1.height = "400";
canvas_1.id = "my-canvas";
document.getElementsByTagName('body')[0].appendChild(canvas_1);

Creating canvas

Everything in fabric is rendered in context of a certain canvas. Each canvas instance corresponds to one canvas element. Initializing canvas is as simple as creating objects. The only thing that has to be passed to `fabric.Canvas` constructor is id of a canvas element that exists in a document.

<canvas id="my-canvas"></canvas>
...
var myCanvas = new fabric.Canvas('my-canvas');

Similar to object initialization, `fabric.Canvas` constructor can accept options object as a second argument. For example, we can specify canvas background to be black, and turn off ability to select objects (“selection” option):

var myCanvas = new fabric.Canvas('my-canvas', {
  backgroundColor: 'black',
  selection: false
});

Objects

Creating objects

You can create all kinds of shapes with fabric — simple ones like circle, rectangle, triangle, as well as complex ones like paths and path groups. Creating objects is very simple. Let’s take a look at how to create a rectangle:

var myRect = new fabric.Rect({ width: 100, height: 100 });

And what about circle?

var myCircle = new fabric.Circle({ radius: 50 });

And what about a triangle?

var myTriangle = new fabric.Triangle({ width: 100, height: 100 });

AW: anything else? polygons?

It’s important to understand that when object is created in such way, it doesn’t yet render on canvas. It only exists in memory. In order to render it on canvas, you need to add it to that particular canvas, using canvas’ `add` method:

myCanvas.add(myCircle);

Object options

Note how we specified “width” and “height” of rectangle, and “radius” of circle. These properties are all part of the initial options that can be passed to an object initializer. Let’s try creating a circle but this time with few more options passed in:

var myCircle = new fabric.Circle({ 
  radius: 10, 
  fill: 'red', 
  stroke: 'blue'
});

Notice how we specified “fill” and “stroke” values of a circle. This will make circle entirely red, with a blue outline. We could have also specified other options, such as “left”, “top”, “angle”, “opacity”, and many others:

var myCircle = new fabric.Circle({
  radius: 10,
  left: 100,
  top: 200,
  opacity: 0.5
});

Modifying objects

Once you create an object, you can modify its properties. Let’s create a rectangle again, then try to change some of its properties:

var rect = new fabric.Rect({ width: 100, height: 50 });
rect.getWidth(); // 100

rect.setWidth(200);
rect.getWidth(); // 200

Notice how we created rectangle with width of 100, then changed it to 200. You can change almost any property of an object in such way, even after it’s created:

var circle = new fabric.Circle({ radius: 20 });
circle.set('radius', 30); // radius is now changed from 20 to 30

When you need to change multiple properties at the same time, you can pass an object to `set` method, instead of calling it again and again:

var circle = new fabric.Circle({ radius: 20, fill: 'red' });
circle.set({
  fill:     'green',  // change fill color to green
  opacity:  0.5,      // make it half transparent
  left:     100,      // position it at 100 pixels from the left edge
  top:      100       // ... and 100 pixels from the top edge
});

Chaining object methods

For convenience, most of the object methods can be chained. For example, let’s say we want to change both — opacity and coordinates of a circle object. One way to do this would be like so:

myCircle.setLeft(100);
myCircle.setTop(200);
myCircle.setOpacity(0.25);

Another way — as we’ve seen in the previous section — is to pass an object to `set` method:

myCircle.set({ 
  left: 100, 
  top: 200, 
  opacity: 0.25 
});

Finally, we can always take advantage of method chaining:

myCircle
  .setLeft(100)
  .setTop(200)
  .setOpacity(0.25);

Canvas

Adding objects

After you have created a canvas it’s time to finally draw something on it. You already know how to create an object, and how to create a canvas. The only missing link is adding created object onto canvas. Let’s see how this is done:

var myRect = new fabric.Rect({ width: 100, height: 50, fill: 'red' });
var canvas = new fabric.Canvas('my-canvas');

canvas.add(myRect);
canvas.renderAll();

What’s going on here? Well, let’s see. First we create a rectangle object — `myRect`. Then we initialize canvas — `myCanvas`. Then we add rectangle to this newly initialized canvas, and finally call `renderAll` method.

What’s the purpose of `renderAll` method?

You see, while `canvas.add` does add object to canvas, it does it quietly, without rendering anything on the screen. The object is considered part of canvas, it can be modified, or even removed. But it doesn’t render until we call canvas’ `renderAll` method.

This means that we can add few objects to canvas, and then render everything in one go:

canvas.add(new fabric.Rect({ width: 10, height: 10, fill: 'red' }));
canvas.add(new fabric.Circle({ radius: 20, fill: 'blue' }));
canvas.add(new fabric.Triangle({ width: 20, height: 20, fill: 'green' }));

canvas.renderAll(); // only at this point all objects are rendered on canvas

Just like with other methods in fabric, `add` tries to be as helpful as possible. If you wish to add few objects to canvas at the same time, you can simple pass them all to `add` as separate arguments:

var rect = new fabric.Rect({ width: 10, height: 10, fill: 'red' });
var circle = new fabric.Circle({ radius: 20, fill: 'blue' });
var triangle = new fabric.Rectangle({ width: 20, height: 20, fill: 'green' });

canvas.add(rect, circle, triangle);
canvas.renderAll();

We can now use canvas’ `getObjects` method to see what exactly is contained within canvas:

 canvas.getObjects(); // [ rect, circle, triangle ]

As you can see, `getObjects` returns an array of objects that exist on canvas. `getObjects` will return any object that’s part of canvas, even if that object is not rendered. `getObjects` doesn’t care if `renderAll` wasn’t yet called on canvas, or if object was made transparent.

Removing objects

So we now know how to add objects to canvas. But what if an object is of no longer use to us? How to remove it? As surprising as it sounds, this is done via canvas’ `remove` method:

var rect = new fabric.Rect({ width: 100, height: 50 });
canvas.add(rect);
canvas.getObjects(); // [ rect ]

canvas.remove(rect);
canvas.getObjects(); // [ ]

Notice that `remove` accepts a reference to an object to be removed. But don’t worry if reference to object is somehow lost. Using that same `getObjects`, we can retrieve any object from canvas. For example, here’s how we would remove first object:

canvas.remove(canvas.getObjects()[0]);

.. or using a convenient `item` shortcut:

canvas.remove(canvas.item(0));

Very simple, isn’t it?

Changing objects’ z-index

Canvas background

By default canvas background is always white. But we can change it at any moment — either during canvas initialization (by passing `backgroundColor` property via options object) or by setting canvas’ “backgroundColor” property directly, even after initialization:

var myCanvas = new fabric.Canvas('my-canvas', {
  backgroundColor: 'black'
});
myCanvas.backgroundColor = 'blue';

Clipping canvas

Chaining

Similarly to objects’ methods like `set`, most of canvas’ methods can be chained as well. A very simple example would be using `add` many times in a chained fashion:

canvas.add(rect).add(circle).add(triangle);

Here’s a more interesting example:

canvas.clear().add(rect).centerObjectH(rect).centerObjectV(rect).renderAll();

What’s going on here? First canvas is cleared (`clear()`), then we add a rectangle to it (`add(rect)`), then we center that rectangle horizontally (`centerObjectH(rect)`), then we center it vertically (`centerObjectV(rect)`), and finally render all the changes (`renderAll()`).

Recalculating offset