Weaving Fabric.js With Anime.js For Exceptional Designs
A short module about integrating Fabric.js with anime.js for for excellent animation decisions

Search for a command to run...
A short module about integrating Fabric.js with anime.js for for excellent animation decisions

No comments yet. Be the first to comment.
OpenClaw is a powerful, self-hosted AI assistant that connects to your tools to perform actions. Explore its Gateway architecture, real-world use cases, and security precautions.

Discover how neo-brutalism is shaping 2026 design trends. See how anti-design principles can create distinct, usable, and memorable product experiences.

When code breaks a pipeline, developers have to stop working and figure out why. This blog shows how an AI agent reads the error, finds the fix, and submits it for review all on its own.

GeekyAnts built a 5-agent fraud detection pipeline that makes decisions in under 200ms — 15x cheaper than single-model systems, with full explainability built in.

A deep dive into how GeekyAnts built a real-time AI fraud detection system that evaluates transactions in milliseconds using a hybrid multi-agent approach.

GeekyAnts Tech Blog
348 posts
GeekyAnts is an AI-powered digital product engineering and consulting company helping startups, enterprises, and Fortune 500 brands build scalable, future-ready digital solutions. Since 2006, we have delivered 800+ successful projects for 550+ global clients across healthcare, BFSI, retail, logistics, education, and enterprise technology. We help businesses accelerate digital transformation through strategy, design, engineering, and AI-led innovation.
Most of us have worked with/come across Fabric.js when working on projects that involves fiddling around with the canvas. It could be dragging simple shapes around or defining animations on them. Here's how a simple Fabric object looks like:
var canvas = new fabric.Canvas('c');
var rect = new fabric.Rect({
width: 50,
height: 50,
left: 100,
top: 100,
stroke: '#aaf',
strokeWidth: 5,
fill: '#faa',
selectable: false
});
canvas.add(rect);
// Adding animation to the rect object
rect.animate('left', rect.left === 100 ? 400 : 100, {
duration: 1000,
onChange: canvas.renderAll.bind(canvas),
onComplete: function() {
animateBtn.disabled = false;
},
easing: fabric.util.ease[document.getElementById('easing').value]
});
Let's look into how anime.js creates animation on different objects, specifically the timeline feature. With the help of this feature on the timeline, we can control the animations more comfortably like a video. Use the following code to change this:
// Create a timeline with default parameters
var tl = anime.timeline({
easing: 'easeOutExpo',
duration: 750
});
// Add children
tl
.add({
targets: '.basic-timeline-demo .el.square',
translateX: 250,
})
.add({
targets: '.basic-timeline-demo .el.circle',
translateX: 250,
})
.add({
targets: '.basic-timeline-demo .el.triangle',
translateX: 250,
});
In the above snippet we start with defining the type of animations as well as defining the duration of the entire animation. In this scenario, we would be working with a timeline animation:
tl is a timeline object with a bunch of different properties like pause, play, restart, current time etc on it. With the help of these properties, the user can control how the animation is played. anime({
targets: '.animation-keyframes-demo .el',
keyframes: [
{translateY: -40},
{translateX: 250},
{translateY: 40},
{translateX: 0},
{translateY: 0}
],
duration: 4000,
easing: 'easeOutElastic(1, .8)',
loop: true
});
Now, we have a basic understanding of integrating the animations using Fabric.js and anime.js. While Anime.js is more suitable for video like animations, Fabric.js works with the canvas to gain control over the behaviour of the objects.
Now the question is how can we combine these together to create animations on the timeline using anime.js?
We need the timeline in order to support all the basic video like controls. This can be achieved by defining custom properties on fabric objects. For example:
rect.setOptions({name:value})._anim property which has all the required keyframes that makes up the animation of that object. A sample object with animation keyframes would look like this:{
"rx": 0,
"ry": 0,
"top": 539.4963730569948,
"fill": "#fff",
"left": 539.4963730569947,
"type": "rect",
"_anim": {
"config": {
"keyframes": [
{
"top": 539.4963730569948,
"left": 539.4963730569947,
"angle": 0,
"skewX": 0,
"skewY": 0,
"width": 1080,
"height": 1080,
"scaleX": 1,
"scaleY": 1,
"opacity": 1,
"_initial": {
"opacity": 0
},
"duration": 1,
"_presetId": 35,
"_presetIndex": 0
},
{
"top": 539.4963730569948,
"left": 539.4963730569947,
"angle": 0,
"skewX": 0,
"skewY": 0,
"width": 1080,
"height": 1080,
"scaleX": 1,
"scaleY": 1,
"opacity": 1,
"duration": 2434,
"_presetId": 35,
"_presetIndex": 0
}
]
},
"offset": 0
},
"angle": 0,
"flipX": false,
"flipY": false,
"skewX": 0,
"skewY": 0,
"width": 1080,
"clipTo": null,
"height": 1080,
"scaleX": 1,
"scaleY": 1,
"shadow": null,
"stroke": null,
"_nodeId": "845eeaeb-491b-4db1-8e1e-22199e42a7f5",
"_objKey": "01f114f2-cf8b-4ab5-92d9-0e2e41ab5b32",
"opacity": 1,
"originX": "center",
"originY": "center",
"version": "3.6.2",
"visible": true,
"fillRule": "nonzero",
"paintFirst": "fill",
"crossOrigin": "anonymous",
"strokeWidth": 0,
"strokeLineCap": "butt",
"strokeLineJoin": "miter",
"backgroundColor": "",
"strokeDashArray": null,
"transformMatrix": null,
"strokeDashOffset": 0,
"strokeMiterLimit": 4,
"globalCompositeOperation": "source-over",
}
You can even add videos as fabric objects not just images/shapes. This is possible with the help of
fabric.util.createClass. You can look up more on this in the Fabric docs.
The next step is to create a visualJson using such different objects. Use the code given below to do this:
{"visualJson": {
"objects": [
// Array of fabric objects
],
"version": "",
"backgroundImage": {
// A fabric image object
},
"_canvasDimensions": {
"width":1280,
"height":860
}
}
}
We can make use of this JSON to render objects on the canvas and play animations. So the question remaining is how to animate these properties using _anim?
We can start by creating a timeline object with added keyframes to play animations. Using this, we can iterate through the array of objects and add keyframes to the timeline object. A simple implementation of this would look like:
const timeline = anime.timeline({
easing: 'easeInOutQuad',
duration: 10000,
autoplay: false,
update: () => {
// operations to perform everytime the timeline object changes
},
complete: () => {
// executed when timeline completes
});
// Adding objects to the timeline,
const animConfig = obj._anim;
const keyframes = obj._anim.config.keyframes;
timeline.add(
{
...animConfig,
keyframes,
targets: obj,
update: () => canvas.requestRenderAll()
},
animOffset
);
In the above code snippet the first part creates a timeline object and then we add object keyframes to it.
Every time there’s an update to the object, the canvas has to be re-rendered to account for those changes. With the use of this, we can play a visualJson as an animation on this canvas. The part relating to loading the visualJson on the canvas is quite simple and can be achieved with the fabric canvas loadFromJSON method.
So far we went through how to play a visualJson (an array of fabric objects) as an animation. But, what if we want to update/create animations or delete existing animations/objects? How, do we account for these changes? Let’s try to question what happens to the visualJson when we perform any of these operation and not think about the timeline object for the time-being.
_anim properties.In the last part of this article let’s look into how we can add videos as Fabric objects and manage them along with other animations. What we need to do with videos is play them based on their delay and the duration, i.e. based on the currentTime of the timeline object. We should also make sure to sync that with videos on the pause/play/restart sections of the timeline .
I hope helps you get a basic understanding of Fabric.js and anime.js working in tandem with each other. This should a good starting point for you to start making design decisions for complex functionalities. I’ve worked on a pretty extensive project that involves working with different sorts of animation using Fabric.js, anime.js and React with Typescript. So, if you have any questions/queries feel free to reach out to me on my Twitter handle. Hope you've had a great read!