paint-brush
Introducing The Web Animations API and @okikio/animate by@okikio
469 reads
469 reads

Introducing The Web Animations API and @okikio/animate

by Okiki OjoJune 11th, 2021
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

The Web Animations API lets us construct animations and control their playback with JavaScript. @okikio/animate is a Javascript animation library focused on performance and ease of use. The API was designed to underlie implementations of both CSS Animations and CSS Transitions. It is one of the most performant ways to animate on the Web, letting the browser make its own internal optimizations without hacks, coercion, or window.requestAnimationFrame.(). For building custom animation libraries and creating interactive animations, the Web. Animation API might be the perfect tool for the job.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Introducing The Web Animations API and @okikio/animate
Okiki Ojo HackerNoon profile picture

The Web Animations API lets us construct animations and control their playback with JavaScript. The Web Animations API opens the browser’s animation engine to developers and manipulation by JavaScript. This API was designed to underlie implementations of both CSS Animations and CSS Transitions and leaves the door open to future animation effects. It is one of the most performant ways to animate on the Web, letting the browser make its own internal optimizations without hacks, coercion, or window.requestAnimationFrame().

With the Web Animations API, we can move interactive animations from stylesheets to JavaScript, separating presentation from behavior. We no longer need to rely on DOM-heavy techniques such as writing CSS properties and scoping classes onto elements to control playback direction. And unlike pure, declarative CSS, JavaScript also lets us dynamically set values from properties to durations. For building custom animation libraries and creating interactive animations, the Web Animations API might be the perfect tool for the job. Let's see what it can do! 

For the rest of this article, I will sometimes refer to the Web Animation API as WAAPI. When searching for resources on the Web Animation API on Google, Bing, etc… you can often be led astray by the search query “Web Animation API” so, to make it easy to find resources, I feel we should adopt the term WAAPI; tell me what you think in the comments below.

@okikio/animate

@okikio/animate is an animation library for the modern web. It was inspired by animateplus, and animejs; @okikio/animate is a Javascript animation library focused on performance and ease of use. It utilizes the Web Animation API to deliver butter-smooth animations at a small size, it weighs ~5.36 KB (minified and gzipped).

What is the story behind @okikio/animate?

In 2020, I decided to make a more efficient PJAX library, similar to Rezo Zero’s - Starting Blocks project, but with the ease of use of barbajs. I felt starting blocks was easier to extend with custom functionality, and could be made smoother, faster, and easier to use. (Note: if you don’t know what a PJAX library is I suggest checking out MoOx/pjax; in short PJAX allows for smooth transitions between pages using fetch requests and switching out DOM Elements).

I started the project, over time my intent shifted, I started noticing how often sites from awwwards.com used PJAX, but often they butchered the natural experience of the site and browser, alot of the sites that featured PJAX look cool at first glance, but actual usage was a different story, scrollbars were often overridden, prefetching was often too eager, and the sites almost never prepared for people who didn’t have powerful internet connections, CPU’s and/or GPU’s. So, I decided that for the library I was going to build everything was going to be progressively enhanced. I started what I call the native initiative stored in the Github repo okikio/native; a means of introducing all the cool and modern features in a highly performant, compliant, and light-weight way.

For the native initiative I designed the PJAX library @okikio/native; while testing on an actual project I realized there were no libraries that took advantage of it, so, I developed @okikio/animate (Note: this was in 2020, around the same time use-web-animations by wellyshen was being developed. If you are using react and need some quick animate.css like effects, use-web-animations is a good fit). At first it was just supposed to be simple wrapper, but little by little I built on it, and it’s now at 80% feature parity with more mature animation libraries.

Note: you can read more on the native initiative as well as the @okikio/native library on the Github repo okikio/native. Also, okikio/native, is a monorepo with @okikio/native & @okikio/animate being sub-packages within it.

How does @okikio/animate fit in?

