spring-easing
Quick and easy spring animation. Works with other animation libraries (gsap...
README
spring-easing
A frame represent a single frame of an animation
_Note: the spring-easing package also supports 4 extra variants of [spring](https://spring-easing.okikio.dev/modules.html#SpringFrame), namely [spring-in](https://spring-easing.okikio.dev/modules.html#SpringInFrame), [spring-out](https://spring-easing.okikio.dev/modules.html#SpringOutFrame), [spring-out-in](https://spring-easing.okikio.dev/modules.html#SpringOutInFrame), and [spring-in-out](https://spring-easing.okikio.dev/modules.html#SpringInOutFrame), you can use these easing to create some really unique spring like animations._
_Check out the spring easing variants on Codepen._
_Attention: This entire library is a lightweight version of the [CustomEasing](https://native.okikio.dev/animate/api/custom-easing/) implemented in [@okikio/animate](https://native.okikio.dev/animate), which supports only string and number interpolation. If you'd like the complete CustomEasing with color interpolation, complex value interpolation, and more, go through the source code as a Github Gist, which is licensed under the MIT license._
<br>
Installation
- ``` sh
- npm install spring-easing
- ```
Others
- ``` sh
- yarn add spring-easing
- ```
- ``` sh
- pnpm install spring-easing
- ```
Usage
- ```ts
- import { SpringEasing } from "spring-easing";
- // or
- import SpringEasing from "spring-easing";
- ```
- ``` html
- <script src="https://unpkg.com/spring-easing" type="module"></script>
- <script type="module">
- // You can then use it like this
- const { SpringEasing } = window.SpringEasing;
- </script>
- ```
- ```ts
- import SpringEasing from "https://cdn.skypack.dev/spring-easing";
- // or
- import SpringEasing from "https://cdn.jsdelivr.net/npm/spring-easing";
- // or any number of other CDN's
- ```
Use with Animation Libraries
_Note: I cannot guarantee that every animation library works with spring-easing, for example, if an animation library doesn't support array values as keyframes, it won't work well with spring-easing._
| Animation | Support | Demo |
|---|---|---|
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| [GSAP](https://greensock.com/) | ✅ | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |
| [animejs](https://animejs.com) | ✅ | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |
| [Framer | ✅ | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |
| [Motion | ✅ | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |
| [@okikio/animate](https://okikio.github.io/native/packages/animate) | ✅ | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |
| [Web | ✅ | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |
- ```ts
- import anime from "animejs";
- import { SpringEasing, SpringOutFrame } from "spring-easing";
- // Note: this is the return value of `SpringEasing` and `GenerateSpringFrames`
- let [translateX, duration] = SpringEasing([0, 250], {
- easing: "spring-out-in(1, 100, 10, 0)",
- // You can change the size of Array for the SpringEasing function to generate
- numPoints: 200,
- // The number of decimal places to round, final values in the generated Array
- // This option doesn't exist on `GenerateSpringFrames`
- decimal: 5,
- });
- anime({
- targets: "div",
- // Using spring easing animate from [0 to 250] using `spring-out-in`
- translateX,
- // You can interpolate between strings
- // You can set the easing without an easing options object
- // You can interpolate between more than 2 values
- // Remember the `0` index of `SpringEasing` is an array of spring animation keyframes
- rotate: SpringEasing(
- ["0turn", 1, 0, 0.5],
- [SpringOutFrame, 1, 100, 10, 0]
- )[0],
- // TIP... Use linear easing for the proper springy effect
- easing: "linear",
- // The optimal duration for this specific spring configuration, e.g. mass, velocity, damping, etc...
- duration,
- });
- ```
_Note: make sure to read the comments above, as they are valuable resources for understanding what is happening._
Check out this demo on Codepen
Showcase
API
What's New...
REVERT _The new interpolation syntax has been reverted and removed; instantNumber, etc... functions have been renamed to interpolateNumber, etc..._
NEW _Re-introduced instantaneous interpolation functions._
e.g.
import { interpolateNumber, interpolateString, interpolateSequence, interpolateComplex } from "spring-easing";
These functions represent the interpolated value at a specific instance in time, where time is represented by t with a range of 0 to 1.
You can use these functions as building blocks to create your own custom interpolation functions.
NEW _(deprecated) interpolateUsingIndex is now an alias of interpolateSequence, it still keeps the same functionality._
The recommendation is to use interpolateSequence instead of interpolateUsingIndex, but you can still keep using interpolateUsingIndex, but beware it can be removed in future versions.
<strike> NEW _Re-introduced instantaneous interpolation functions._
e.g.
import { instantNumber, instantString, instantSequence, instanceComplex } from "spring-easing";
These functions represent the interpolated value at a specific instance in time, where time is represented by t with a range of 0 to 1.
You can use these functions as building blocks to create your own custom interpolation functions.
</strike>
<strike> BREAKING CHANGE _Interpolation functions use a new syntax._
_In older versions of spring-easing interpolation functions used to follow a syntax called the instantaneous interpolation function (t, values, decimal) => string | number | any, the new syntax is called interpolation function (frames, values, decimal) => string[] | number[] | any[]._
_The key difference between both syntaxes are the parameters each function takes and the return value of each function._
_The older syntax returned instantaneous frame values at a specific t-value, but the new syntax returns all the frames that make the entire animation, allowing for performance optimizations that couldn't be done before._
_For the most part this shouldn't leave too much of an effect as all the built-in interpolation functions have been updated to use the new synatax._
e.g.
function interpolateNumber(frames: number[], values: number[], decimal = 3) {
// nth index
const n = values.length - 1;
return frames.map(t => {
// The current index given t
const i = limit(Math.floor(t * n), 0, n - 1);
const start = values[i];
const end = values[i + 1];
const progress = (t - i / n) * n;
return toFixed(scale(progress, start, end), decimal);
});
}
SpringEasing([0, 250], spring, interpolateNumber)
</strike>
<strike> NEW _There is a new toAnimationFrames function that be used on instantaneous interpolation functions, to transform them into complete animation interpolation functions._
e.g.
import { SpringEasing, toAnimationFrames, toFixed, scale, limit } from "spring-easing";
function interpolateNumber(t: number, values: number[], decimal = 3) {
// nth index
const n = values.length - 1;
// The current index given t
const i = limit(Math.floor(t * n), 0, n - 1);
const start = values[i];
const end = values[i + 1];
const progress = (t - i / n) * n;
return toFixed(scale(progress, start, end), decimal);
}
function interpolatePixels(t: number, values: number[], decimal = 3) {
const result = interpolateNumber(t, values, decimal);
return ${result}px;
}
SpringEasing(
[0, 250],
'spring',
toAnimationFrames(interpolatePixels)
);
</strike>
NEW _Easily register new easing functions._
e.g.
import { SpringEasing, registerEasingFunction } from "spring-easing";
registerEasingFunction("linear", (t) => t);
registerEasingFunctions({
quad: (t) => Math.pow(t, 2),
cubic: (t) => Math.pow(t, 3),
});
SpringEasing(
[0, 250],
'linear'
);
SpringEasing(
[0, 250],
'quad'
);
NEW _SpringEasing now support interpolating between strings. It treats the units of the first value as the units for the rest of the values to interpolate between._
e.g.
SpringEasing(["0turn", "1px", "18rem", "125deg", 25], ...)
_Important All the values above get transformed to ["0turn", "1turn", "18turn", "125turn", "25turn"], before being interpolated._
NEW _interpolateStrings, interpolateUsingIndex, and interpolateComplex, are now built-in, they allow for supporting string keyframes._
NEW _Custom interpolation functions are now supported._
e.g.
import { interpolateNumber, toFixed, scale, limit } from "spring-easing";
// ...
export function interpolateColor(t: number, values: string[], decimal = 3) {
const color = transpose(...values.map((v) => rgba(v)))
.map((colors: number[], i) => {
const result = interpolateNumber(t, colors);
return i < 3 ? Math.round(result) : toFixed(result, decimal);
});
return rgba(${color.join()});
}
SpringEasing(["red", "green", "#4f4"], "spring", interpolateColor);
_Important The logic for color interpolation is defined in this tests/utils/interpolate-color.ts._
| Properties | Default |
|---|---|
| ----------- | ----------------------- |
| `easing` | `spring(1, |
| `numPoints` | `50` |
| `decimal` | `3` |
| Parameter | Default |
|---|---|
| --------- | ------------- |
| mass | `1` |
| stiffness | `100` |
| damping | `10` |
| velocity | `0` |
_Note: the return value of the SpringEasing function is actually [Array of keyframes , duration], in that order._
Browser Support
| Chrome | Edge | Firefox | Safari | IE |
|---|---|---|---|---|
| ------ | ---- | ------- | ------ | --- |
| 4+ | 12+ | 4+ | 4+ | 10+ |
Contributing
- ``` sh
- npm install
- ```
- ``` sh
- npm test
- ```
- ``` sh
- npm run build
- ```
- ``` sh
- npm run typedoc && npm run preview
- ```
_Note: this project uses Conventional Commits standard for commits, so, please format your commits using the rules it sets out._
探客时代
