Product
Introducing Ruby Support in Socket
Socket is launching Ruby support for all users. Enhance your Rails projects with AI-powered security scans for vulnerabilities and supply chain threats. Now in Beta!
This is an experimental animation library. Its primary goals will be:
Warning: This is currently a proof-of-concept only. Not intended for use in production.
npm install motion@alpha
import { animate } from "motion"
const target = {
backgroundColor: "green",
transform: "translateX(100px)",
}
const options = { duration: 0.4, stagger: 0.2 }
animate("div", target, options)
animate(
selector: Element | Element[] | NodeList | string,
target: Keyframe | Keyframes[],
options: AnimationOptions
)
duration
number
: In seconds. Defaults to 0.3
.
How long the animation will play for.
delay
number
: In seconds. Defaults to 0
.
Delay the start of the animation by this duration.
animate("div", [{ scale: 0.5 }, { scale: 1.2 }], { delay: 1 })
easing
string | number[]
: Currently either a string defining a DOM easing function or an array of numbers to define a cubic bezier curve.
stagger
number
: In seconds. Defaults to 0
.
If animating multiple elements, add this duration to each delay
.
repeat
number
: Defaults to 0
.
Number of times to repeat the animation. Can be defined as Infinity
.
initialProgress
number
: In 0
-1
progress. Defaults to 0
.
How far through the animation to start.
One of the great benefits of WebAnimations API (WAAPI) is the ability to run animations off the main thread. But while this is a great benefit, there are others.
For instance, the ability to animate between different color types has been absent from all my animation libraries due to the filesize cost of conversion functions. For the same reason, Popmotion's ability to interpolate between complex strings is much stricter than the browsers, for instance limiting you to interpolating between shadow lists of the same length.
Framer Motion has the ability to animate properties like width
and translateX
between different value types. But in addition to a filesize cost, this has a runtime cost as we need to measure the DOM in order to turn all measurements into pixels.
We get all this for free in WAAPI.
On the contrary, the WAAPI is often non-intuitive. For example, its default behaviour is that a completed animation leaves an element in the state it was in before the animation started. Likewise common use-cases like stagger are left to userland.
I think there's already value in a simple wrapper API that can smooth over its rough edges. However as the API has hard limitations that I've always considered show-stoppers, I've never bothered, but now I wonder if there's a way out of all of these:
The best-performing animation props are opacity
and transform
. But transform
is really a collection of many props, so in all my animation libraries I've made it possible to animate them with shorthand syntax and animate them separately:
<motion.div animate={{ x: 100, scaleX: 2 }} />
Until now this has been impossible with WAAPI. The spec binds itself tightly to the limitations of CSS and this doesn't allow for the individual setting of values.
But recently the CSS Properties and Values API offers us a way out. This would allow us to register individual transforms as CSS variables and animate those instead.
Animating these values individually would lose us the ability to animate them between unit types, but would gain us the ability to offer default unit types.
// 👍 x could default to "px"
animate("div", [{ x: 10 }, { x: 100 }])
// 👎 Unit type interpolation on individual transforms
animate("div", [{ x: "10%" }, { x: 100 }])
// 👍 Different unit types with full transform string
animate("div", [{ transform: "translateX(10%)" }, { x: "translateX(100px)" }])
This would have to be a little ways down the road as Firefox and Safari have been slow to implement.
WAAPI offers the easing functions it offers and nothing more. The most bizarre limitation of the upcoming AnimationWorklet is that this doesn't offer a way around this either, without some weird hacks.
But as I thought about the remaining benefits of WAAPI once you remove the off-thread animations, I realised that these weird hacks are transportable to the synchronous world too, so we can introduce spring animations and custom easing today.
The idea is that you provide the defined animation headroom and then animate its currentTime
using Popmotion.
import { animate } from "popmotion"
// WAAPI
const animation = element.animate(
[
{},
// This is your real target
{ backgroundColor: "red", transform: "translateX(100px)" },
// This is your headroom
{ backgroundColor: "red", transform: `translateX(${100 * 2}px)` },
],
{
// This is double your desired animation duration
duration: 2000,
}
)
// We'll do the rest, thanks v.much
animation.pause()
// Animate using a Popmotion spring animation or custom easing
animate({
to: 1000,
elapsed: -1000,
type: "spring",
...options,
onUpdate: (v) => (animation.currentTime = v),
})
Using the smallest parts of Popmotion to provide synchronous time-based and spring animations would probably only amount to a ~3kb overall bundlesize.
As there'd only be a single spring animation powering all the animating values it'd be a much cheaper runtime than normal spring animations, in addition to all the benefits of browser interpolation.
FAQs
A tiny, performant animation library for the web
The npm package motion receives a total of 275,434 weekly downloads. As such, motion popularity was classified as popular.
We found that motion demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket is launching Ruby support for all users. Enhance your Rails projects with AI-powered security scans for vulnerabilities and supply chain threats. Now in Beta!
Product
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
Product
We're launching a new set of license analysis and compliance features for analyzing, managing, and complying with licenses across a range of supported languages and ecosystems.