This all started when I was looking to add scroll based animations to the home page of this portfolio. I set out to find a library to help a bit with that. There’s quite a few in the wild. Time-based animations libraries that I could then tie to the scroll position (like greensock, anime.js, velocity or tweenjs). Or more scroll specific things (like scrollmagic).
While they all seemed to do a pretty good job (a lot of websites use them in production), they all had one major flaw to me. They’re all quite monolithic. They provide plenty, and your users download all that plenty, whether your website uses 1% or 99% of their features.
I used this as an excuse to explore how animations could be expressed through functions, rather than OOP APIs. Looking to compose just the features that the animations needed to limit what visitors would have to download. Let’s see how it went!
A simple starting point
Before diving into complex animations driven by scroll, let’s start with a more restricted case: a simple time driven fade-in. Written in plain JS, this goes like this:
Definitely smaller than embedding a library. But while it’s nice to know how to write it all from scratch by hand, a bit of abstraction would help to reuse things from one animation to another.
Divide and conquer
The code above mixes two main parts of the animation:
– generating some measure of
progress (here using requestAnimationFrame ticks)
– interpolating this
progress into updates of the UI (here with
So let’s split things up accordingly.
That’s a first step! We can use our
timer to power all kinds of animations. And control the
fadeIn from other sources of progress… the scroll position maybe.
Progress on scroll
A time-based source of progress works like this: “run for N ms (after a delay of D ms maybe)”. In the same spirit, a scroll based source of progress would go “run for N% of the scroll (after a delay of D% maybe)”. Pixels would work too, but given the diversity of screen heights around… best use percents.
So let’s create just that (ignoring for now that the viewportHeight might change when resizing the browser):
This is just a simple base to start with. From there, there’s plenty more to explore, keeping this idea of composing functions to create animations. While creating this portfolio, I touched on:
And other topics come to mind too:
- enhancing the rudimentary timer: play/pause, reset, seek, repeat (alternating)
- splitting the computation of values from their use, so they can be applied via CSS variables (to keep specificity low), used with canvas…
- listening on progress, obtaining a promise of animation completion
I’ve started to gather some code on the tinymation project on Github. If you have thoughts on the topic, maybe specific use case, I’d be really happy to head about them. Feel free to look at the code and add issues (or comment on the existing ones).