How to attach event listeners directly to canvas objects?

Mandev
3 min readDec 4, 2022

--

In the previous article, we added mouse events onto the canvas whereby we learnt how we can tackle events that occur due to user interaction with the mouse.

When we write, canvas.on() and attach the events to the canvas, it means that the particular event is scoped to that canvas instance.

So, if we had two canvases whose instances were say, canvas1 and canvas2, we could attach different event listeners to them without stumbling upon an error. This is because the instances respect only the events that are assigned to them.

      var canvas1 = new fabric.Canvas("canvas1", {
backgroundColor: "black",
isDrawingMode: false,
});

var canvas2 = new fabric.Canvas("canvas2", {
backgroundColor: "red",
isDrawingMode: false,
});

canvas1.on("mouse:down", () => {
console.log("This is canvas1");
});

canvas2.on("mouse:down", () => {
console.log("This is canvas2");
});
canvas1 has bg color “black” while canvas2 has bg color “red”.

Attach event listeners to objects

The “skewing” event Listener

Just how we can attach event listeners to canvas instances by using the on() method, we can do the same to other canvas objects. So, that means that the below code is completely valid:


var skewFunction = function () {
canvas.renderAll();
tri.animate("strokeWidth", "+=8", {
onChange: canvas.renderAll.bind(canvas),
easing: fabric.util.ease.easeOutExpo,
});
};

tri.on("skewing", skewFunction);

In the code above, tri is a triangle instance to which I have added the “skewing” event listener. Also, I have created an event handler called the skewFunction which will be called every time we skew the triangle.

Note: You can skew an object on the canvas by pressing shift and dragging along the controls

The skewFunction inturn, is a function which animates the triangle. When we say tri.animate and pass it the arguments “strokeWidth” and “+=8”, it means that its stroke width will be incremented by a value of 8 every time it is skewed.

Every time we skew tri, it’s strokeWidth value gets incremented by 8.

Here’s the complete code:

    var canvas = new fabric.Canvas("canvas", {
backgroundColor: "black",
isDrawingMode: false,
});

// Initiating a triangle instance
var tri = new fabric.Triangle({
top: 20,
left: 90,
width: 80,
height: 200,
fill: "blue",
stroke: "white",
strokeWidth: 1,
});

// Adding the tri instance to the canvas
canvas.add(tri);

// This is the event handler
var skewFunction = function () {
canvas.renderAll();
tri.animate("strokeWidth", "+=8", {
onChange: canvas.renderAll.bind(canvas),
easing: fabric.util.ease.easeOutExpo,
});
};

// when skewing event occurs, call skewFunction
tri.on("skewing", skewFunction);

Increasing the Radius of a circle while Moving it

Instead of creating a handler, we can use the good old arrow function like so:


// Initiating a circle instance
var circle = new fabric.Circle({
top: 20,
left: 90,
radius: 6,
fill: "#e6e6fa",
stroke: "#9966cc",
strokeWidth: 16,
});

// Adding the circle instance to the canvas
canvas.add(circle);

// Using an arrow function in the second argument
circle.on("moving", () => {
canvas.renderAll();
circle.animate("radius", "+=7", {
onChange: canvas.renderAll.bind(canvas),
easing: fabric.util.ease.easeOutSine,
});
});

This is similar to the previous example except, the radius gets incremented by 7 whenever we move the circle on the canvas. Since, originally, the radius was 6, on moving it once, its radius will change to 13 and it will only be incrementing on being moved!

I hope you get the idea. Other event listeners can also be attached to object instances like this. So, those would be, selected, deselected, moving, skewing, rotating, modified etc.

You can see the radius increases only when we are moving the circle on the canvas!

--

--