During my freshman year, I took a general education course where the professor showed an animation drawn using mathematical formulas—a bunch of circles and lines spinning to music. At the time, I just thought it was cool and never thought about how it was done. Years later, when I wrote animations myself using code, I realized that the core of that kind of thing is actually: you're not drawing pictures, you're describing "how things should change as time goes by."
Motion Canvas is an open-source animation library written in TypeScript, licensed by MIT, and currently at version 3.x. Its biggest difference from traditional animation software is that animation is code; each shot is a generator function.yield* A tween is a movement of time forward. The visuals are rendered using Canvas in the browser, previewed in real-time using Vite's development server during development, and output using playwright-core to drive a browser to capture frames one by one.
What's it like to write animations using code?
It felt very strange the first time I wrote it. In typical animation software, you drag a cube to the left, set a keyframe, then drag it to the right and set another, and the software fills in the middle for you. In Motion Canvas, you write "the cube's x changes from 0 to 300, taking one second," and then...yield* You can't see the timeline; the timeline is simply the order of your code from top to bottom.
The discomfort lasted for about two days. On the third day, I discovered something really awesome: I could draw ten squares using loops, control all the spacing using variables, and wrap a shot into a function and call it with different parameters in different places. These things are either impossible in drag-and-drop software, or making them so difficult that you want to cry.
Why is code so important in animation?
For a workflow that needs to run unattended, "the same input always for the same frame" is more important than anything else. Stylized animation is inherently fixed; changes are visible in the diff, and camera angles can be parametrically configured, allowing the same template to be applied to different text and materials. It's not suitable for the improvisational nature of hand-drawn animation—you wouldn't use it to draw a character's facial expressions—but it's perfect for things like motion comics, watercolor-style static shots, and step-by-step diagrams.
Output only image sequences
Motion Canvas has an official video outputter, but that suite comes with its own FFmpeg executable. If your workflow already has a verified and licensed FFmpeg, there's no reason to have a second one. Let Motion Canvas only output PNG sequences, one directory per shot, and let the existing FFmpeg handle encoding and assembly.
This decision has nothing to do with functionality, but everything to do with the checklist: every additional binary digit means one more authorization record to maintain. I'm a bit sensitive about "adding something," not because the thing itself is bad, but because everything needs to be updated, checked, and explained at some point. Losing one means losing one.
Integrating into existing processes
My approach is to add an optional field to the original rendering job definition. Frames with this field are handled by Motion Canvas; those without it continue as before. The output of existing jobs remains unchanged byte-by-byte. This is my requirement for any new art style: anything added cannot alter the output of existing elements.
The first round of experiments calculated 21 shots and over 4,800 frames, all encoded using existing FFmpeg. Watching over 4,000 PNGs appear one by one in the folder gave me a strange sense of peace, like watching freshly washed clothes being hung out to dry.
When should I revert to the original version?
The most common mistake in stylized animation is drawing blindly: insufficient source material, inadequate original text, and actions exceeding the template's capabilities, yet the template still outputs a visually plausible image. Because the program doesn't say "I can't," it simply draws according to the parameters you provide, creating something nobody wants.
My rule is to revert the entire passage to the original version in such cases. It's better to have one less shot than one shot that doesn't match the original text. It's like writing a report: it's better to leave out uncertain paragraphs than to force a seemingly reasonable statement. The professor will see it, and the audience will see it too.
Mini-drama: How is this different from making animations with PowerPoint?
"I can do this kind of thing using PowerPoint's animation feature too."
"Yes, and PowerPoint is much faster if you're only doing it once."
"When should we use this?"
"When you're doing it a hundred times. A hundred slides, each one just different in title and number, you'll want to go through a loop."
"PowerPoint does not have a loop."
"Yes, PowerPoint doesn't have loops. That's the key point of the whole article."
Browser host authorization
When outputting, playwright-core requires a browser. Chromium itself is BSD, but if you make it use an existing browser like Edge or Chrome on your machine, it becomes proprietary software. If you only use it and don't distribute it with the package, it doesn't need to be listed as an open-source component, but you should clearly state what you're using in the license record. Motion Canvas itself is MIT (Made in Taiwan), so just retain the copyright and license details.
My opinion on it
It transforms "animation" into something that can be tested, reviewed, and reproduced, just like other code. For those who want to mass-produce visuals programmatically and also want every frame to be interpretable, this is currently my most convenient tool.
If the professor of that general education course saw what I'm doing now, he'd probably say, "You finally understand." Actually, I still don't quite understand those mathematical formulas, but I've understood something else: animation can be a form of writing, except you're writing about time.
It's a tool that a YouTuber wrote for himself.
The creator of Motion Canvas is a YouTuber who makes game development tutorial videos, known online as aarthificial. His videos contain many animated explanations of programming concepts. He initially used general animation software to create them, but it became increasingly difficult because the essence of those animations was "explaining the behavior of a program," and program behavior is best described using programs. So he wrote his own, released it as open source in 2022, and licensed it through MIT.
This origin explains many of its design choices. It doesn't strive for the expressiveness of hand-drawn illustrations; instead, it aims to "precisely bring an idea to life." Its API revolves around time.yield* tween(1, ...) It's about "doing this in a second."yield* all(a, b) It means "doing both things at the same time".yield* waitFor(0.5) It's "wait half a second." It reads like reading a storyboard, except this storyboard executes itself.
It has a concept called a signal. When one value changes, everything that depends on it automatically changes accordingly. You can bind the position of a block to a signal, and then only change the signal, and the block will move on its own. This is the same idea as the reactive states of front-end frameworks, and it is surprisingly suitable for animation because animation is essentially "a bunch of things moving around each other over time".
Three common misunderstandings
The first misconception is that "stylized animation must look mechanical." Easing functions, random jitter, and organic curves can all be written, and once written, they can be accurately reproduced. The mechanical feel comes from laziness, not from the tools.
The second misconception is that "it can replace After Effects." No, it cannot, and it doesn't intend to. Hand-drawing, compositing, color grading, and complex masking are the domain of professional animation software. Motion Canvas excels at structured, parametric, and repeatable visuals.
The third misconception is that "the output is slow." This refers to drawing with Canvas in the browser and taking screenshots frame by frame, which sounds slow, but in reality, hundreds of frames take tens of seconds. The slowness usually comes from doing too much calculation in each frame yourself.
A small exercise you can try over the weekend
npm init @motion-canvas@latestChoose an empty project and runnpm start The browser will open an editor. Opensrc/scenes/example.tsx You will see a generator function. Add a circle inside it.yield* circle().position.x(300, 1) Save the file, and the circle in the browser will slide to the right in one second.
Then wrap it in a loop, draw five circles, each starting with a 0.2-second delay. Next, bind the color to a signal, and change the signal's value halfway through the animation. In this hour, you'll experience two benefits of "animation is code": loops, and "changing one thing changes everything." Finally, use the editor's output function to save it as an image sequence, and check out the row of PNGs in your folder.
Postscript
"Animation can be a form of writing, except you're writing about time." I looked at this sentence for a long time after writing it. It sounds a bit pretentious, but I can't think of a more accurate way to put it. When you're writing an article, you're deciding what the reader sees first and what they see next; when you're creating animation, you're deciding what the audience sees first and what they see a few seconds later. The core of both is order and rhythm; the tools are just different ways of writing down your decisions. I now feel that the tuition for that general education course was well worth it.
Project page: motioncanvas.io