There’s plenty of buzz in the dev world around the relatively new Theatre.js. So, is it just another JavaScript animation library?
The answer is no, not really. Theatre.js is a motion graphics library that allows you to build powerful animations easily. According to the creators, “Theatre.js is an animation library for high-fidelity motion graphics. It is designed to help you express detailed animation, enabling you to create intricate movement, and convey nuance.”
And, unlike other JavaScript and CSS animation libraries, Theatre.js is an animation library with a graphical user interface (GUI). The GUI allows you to build the animations visually with the editor integrated into your browser.
It literally turns your browser into an animation studio — you’ll most likely only need to write the setup code, and that’s it.
It even animates the DOM, WebGL, Three.js, HTML, and other JavaScript variables, meaning you can set it up and allow even a non-developer to create the animations on the browser with the Theatre.js editor.
Here is an example:
Throughout this article, we’ll explore how to set up and create your own animation lab with JavaScript and Theatre.js.
You can use Theatre.js with vanilla JavaScript or any JavaScript library like React or Angular. In this article, we’ll use Theatre.js with vanilla JavaScript and the Parcel build tool.
First, let’s create a directory, initialize it with npm init
, and run the command below to install Theatre Core and Theatre Studio. Theatre Core is the main library, while Theatre Studio is the editor, which you’ll only need in design and development.
Theatre Core:
npm install @theatre/core --save
Theatre Studio:
npm install @theatre/studio --save-dev
Next, we’ll create the necessary files we need to run the application. To make it easy to follow along, I’ve created a boilerplate for this article. Run git clone https://github.com/ezesundayeze/theatrejs
on your terminal to grab a copy of it.
Edit the HTML document with the following content:
src/index.html <style> body { background: rgb(6, 143, 113); margin: 0; } #box { position: absolute; width: 100%; top: 0; height: 50%; display: flex; justify-content: center; align-items: flex-end; gap: 8px; --box-size: 40px; } .boxContainer { width: var(--box-size); position: relative; } </style> <div class="boxContainer"> <div id="box"></div> </div> <script type ="module" async src="index.ts"></script>
Next, let’s add the JavaScript code we linked to the HTML. Create an index.js
file and import Theatre and Theatre Studio, as shown below:
import * as core from "@theatre/core"; import studio from "@theatre/studio";
After that, initialize Theatre Studio by adding studio.initialize()
to the existing code. It should now look like this:
import * as core from "@theatre/core"; import studio from "@theatre/studio"; studio.initialize()
Run the application with npm run dev
to see Theatre Studio in action. The little icon at the top left corner of the page shows that Studio is active.
However, we still won’t be able to do anything just yet, as our studio setup is incomplete.
In Theatre.js, you’ll come across and use the following:
Let’s set them up in our studio.
A project in Theatre.js is the workspace in which all animation work will be done. Creating a project is as easy as adding the following line to your code after you’ve imported Theatre.js and Studio:
const project = core.getProject("soccer ball Animation");
A sheet is similar to a component in React. It holds objects that are animated together, and you can have more than one sheet within a project.
This is how you add a sheet to a project:
js const ballSheet = project.sheet("ballSheet");
An object in Theatre.js refers to the actual object to animate. In this object, we’ll set the default properties we’d like to animate. These props can be modified in the animation editor to create the type of animated look and feel we want.
Here is an example on how to add the object props:
const ballObj = sheet.object("ballSheet", { y: 100, x: 150, angle: 0, stretch:1 });
Let’s take a look at how object properties will show up as controls in the editor when you run the app. You’ll need to slide them left to right, or vice versa, to get the desired animation.
A sequence defines the order and manner in which related items follow each other. In Theatre.js, sequences define the order in which object properties move. It’s this movement that creates the actual animation.
The section below is what allows you to create and modify the sequences:
Each sequence has a position
, which determines progress within the animation. The figures at the top of the bar show the position of the object at a certain instance. The default unit is in seconds.
So, let’s add some animation to the HTML we used initially. First, select the target element, add the image we intend to use (it’s not required to be an image — you can create shapes or animate any item at all), and add some basic CSS to align the element on the page.
const boxDiv = document.getElementById("box"); const ball = document.createElement("img"); ball.src = "soccer ball.png"; boxDiv.appendChild(ball); ball.style.position = "absolute"; ball.style.width = "100px"; ball.style.height = "100px";
For this example, I’ll start the animation by clicking on the soccer ball. So, let’s add an eventListener
to the ball element.
ball.addEventListener("click", () => { const sequence = sheet.sequence.play({ iterationCount: Infinity, rate: 1, range: [1, 6] }) });
When the ball is clicked, we can play the sequence by calling the sequence.play()
method. You can customize the sequence by passing an object with properties, such as rate
, which sets the speed of the sequence, and iterationCount
, which sets the number of times you want the sequence to play.
In the example above, I set it to play forever. Range
is the position range you want it to run through. We set ours to run from position 1
to 6
. You can find more props in the docs.
To see the animation progression, we’ll use the .onValueChange
method of the ball object and then set the CSS transformation to match the expected behavior.
ballObj.onValuesChange(({ y, x, angle, stretch }) => { boxDiv.style.cssText = ` transform: translateX(${x}px) rotate(${angle}deg) translateY(${y}px) scale(${1 / stretch}, ${stretch}); `; });
In the transformation (transform
adds a 2D or 3D transformation to an element), we are using the translateY
and translateX
properties to modify the behavior of the transformation.
We’ve now set up our Theatre.js animation studio to animate a soccer ball. You can view this in action below or click on this link to see the demo on CodeSandbox.
In production, you might want to turn off the studio. You can do so by calling the studio.ui.hide()
method. To restore it in development, call the studio.ui.restore()
method.
Finally, after playing around with the studio and creating your desired animation for the objects, you can export the studio state by clicking on Project, then Export, as shown below.
You can now link this state to your project by importing and adding it to your project instance, like so:
import state from "./state.json" const project = core.getProject("soccer ball Animation", {state});
Congratulations, you’ve set up your Theatre Studio and have explored some of its features. We have only scratched the surface. Keep in mind that there is still a lot to learn, as this project is less than two months old and still developing at the time of this writing.
Theatre.js is an amazing project that gives you the power to craft your own animation studio. This has the potential to shape the web animation ecosystem as it gathers more adoption from the community, so now is a great time to jump in and start exploring Theatre.js or contribute to developing the library further.
There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.
LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.
LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.
Build confidently — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.