The Web Animation API is very open in design, it is functional on its own but it's not the most developer-friendly or intuitive API, so, I developed @okikio/animate to act as a wrapper around the WAAPI, to introduce the features you know and love from other more mature animation libraries (with some new features included) to the high-performance nature of the Web Animation API.

Getting Started

@okikio/animate is heavily inspired by animejs and animateplus, as such it uses a very similar format.

@okikio/animate creates animations by creating new instances of Animate (a class that acts as a wrapper around the Web Animation API), 


import { Animate } from "@okikio/animate";

new Animate({
  target: [/* ... */],
  duration: 2000,
  // ... 
});

The Animate class receives a set of targets to animate, it then creates a list of WAAPI Animation instances, alongside a main animation (the main animation is a small Animation instance that is set to animate the opacity of a non-visible element, it exists as a way of tracking the progress of the animations of the various target elements), the Animate class then plays each target elements Animation instance, including the main animation, to create butter-smooth animations.

The main animation is there to ensure accuracy in different browser vendor implementations of WAAPI. The main animation is stored in Animate.prototype.mainAnimation, the target elements Animation instances are stored in a WeakMap, with the key being its KeyframeEffect, you can access the animation for a specific target using the Animate.prototype.getAnimation(el).

You don't need to fully understand the prior sentences, but they will aid your understanding of what @okikio/animate does. If you want to learn more about how WAAPI works check out MDN, or if you would like to learn more about the @okikio/animate library I'd suggest checking out the Github project, okikio/native.

Usage, Examples & Demos

By default, needing to create a new instance of Animate is very annoying, so, I created the animate function, which creates new Animate instances every time it’s called.


import animate from "@okikio/animate";
// or
import { animate } from "@okikio/animate";

animate({ 
  target: [/* ... */],
  duration: 2000,
  // ... 
});

When using the @okikio/animate library to create animations you can do this:

import animate from "@okikio/animate";

// Do note, on the web you need to do this, if you installed it via the script tag:
// const { animate } = window.animate;

(async () => {
    let [options] = await animate({
        target: ".div",

        // Units are added automatically for transform CSS Properties
        translateX: [0, 300],
        duration: 2000, // In miliseconds
        speed: 2,
    });

    console.log("The Animation is done...");
})();

Check out the embedded CodeSandbox demo:

You can also play with a demo with playback controls:

Try out Motion Path:

Try different types of Motion by changing the Animation Options:

I also created a complex demo page--with polyfills: https://okikio.github.io/native/demo/animate.html

You can find the source code for this demo on Github at: https://github.com/okikio/native/blob/master/build/ts/modules/animate.ts and https://github.com/okikio/native/blob/master/build/pug/animate.pug

