13. 10. 2024 · Motion Canvas 2/3 · 33 min read · [edit]
Note: The original Motion Canvas project is no longer maintained – its website, motioncanvas.io, is now offline. This series has been updated to use Canvas Commons, the actively-maintained community fork. The API is the same; only the package imports differ (@canvas-commons/* instead of @motion-canvas/*), and all documentation links here point to the Canvas Commons docs.
In this part of the series, we’ll explore some more layout-related animations, explore the animation flow and discover signals + effects.
We’ll also play around with colors a bit 🙂.
Grouping objects
Motion Canvas doesn’t fully support the same grouping as Manim (i.e. change the color of all objects in this particular group). Instead, we should always be working with the scene hierarchy and layout objects, which do support certain operations, mostly related to their position, scale/size and rotation.
In this example, we’re also using the fact that Motion Canvas supports any X11 color names – feel free to browse through them and pick the ones that you like!
| |
| |
Arranging objects in Manim is usually done via the arrange
function.
In Motion Canvas, we again utilize the almighty flexbox… well, kind of – animating certain flexbox properties is still not supported (but will likely be in the future):
| |
| |
For grids, Manim’s arrange_in_grid
is just a special case of Motion Canvas’ flexbox shenanigans.
The only difference here is that we’re newly using the wrap property, since the circles would otherwise be squished and not wrapped to form a grid.
To make the animation a bit more interesting, we can utilize the chroma.js library (which Motion Canvas internally uses to work with colors) to assign colors using a color scale.
| |
Adding, removing and ordering
The order in which the objects are rendered is based on the scene hierarchy – the higher they are, the sooner they are rendered (i.e. the more at the bottom they are). However, if they differ in their z-index, the one with a higher z-index will always be drawn on top of the other:
| |
Animation flow
We’ve already seen a few of these in the previous post, but we can use different functions for working with animation flow. One of the main differences between Manim and Motion Canvas is that the animation model inherently allows for a lot of concurrency, since you can have multiple threads concurrently changing different properties, even of the same object:
| |
Signals
Signals are Manim’s updaters on crack.
Instead of an object’s characteristics being static values, they are usually signals, which are (as the documentation describes) values that can change over time and define dependencies between objects.
This means that, as opposed to Manim’s updaters, we don’t need to explicitly say that an object’s attribute should be set to this value at every frame – we say that it is that value:
| |
Note that we don’t necessarily need to only assign one signal to another – we can assign a function that takes the value of the signal and modifies it how we want, for example taking the position of an object and converting it to text to display it:
| |
A crucial detail is that signals are lazy – assuming that the value of a signal is some complicated function that relies on other signals, it is only calculated when the value is requested, making it a perfect fit for creating dependencies between properties, but not so much for e.g. a simulation function that needs to change things each frame.
For that, we have effects…
Effects
Effects are functions that are run on their dependency changes, but unlike signals are no longer lazy. This means that all of their dependencies are no longer lazy as well, so if you have many things going on at the same time, things might run a bit slow…
Effects come in two flavors; directly quoting the documentation:
createEffect()runs immediately after any of its dependencies changes.createDeferredEffectruns at the end of each frame if any of its dependencies changed.
For example, we could use it to create a simple particle simulation like this one:
| |
Tasks
Shuffle
Before trying to animate this, here are a few useful things:
- to move a circle along a nice path, you can define a spline between two points and then move along it using the
getPointAtPercentagefunction (see the documentation page for splines) - to animate a value from
0to1that we can use for the percentage value, we can create and animate a new signal (more about what that is in the signals section above) - the
easeInOutExpoeasing curve is nicer for shuffling since it’s more sudden than the default
All of the above can be summarized in the following animation:
| |
| |
| |
Triangle
Unlike Manim’s Circle.from_three_points
, Motion Canvas doesn’t have a utility function for doing this.
Instead, the following functions (along with a createDeferredEffect
) could be useful:
| |
| |
| |
Wave
Nothing extra here, just a BFS.
Here is the text input that I used to generate the maze, if you wish to use it.
| |
| |
| |
Hilbert
Here are some useful things:
- the
clonefunction will be very useful here to create copies of an object - use the
topLeft,topRight,bottomLeftandbottomRightcardinal directions for alignment - you can define the spline using
<Knot>, which allows you to access theirabsolutePosition, which will make the code a lot simpler (the clones will likely be scaled + rotated at this point, which doesn’t change their relativeposition) - setting the smoothness of a spline to
0will make it line segments - you can animate drawing of a spline with the
endsignal
| |
| |

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.