Rive Animations example
How it works
A Rive file playing in a canvas. Point an element at the file, name the state machine, done.
Rive plays a .riv file, the format exported by the Rive editor, inside a canvas it creates for you. The class in src/js/handler/rive reads four data attributes from the element, appends a canvas to it and hands both to the @rive-app/canvas runtime, which fetches the file, loads its WebAssembly backend and starts drawing. The runtime is imported dynamically the first time an element is built, so it costs nothing on pages without a Rive element.
A state machine is how a Rive file decides what to play: it holds the animations and the logic between them. Name it with data-state-machine and the runtime runs it. Leave it out and the runtime plays the first animation of the artboard, or its first state machine if it has no plain animations. The canvas is resized to the element's real pixels on load and on every window resize, so the drawing stays sharp at any size and pixel density. See the Rive docs for how files, artboards and state machines are made.
The markup
One element with the js--rive-element hook and the attributes. The element must have a height: the canvas fills 100% of it, so an element with no height draws nothing. Both examples on this page size it with an inline style to keep the snippet short; in a real project give the element a component class and set the size in SCSS, with an aspect ratio or a fixed height.
<!-- The element is the frame; the class appends a canvas that fills it -->
<div class="js--rive-element" data-src="/animation.riv" data-state-machine="State Machine 1" style="width: 100%; height: 400px;"></div> The handler
Handler.js has nothing to pass on: the config is the element and nothing else, because Rive.js reads the attributes itself.
this.config = ({ element }) => ({
element,
}); This is what the class reads. A missing attribute is undefined, which the runtime treats as its default; data-autoplay is only false when it says "false":
this.src = element.getAttribute("data-src");
this.artboard = element.getAttribute("data-artboard") || undefined;
this.stateMachine = element.getAttribute("data-state-machine") || undefined;
this.autoplay = element.getAttribute("data-autoplay") !== "false"; And how they reach the runtime. onLoad fits the drawing surface to the canvas once the file is in:
this.riveInstance = new RiveLib({
src: this.src,
canvas: this.canvas,
artboard: this.artboard,
stateMachines: this.stateMachine,
autoplay: this.autoplay,
onLoad: () => {
this.riveInstance.resizeDrawingSurfaceToCanvas();
},
}); What the framework does for you
- Lazy loading. An element is only built when it gets within 30px of the viewport (Boostify scroll).
Rive.jsis loaded through the Manager on first use, and it imports@rive-app/canvasonly then. - Page transitions. Before swup replaces the content every instance is destroyed: the runtime is cleaned up, the resize listener removed and the canvas taken out of the DOM. The new page builds its own.
- Resize. The drawing surface follows the canvas size, so a responsive element never shows a blurry or cropped animation.
Remote file
A .riv fetched from a CDN, with the artboard named explicitly.
artboard="Main Artboard"state-machine="Motion"autoplay="true" data-src takes any URL, so the file can live on a CDN or an asset host; the runtime fetches it when the element is built. This file has more than one artboard, so data-artboard picks the one to draw and data-state-machine names the machine inside it. data-autoplay="true" is the default and is written here only to show it.
A remote file is only requested when the element is near the viewport, so a heavy animation low on the page costs nothing until it is needed.
<div
class="js--rive-element"
data-src="https://assets.codepen.io/278239/3306-6996-cannonball-man.riv"
data-artboard="Main Artboard"
data-state-machine="Motion"
data-autoplay="true"
style="width: 100%; height: 400px;"
></div> artboard="Main Artboard"state-machine="Motion"autoplay="true" Local file
A .riv served from public/, using the file's default artboard.
src="/menu.riv"state-machine="State Machine 1" The usual case in a project: the file is part of the build, in public/, and data-src is its path. There is no data-artboard, so the runtime uses the default artboard of the file, which is what most exports have. The state machine is the one the designer named in the editor, State Machine 1 being the editor's default name.
<!-- /menu.riv lives in public/. No artboard: the file's default one is used -->
<div
class="js--rive-element"
data-src="/menu.riv"
data-state-machine="State Machine 1"
data-autoplay="true"
style="width: 100%; height: 400px;"
></div> src="/menu.riv"state-machine="State Machine 1" Options reference
Everything you can set, on the element.
| Attribute | Values | What it does |
|---|---|---|
data-src | URL or path, required | The .riv file to play. A path under public/ or a full URL |
data-artboard | name, default: the file's default artboard | Which artboard of the file to draw, for files that have more than one |
data-state-machine | name, default: none | The state machine to run. Without it the runtime plays the first animation of the artboard, or its first state machine if there are no animations |
data-autoplay | true (default) or false | Starts playing as soon as the file loads. Only the exact string false turns it off |
The size of the animation is the size of the element: the canvas fills it. Set the width and height, or an aspect ratio, in SCSS on a component class of your own; js--rive-element is a hook and carries no styles.