The demo uses pug, and is a fairly complex setup, so, I highly suggest reading (https://github.com/okikio/native/tree/master/packages/animate#demo)

The native initiative uses Gitpod, so, if you want to play with the demo, I recommend clicking the Open in Gitpod link, since the entire environment is already setup for you, you don’t need to do any configuring. 

You can also check out some more complex examples at: https://codepen.io/collection/rxOEBO

For the most part, you can port your code from animejs to @okikio/animate with little to no issues.

But I should probably mention that @okikio/animate supports both the target and targets keywords for settings targets, @okikio/animate will merge both list of targets into one list and use Set’s to remove any repeated targets. @okikio/animate supports functions as animation options, so you can use staggering similar to animejs (Note: the order of arguments are different, read more in the Animation Options & CSS Properties as Methods section of the @okikio/animate readme).

Restrictions & Limitations

@okikio/animate isn’t perfect, nothing really is, and seeing as the Web Animation API is a living standard which is constantly being improved, @okikio/animate still has lots of space to grow, though I am constantly trying to improve it and would love your input, you can go to the Github repo open a new issue, create a pull request or we can have a discussion in Github Discussions.

The first limitation is that it doesn’t really have a timeline built-in, there are a couple reasons for this:

1. I ran out of time. I am still only a student, I don’t have lots of time to dedicate to developing all the projects I want to work on, and I simply just ran out of time.

2. I didn’t think a formal timeline was needed, as async/await programming was supported. Also, I added timelineOffset as an animation option, if anyone ever needs to create something similar to animejs’s timeline.

3. I wanted to make @okikio/animate as small as I could.

4. With GroupEffects and SequenceEffects coming soon, I thought it would be best to leave the package small until an actual need was present. Note: I highly suggest reading Daniel C. Wilson’s blog on the Web Animation API’s especially the 4th article in the series discussing GroupEffects and SequenceEffects (https://danielcwilson.com/blog/2015/09/animations-part-4/).

Another limitation on

@okikio/animate
is that it doesn’t support custom easing’s like spring, elastic, etc… but from what I can tell that’s already in development, read more on Jake Archibald’s Easing Worklet proposal (https://github.com/jakearchibald/easing-worklet). He discusses the multiple standards in discussion, I currently prefer his proposal, as it’s the easiest to implement and the most elegant. 

The last limitation was dealt with as of @okikio/[email protected], but there are still some limitations on CSS Properties that support color, check the Github release for more detail.

For example,


animate({
    targets: [".div", document.querySelectorAll(".el")],
    // By default "px", will be applied
    translateX: 300,
    rotate: 120, 
    left: 500,
    margin: "56 70 8em 70%",

    // No units will be auto applied
    color: "rgb(25, 25, 25)",
    "text-shadow": "25px 5px 15px rgb(25, 25, 25)"
});


Looking to the Future

As of right now some future features are just right around the corner, for example, the ScrollTimeline. I don’t think anyone actually knows when it’s getting released but since the ScrollTimeline works as of Chrome Canary 92, I think it’s safe to say it getting released fairly soon.

I built the timeline animation option into @okikio/animate to future proof it, you can check out an example here:

(Note: it may not work on your browser, you may need to use the Canary version of Chrome or turn on Experimental Web Platform features in Chrome Flags. From what I can tell it just works on Firefox, though, so…. 🤣).

I based my example off Bramus’s: https://codepen.io/bramus/pen/GRjPggQ

If you want to read more on the ScrollTimeline I would suggest reading Bramus’s article on it, he goes into it in depth (https://www.bram.us/2021/02/23/the-future-of-css-scroll-linked-animations-part-1/).

I would also suggest reading the Google Developers article on Animation Worklets (https://developers.google.com/web/updates/2018/10/animation-worklet).

Polyfills

The complex demo example above in the usage-examples-demos section, actually uses the polyfills required to support older browsers. You are going to need web-animations-next.min.js from web-animations-js, as in other to support timelines, and other modern features the KeyframeEffect constructor is required. 

For the polyfill, I use js to test if the KeyframeEffect was supported and if not to load the polyfill check out build/ts/webanimation-polyfill.ts in the Github repo, make sure to not add async/defer to the polyfill, or it will not work the way you expect, you should also polyfill Map, Set, and Promise.


<html>
  <head>
    <!-- Async -->
    <script src="https://cdn.polyfill.io/v3/polyfill.min.js?features=default,es2015,es2018,Array.prototype.includes,Map,Set,Promise" async></script>

    <!-- NO Async/Defer -->
    <script src="./js/webanimation-polyfill.min.js"></script>
  </head>
  <body>
    <!-- Content -->
  </body>
</html>

When building for es6+ I highly recommend using esbuild for transpiling, bundling, and minifing. When building for es5, I suggest using esbuild (minify off), typescript (target of es5) & terser; as of now, this is the fastest setup for transpiling to es5, you can checkout the gulpfile from the demo for more details. 

Conclusion

@okikio/animate is a wrapper around the Web Animation API (WAAPI) that allows you to use all the features you love from animejs and other animation libraries, in a small and concise package.

Read more about it on npm or Github.

So, what are your thoughts on @okiko/animate, leave a comment on the dev.to article in the link below or join the discussion on Github Discussions.

Also published on dev.to at https://dev.to/okikio/okikio-animate-animejs-but-built-on-the-web-animation-api-nin