Popmotion

The animator's toolbox

npm version npm downloads Twitter Follow

Popmotion is:

  • Powerful: It supports keyframe and spring animations for numbers, colors and complex strings.
  • Low level: It's designed to be composable and portable into any JavaScript environment, with an eye on worklets in the future.
  • Stable: It's written in TypeScript and enjoys over 95% test coverage.
  • Tiny: animate is just ~4.5kb, and every function is individually importable.

Quick start

npm install popmotion
import { animate } from "popmotion"

animate({
  from: 0,
  to: 100,
  onUpdate: latest => console.log(latest)
})

Animation

animate

animate performs a keyframes or spring animation.

import { animate } from "popmotion"

animate({
  from: 0, 
  to: 100,
  onUpdate: latest => console.log(latest)
})

It can animate numbers:

animate({ from: 0, to: 100 })

Or strings of the same type:

animate({ from: "0px", to: "100px" })
animate({ from: "#fff", to: "#000" })

The strings can be pretty complex, for instance box shadows or SVG path definitions. The only limitation is that the numbers and colors contained within must be in the same order:

animate({
  from: "0px 0px 0px rgba(0, 0, 0, 0)",
  to: "10px 10px 0px rgba(0, 0, 0, 0.2)"
})

The type of animation performed will be automatically detected from the provided options, or can be chosen manually by defining type as "keyframes", "spring" or "decay".

Options

These options can be set for all animations:

from

An initial value to start the animation from.

Defaults to 0

animate({
  from: "linear-gradient(#e66465, #9198e5)",
  to: "linear-gradient(#9198e5, #e66465)"
})
elapsed

Sets an initial elapsed time, in milliseconds. Set to a negative value for a delay.

animate({
  to: 100,
  elapsed: -300
})
repeat

The number of times to repeat the animation. Set to Infinity to repeat forever.

animate({
  to: 100,
  repeat: 2
})
repeatDelay

The duration, in milliseconds, to wait before repeating the animation.

animate({
  to: 100,
  repeat: 2,
  repeatDelay: 200
})
repeatType

Either "loop", "mirror" or "reverse". Defaults to "loop".

  • "loop": Repeats the animation from 0.
  • "mirror": Swaps the from/to values alternately.
  • "reverse": Reverses the animation alternately.
animate({
  to: 100,
  repeat: 2,
  repeatType: "reverse"
})
driver

By default, the animation will be driven by a requestAnimationFrame loop. driver can specify a different source.

A Driver is a function that accepts the animations update function. This is a function that can be called with a time delta from the previous frame. The Driver must return a function that will be called when the animation is stopped.

const xrDriver = session => update => {
  let latestRequestId = 0
  let prevTimestamp = performance.now()
  
  const step = timestamp => {
    const delta = timestamp - prevTimestamp
    prevTimestamp = timestamp

    update(delta)

    latestRequestId = session.requestAnimationFrame(step)
  }

  let latestRequestId = session.requestAnimationFrame(step)

  return () => session.cancelRequestAnimationFrame(latestRequestId)
}

animate({
  to: 100,
  driver: xrDriver(xrSession)
})
type

animate will automatically detect the type of animation to use based on the options provided. But a specific type can be chosen manually by defining type as "keyframes", "spring" or "decay".

animate({
  to: 100,
  type: "spring"
})

Lifecycle events

The following lifecycle events are available for all animations:

onUpdate

This is called every frame the animation fires with the latest computed value.

animate({
  to: 100,
  onUpdate: latest => console.log(latest)
})
onPlay

This is called when the animation starts. Currently this automatically when animate is called.

animate({
  to: 100,
  onPlay: () => {}
})
onComplete

This is called when the animation successfully completes.

animate({
  to: 100,
  onComplete:() => {}
})
onRepeat

This is called when an animation repeats.

animate({
  to: 100,
  repeat: 2,
  onRepeat: () => {}
})
onStop

This is called when the animation is stopped by the stop control.

const animation = animate({
  to: 100,
  onStop: () => {}
})

animation.stop()

Keyframes options

A keyframes animation is the default animation type and it can be defined either with a from and to option:

animate({ from: 0, to: 100 })

Or as a series of keyframes provided to the to option:

animate({ to: [0, 100, 200] })
to

A single value to animate to, or an array of values to animate through.

animate({
  to: ["#0ff", "#f00", "#0f0"]
})

If to is an array, any defined from will be ignored.

duration

This defines the duration of the animation, in milliseconds.

animate({
  to: 100,
  duration: 300
})
ease

This is an easing function, or array of functions, to use when easing between each keyframe.

import { animate, linear, easeInOut } from "popmotion"

animate({
  to: 100,
  ease: linear
})

animate({
  to: ["#fff", "#000", "#f00"],
  ease: [linear, easeInOut]
})

If set as any array, the length of this array must be one shorter than the number of values being animated between.

offset

This is an array of values between 0 and 1 that defines at which point throughout the animation each keyframe should be reached.

This array should be the same length as the number of defined keyframes.

animate({
  to: ["#fff", "#000", "#f00"],
  offset: [0, 0.2, 1]
})

Spring options

Springs are great for creating natural-feeling interfaces and dynamic interruptable animations.

A spring animation will be used if any of the stiffness, damping or mass options are detected.

Note: A spring simulation is inherently numerical so if it's given a color, array or object, it runs the animation from 0 to 100 and interpolates that to the given values. This strategy is likely to be tweaked before the official release so animations made this way may change in feel.

to

A single value to animate to.

animate({
  to: 100,
  type: "spring"
})

If to is an array, any defined from will be ignored.

stiffness

This defines the stiffness of the spring. A higher stiffness will result in a snappier animation.

Defaults to 100

animate({
  to: 100,
  stiffness: 1000
})
damping

This is the opposing force to stiffness. As you reduce this value, relative to stiffness, the spring will become bouncier and the animation will last longer. Likewise, higher relative values will have less bounciness and result in shorter animations.

Defaults to 10

animate({
  to: 100,
  damping: 50
})
mass

This is the mass of the animating object. Heavier objects will take longer to speed up and slow down.

Defaults to 1.

animate({
  to: 100,
  mass: 2
})
velocity

The initial velocity, in units per second, of the animation.

animate({
  to: 100,
  velocity: 1000
})
duration

The duration of the spring, in milliseconds.

Will be overridden by stiffness, mass or damping.

animate({
  to: 100,
  duration: 1000
})
bounce

The bounciness of the spring, as a value between 0 and 1, where 0 is no bounce.

Will be overridden by stiffness, mass or damping.

animate({
  to: 100,
  bounce: 0.2
})
restDelta

The distance from the animation target at which the animation can be considered complete. When both restDelta and restSpeed are met, the animation completes.

animate({
  to: 100,
  restDelta: 0.5
})
restSpeed

The absolute velocity, in units per second, below which the animation can be considered complete. When both restDelta and restSpeed are met, the animation completes. Defaults to 10.

animate({
  to: 100,
  restSpeed: 5
})

Playback controls

animate returns PlaybackControls, which can be used to control the playback of the animation.

Currently this only includes a stop method, but may expand with more.

stop

Stops the animation.

const playback = animate({ from: 0, to: 100 })
playback.stop()

inertia

The inertia animation is used to gradually decelerate a number. Think smartphone scroll momentum.

Options

In addition to animate's from, onUpdate and onComplete options, inertia also supports the following:

velocity

The initial velocity, in units per second, of the animation.

inertia({
  from: 0,
  velocity: 100
})
power

A constant with which to calculate a target value. Higher power = further target.

Defaults to 0.8.

inertia({
  from: 0,
  power: 0.3
})
timeConstant

Adjusting the time constant will change the duration of the deceleration, thereby affecting its feel.

Defaults to 350.

inertia({
  from: 0,
  velocity: 100,
  timeConstant: 400
})
modifyTarget

A function that receives the calculated target and returns a new one. Useful for snapping the target to a grid.

const roundToNearest = target => v => Math.ceil(v / target) * target

inertia({
  from: 0,
  velocity: 100,
  modifyTarget: roundToNearest(100)
})
min

The minimum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.

inertia({
  from: 50,
  velocity: -100,
  min: 0
})
max

The maximum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.

inertia({
  from: 50,
  velocity: 100,
  max: 100
})
bounceStiffness

This defines the stiffness of the spring when the animation hits either min or max. A higher stiffness will result in a snappier animation.

Defaults to 500

inertia({
  from: 0,
  velocity: 100,
  max: 50,
  bounceStiffness: 1000
})
bounceDamping

This is the opposing force to bounceStiffness. As you reduce this value, relative to bounceStiffness, the spring will become bouncier and the animation will last longer. Likewise, higher relative values will have less bounciness and result in shorter animations.

Defaults to 10

inertia({
  from: 0,
  velocity: 100,
  max: 50,
  bounceDamping: 300
})
restDelta

The distance from the animation target at which the animation can be considered complete.

inertia({
  from: 0,
  velocity: 100,
  restDelta: 0.5
})

Iterators

Powering animate and inertia are the keyframes, spring, and decay iterators.

import { keyframes, spring, decay } from "popmotion";

Iterators give you the ability to run an animation with a high degree of control. For example, Framer uses the spring iterator to draw its animation editor visualiser by running it synchronously.

Each can be initialised with the matching options above (decay with a subset of inertia's options, excluding the bounce- options):

const animation = spring({
  from: 0,
  to: 100,
  stiffness: 200
})

With the returned iterator, you can resolve the animation at a specific timestamp with its next method.

// Resolve the animation at 200ms
const { value, done } = animation.next(200)

Easing

Popmotion includes a number of in-built easing functions, as well as factory functions to make entirely new ones.

Functions

Each easing function can be imported like so:

import { linear } from "popmotion"

Each function accepts a progress value between 0 and 1, and returns a new one:

const progress = 0.5
const easedProgress = easeInOut(progress)
  • linear
  • easeIn
  • easeInOut
  • easeOut
  • circIn
  • circInOut
  • circOut
  • backIn
  • backInOut
  • backOut
  • anticipate
  • bounceIn
  • bounceInOut
  • bounceOut

Factories

cubicBezier

import { cubicBezier } from "popmotion"

const easing = cubicBezier(0, .42, 0, 1)

New cubic bezier definitions can be created in the Framer animation editor and copy/pasted directly into this function.

steps

steps returns an easing function that will convert the animation into a discrete series of steps.

import { steps } from "popmotion"

const easing = steps(5)

It optionally accepts a second parameter, either "start" or "end" (default)that decides whether the steps are aligned with the start or end of the animation.

steps(5, "start")

mirrorEasing

Mirrors an existing easing function.

reverseEasing

Reverses an existing easing function. For instance, providing it easeIn would return an easeOut.

import { reverseEasing, linear } from "popmotion"

const reversed = reverseEasing(linear)
reversed(1) // 0
reversed(0.5) // 0.5
reversed(0) // 1

createExpoIn

Creates an easing function based on the exponent of the provided power. The higher the power, the stronger the easing.

import { createExpoIn } from "popmotion"

const expoIn = createExpoIn(4)

The returned easing function is an ease in, which means it starts slow and finished fast. mirrorEasing and reverseEasing can be used to create ease in out, and ease out variations:

const expoIn = createExpoIn(4)
const expoOut = mirrorEasing(easeIn)
const expoInOut = reverseEasing(easeIn)

createBackIn

Creates an easing function with an overshoot. It accepts a power value, the higher the power the stronger the overshoot.

import { createBackIn } from "popmotion"

const backIn = createBackIn(4)

The returned easing function is an ease in, which means the overshoot happens at the start of the animation. mirrorEasing and reverseEasing can be used to create ease in out, and ease out variations:

const backIn = createBackIn(4)
const backOut = mirrorEasing(easeIn)
const backInOut = reverseEasing(easeIn)

createAnticipate

Creates an easing that pulls back a little before animating out with an overshoot. The stronger the power the bigger the overshoot.

import { createAnticipate } from "popmotion"

const anticipate = createAnticipate(4)

Utils

angle

Returns an angle between two points, in degrees.

import { angle } from "popmotion"

angle(
  { x: 0, y: 0 },
  { x: 45, y: 100 }
)

attract

import { attract } from "popmotion"

attract(5, 10, 12)

attractExpo

import { attractExpo } from "popmotion"

attractExpo(5, 10, 12)

clamp

Clamp a value to within the given range.

import { clamp } from "popmotion"

const min = 50
const max = 100
clamp(min, max, 150) // 100

degreesToRadians

Converts degrees to radians.

import { degreesToRadians } from "popmotion"

degreesToRadians(45) // 0.785...

distance

Returns the distance between two numbers, two 2D points, or two 3D points.

import { distance } from "popmotion"

distance(10, 50)
distance({ x: 0, y: 0 }, { x: 45, y: 100 })
distance({ x: 0, y: 0, z: 100 }, { x: 45, y: 100, z: 0 })

interpolate

Creates a function that will interpolate from an linear series of numbers, to a non-linear series of numbers, strings of the same numerical format, colours, or arrays/objects of those.

import { interpolate } from "popmotion"

const mapXToOpacity = interpolate(
  [-100, 0, 100],
  [0, 1, 0]
)
mapXToOpacity(-50) // 0.5

const mapProgressToValues = interpolate(
  [0, 1],
  [
    { x: 0, color: "#fff" },
    { x: 100, color: "#000" }
  ]
)
mapProgressToValues(0.5) // { x: 50, color: "#888" }

const rescale = interpolate(
  [0, 1],
  [100, 200],
  { clamp: false }
)
rescale(2) // 300

Options

interpolate accepts an optional third argument, an object of options.

  • clamp: Clamps values to within given range. Defaults to true.
  • ease: An Easing function, or array of easing functions, to ease the interpolation of each segment.
  • mixer: A function that, when provided a from and to value, will return a new function that accepts a progress value between 0 and 1 to mix between those two values. For integration with libraries like Flubber.

isPoint

Returns true if the provided argument is a 2D point.

import { isPoint } from "popmotion"

isPoint({ x: 0 }) // false
isPoint({ x: 0, y: 0 }) // true

isPoint3D

Returns true if the provided argument is a 3D point.

import { isPoint3D } from "popmotion"

isPoint3D({ x: 0 }) // false
isPoint3D({ x: 0, y: 0 }) // false
isPoint3D({ x: 0, y: 0, z: 0 }) // true

mix

Will mix between two values, given progress as a third argument.

import { mix } from "popmotion"

mix(0, 100, 0.5) // 50
mix(0, 100, 2) // 200

mixColor

Returns a function that, when provided a progress value, will mix between two colors. Accepts hex, rgba and hsla colors.

import { mixColor } from "popmotion"

mixColor("#000", "#fff")(0.5) // "rgba(125, 125, 125, 1)"

mixComplex

Returns a function that, when provided a progress value, will mix between two strings with the same order of numbers and colors.

import { mixComplex } from "popmotion"

mixComplex("100px #fff", "0px #000")(0.5) // "50px rgba(125, 125, 125, 1)"

pointFromVector

Given a point, angle in degrees, and distance, will return a new point.

import { pointFromVector } from "popmotion"

const point = { x: 0, y: 0 }
const angle = 45
const distance = 100

pointFromVector(point, angle, distance)

progress

Given a min and a max range, and a value, will return the progress of the value within the range as normalised to a 0-1 range.

import { progress } from "popmotion"

const min = 100
const max = 200
progress(min, max, 150) // 0.5

radiansToDegrees

Converts radians to degrees.

import { radiansToDegrees } from "popmotion"

radiansToDegrees(0.785) // 45

snap

Creates a function that will snap numbers to the nearest in a provided array or to a regular interval.

import { snap } from "popmotion"

// Snap to regular intervals
const snapTo = snap(45);

snapTo(1); // 0
snapTo(40); // 45
snapTo(50); // 45
snapTo(80); // 90

// Snap to values in an array
const snapTo = snap([-100, -50, 100, 200]);

snapTo(-200); // -100
snapTo(-76); // -100
snapTo(-74); // -50

toDecimal

Rounds a number to a specific decimal place.

import { toDecimal } from "popmotion"

toDecimal(3.3333); // 3.33
toDecimal(6.6666, 1); // 6.67

velocityPerFrame

import { velocityPerFrame } from "popmotion"

velocityPerFrame(50, 16.7); // 0.835

velocityPerSecond

import { velocityPerSecond } from "popmotion"

velocityPerSecond(1, 16.7); // 59.880...

wrap

import { wrap } from "popmotion"

wrap(0, 1, 0.5); // 0.5
wrap(0, 1, 1.5); // 0.5

Popmotion/popmotion

{
"props": {
"initialPayload": {
"allShortcutsEnabled": false,
"path": "/",
"repo": {
"id": 23044617,
"defaultBranch": "master",
"name": "popmotion",
"ownerLogin": "Popmotion",
"currentUserCanPush": false,
"isFork": false,
"isEmpty": false,
"createdAt": "2014-08-17T16:23:07.000Z",
"ownerAvatar": "https://avatars.githubusercontent.com/u/14272617?v=4",
"public": true,
"private": false,
"isOrgOwned": true
},
"currentUser": null,
"refInfo": {
"name": "master",
"listCacheKey": "v0:1674785642.7013838",
"canEdit": false,
"refType": "branch",
"currentOid": "adf681efd8568ada018ce68082dbd585f25c4c7d"
},
"tree": {
"items": [
{
"name": ".circleci",
"path": ".circleci",
"contentType": "directory"
},
{
"name": ".github/ISSUE_TEMPLATE",
"path": ".github/ISSUE_TEMPLATE",
"contentType": "directory",
"hasSimplifiedPath": true
},
{
"name": ".storybook",
"path": ".storybook",
"contentType": "directory"
},
{
"name": "packages",
"path": "packages",
"contentType": "directory"
},
{
"name": "playground",
"path": "playground",
"contentType": "directory"
},
{
"name": "types",
"path": "types",
"contentType": "directory"
},
{
"name": ".babelrc",
"path": ".babelrc",
"contentType": "file"
},
{
"name": ".eslintrc",
"path": ".eslintrc",
"contentType": "file"
},
{
"name": ".gitignore",
"path": ".gitignore",
"contentType": "file"
},
{
"name": ".prettierignore",
"path": ".prettierignore",
"contentType": "file"
},
{
"name": "CODE_OF_CONDUCT.md",
"path": "CODE_OF_CONDUCT.md",
"contentType": "file"
},
{
"name": "CONTRIBUTING.md",
"path": "CONTRIBUTING.md",
"contentType": "file"
},
{
"name": "README.md",
"path": "README.md",
"contentType": "file"
},
{
"name": "lerna.json",
"path": "lerna.json",
"contentType": "file"
},
{
"name": "package.json",
"path": "package.json",
"contentType": "file"
},
{
"name": "rollup-generate-config.js",
"path": "rollup-generate-config.js",
"contentType": "file"
},
{
"name": "tsconfig.json",
"path": "tsconfig.json",
"contentType": "file"
},
{
"name": "tslint.json",
"path": "tslint.json",
"contentType": "file"
},
{
"name": "yarn.lock",
"path": "yarn.lock",
"contentType": "file"
}
],
"templateDirectorySuggestionUrl": null,
"readme": null,
"totalCount": 19,
"showBranchInfobar": false
},
"fileTree": null,
"fileTreeProcessingTime": null,
"foldersToFetch": [],
"treeExpanded": false,
"symbolsExpanded": false,
"isOverview": true,
"overview": {
"banners": {
"shouldRecommendReadme": false,
"isPersonalRepo": false,
"showUseActionBanner": false,
"actionSlug": null,
"actionId": null,
"showProtectBranchBanner": false,
"recentlyTouchedDataChannel": null,
"publishBannersInfo": {
"dismissActionNoticePath": "/settings/dismiss-notice/publish_action_from_repo",
"releasePath": "/Popmotion/popmotion/releases/new?marketplace=true",
"showPublishActionBanner": false
},
"interactionLimitBanner": null,
"showInvitationBanner": false,
"inviterName": null
},
"codeButton": {
"contactPath": "/contact",
"isEnterprise": false,
"local": {
"protocolInfo": {
"httpAvailable": true,
"sshAvailable": null,
"httpUrl": "https://github.com/Popmotion/popmotion.git",
"showCloneWarning": null,
"sshUrl": null,
"sshCertificatesRequired": null,
"sshCertificatesAvailable": null,
"ghCliUrl": "gh repo clone Popmotion/popmotion",
"defaultProtocol": "http",
"newSshKeyUrl": "/settings/ssh/new",
"setProtocolPath": "/users/set_protocol"
},
"platformInfo": {
"cloneUrl": "https://desktop.github.com",
"showVisualStudioCloneButton": false,
"visualStudioCloneUrl": "https://windows.github.com",
"showXcodeCloneButton": false,
"xcodeCloneUrl": "https://developer.apple.com",
"zipballUrl": "/Popmotion/popmotion/archive/refs/heads/master.zip"
}
},
"newCodespacePath": "/codespaces/new?hide_repo_select=true&repo=23044617"
},
"popovers": {
"rename": null,
"renamedParentRepo": null
},
"commitCount": "3,010",
"overviewFiles": [
{
"displayName": "README.md",
"repoName": "popmotion",
"refName": "master",
"path": "README.md",
"preferredFileType": "readme",
"tabName": "README",
"richText": "<article class=\"markdown-body entry-content container-lg\" itemprop=\"text\"><h1 tabindex=\"-1\" dir=\"auto\"><a id=\"\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a><a href=\"https://popmotion.io\" rel=\"nofollow\"><img src=\"https://user-images.githubusercontent.com/7850794/90245722-80926e80-de33-11ea-9c39-ea6c5b344217.png\" height=\"52\" width=\"243\" alt=\"Popmotion\" style=\"max-width: 100%;\"></a></h1>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-the-animators-toolbox\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#the-animators-toolbox\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>The animator's toolbox</h3>\n<p dir=\"auto\"><a href=\"https://www.npmjs.com/package/popmotion\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/aeeae50932eb354936d60f676d7a5bdd64f3d2925efbbab66489b773b2349426/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f706f706d6f74696f6e2e7376673f7374796c653d666c61742d737175617265\" alt=\"npm version\" data-canonical-src=\"https://img.shields.io/npm/v/popmotion.svg?style=flat-square\" style=\"max-width: 100%;\"></a>\n<a href=\"https://www.npmjs.com/package/popmotion\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/817d6339923abdbb42fe0d0aa640bd56d68a29c3c765d70c68784f9073c41fca/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f706f706d6f74696f6e2e7376673f7374796c653d666c61742d737175617265\" alt=\"npm downloads\" data-canonical-src=\"https://img.shields.io/npm/dm/popmotion.svg?style=flat-square\" style=\"max-width: 100%;\"></a>\n<a href=\"http://twitter.com/popmotionjs\" rel=\"nofollow\"><img src=\"https://camo.githubusercontent.com/62023c054cea8497e12bb1d3986731e8f74921a2d7180164a42be1fe6410f078/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f666f6c6c6f772f706f706d6f74696f6e6a732e7376673f7374796c653d736f6369616c266c6162656c3d466f6c6c6f77\" alt=\"Twitter Follow\" data-canonical-src=\"https://img.shields.io/twitter/follow/popmotionjs.svg?style=social&amp;label=Follow\" style=\"max-width: 100%;\"></a></p>\n<p dir=\"auto\">Popmotion is:</p>\n<ul dir=\"auto\">\n<li><strong>Powerful</strong>: It supports keyframe and spring animations for numbers, colors and complex strings.</li>\n<li><strong>Low level</strong>: It's designed to be composable and portable into any JavaScript environment, with an eye on worklets in the future.</li>\n<li><strong>Stable</strong>: It's written in TypeScript and enjoys over 95% test coverage.</li>\n<li><strong>Tiny</strong>: <code>animate</code> is just ~4.5kb, and every function is individually importable.</li>\n</ul>\n\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-quick-start\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#quick-start\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Quick start</h2>\n<div class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"npm install popmotion\"><pre>npm install popmotion</pre></div>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { animate } from &quot;popmotion&quot;\n\nanimate({\n from: 0,\n to: 100,\n onUpdate: latest =&gt; console.log(latest)\n})\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">animate</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">onUpdate</span>: <span class=\"pl-s1\">latest</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">latest</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-animation\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#animation\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Animation</h2>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-animate\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#animate\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>animate</h3>\n<p dir=\"auto\"><code>animate</code> performs a keyframes or spring animation.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { animate } from &quot;popmotion&quot;\n\nanimate({\n from: 0, \n to: 100,\n onUpdate: latest =&gt; console.log(latest)\n})\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">animate</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> \n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">onUpdate</span>: <span class=\"pl-s1\">latest</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">latest</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">It can animate numbers:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({ from: 0, to: 100 })\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">Or strings of the same type:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({ from: &quot;0px&quot;, to: &quot;100px&quot; })\nanimate({ from: &quot;#fff&quot;, to: &quot;#000&quot; })\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">from</span>: <span class=\"pl-s\">\"0px\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">to</span>: <span class=\"pl-s\">\"100px\"</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">from</span>: <span class=\"pl-s\">\"#fff\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">to</span>: <span class=\"pl-s\">\"#000\"</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">The strings can be pretty complex, for instance box shadows or SVG path definitions. The only limitation is that the numbers and colors contained within must be in the same order:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n from: &quot;0px 0px 0px rgba(0, 0, 0, 0)&quot;,\n to: &quot;10px 10px 0px rgba(0, 0, 0, 0.2)&quot;\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-s\">\"0px 0px 0px rgba(0, 0, 0, 0)\"</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-s\">\"10px 10px 0px rgba(0, 0, 0, 0.2)\"</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n\n<p dir=\"auto\">The type of animation performed will be automatically detected from the provided options, or can be chosen manually by defining <code>type</code> as <code>\"keyframes\"</code>, <code>\"spring\"</code> or <code>\"decay\"</code>.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-options\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#options\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Options</h4>\n<p dir=\"auto\">These options can be set for <strong>all animations</strong>:</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-from\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#from\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>from</h5>\n<p dir=\"auto\">An initial value to start the animation from.</p>\n<p dir=\"auto\">Defaults to <code>0</code></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n from: &quot;linear-gradient(#e66465, #9198e5)&quot;,\n to: &quot;linear-gradient(#9198e5, #e66465)&quot;\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-s\">\"linear-gradient(#e66465, #9198e5)\"</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-s\">\"linear-gradient(#9198e5, #e66465)\"</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-elapsed\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#elapsed\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>elapsed</h5>\n<p dir=\"auto\">Sets an initial elapsed time, in milliseconds. Set to a negative value for a delay.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n elapsed: -300\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">elapsed</span>: <span class=\"pl-c1\">-</span><span class=\"pl-c1\">300</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-repeat\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#repeat\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>repeat</h5>\n<p dir=\"auto\">The number of times to repeat the animation. Set to <code>Infinity</code> to repeat forever.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n repeat: 2\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">repeat</span>: <span class=\"pl-c1\">2</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-repeatdelay\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#repeatdelay\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>repeatDelay</h5>\n<p dir=\"auto\">The duration, in milliseconds, to wait before repeating the animation.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n repeat: 2,\n repeatDelay: 200\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">repeat</span>: <span class=\"pl-c1\">2</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">repeatDelay</span>: <span class=\"pl-c1\">200</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-repeattype\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#repeattype\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>repeatType</h5>\n<p dir=\"auto\">Either <code>\"loop\"</code>, <code>\"mirror\"</code> or <code>\"reverse\"</code>. Defaults to <code>\"loop\"</code>.</p>\n<ul dir=\"auto\">\n<li><code>\"loop\"</code>: Repeats the animation from <code>0</code>.</li>\n<li><code>\"mirror\":</code> Swaps the <code>from</code>/<code>to</code> values alternately.</li>\n<li><code>\"reverse\":</code> Reverses the animation alternately.</li>\n</ul>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n repeat: 2,\n repeatType: &quot;reverse&quot;\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">repeat</span>: <span class=\"pl-c1\">2</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">repeatType</span>: <span class=\"pl-s\">\"reverse\"</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-driver\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#driver\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>driver</h5>\n<p dir=\"auto\">By default, the animation will be driven by a <code>requestAnimationFrame</code> loop. <code>driver</code> can specify a different source.</p>\n<p dir=\"auto\">A <code>Driver</code> is a function that accepts the animations <code>update</code> function. This is a function that can be called with a time delta from the previous frame. The <code>Driver</code> must return a function that will be called when the animation is stopped.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const xrDriver = session =&gt; update =&gt; {\n let latestRequestId = 0\n let prevTimestamp = performance.now()\n \n const step = timestamp =&gt; {\n const delta = timestamp - prevTimestamp\n prevTimestamp = timestamp\n\n update(delta)\n\n latestRequestId = session.requestAnimationFrame(step)\n }\n\n let latestRequestId = session.requestAnimationFrame(step)\n\n return () =&gt; session.cancelRequestAnimationFrame(latestRequestId)\n}\n\nanimate({\n to: 100,\n driver: xrDriver(xrSession)\n})\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-en\">xrDriver</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">session</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-s1\">update</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">let</span> <span class=\"pl-s1\">latestRequestId</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">0</span>\n <span class=\"pl-k\">let</span> <span class=\"pl-s1\">prevTimestamp</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">performance</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">now</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span>\n \n <span class=\"pl-k\">const</span> <span class=\"pl-en\">step</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">timestamp</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">{</span>\n <span class=\"pl-k\">const</span> <span class=\"pl-s1\">delta</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">timestamp</span> <span class=\"pl-c1\">-</span> <span class=\"pl-s1\">prevTimestamp</span>\n <span class=\"pl-s1\">prevTimestamp</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">timestamp</span>\n\n <span class=\"pl-en\">update</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">delta</span><span class=\"pl-kos\">)</span>\n\n <span class=\"pl-s1\">latestRequestId</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">session</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">requestAnimationFrame</span><span class=\"pl-kos\">(</span><span class=\"pl-en\">step</span><span class=\"pl-kos\">)</span>\n <span class=\"pl-kos\">}</span>\n\n <span class=\"pl-k\">let</span> <span class=\"pl-s1\">latestRequestId</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">session</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">requestAnimationFrame</span><span class=\"pl-kos\">(</span><span class=\"pl-en\">step</span><span class=\"pl-kos\">)</span>\n\n <span class=\"pl-k\">return</span> <span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-s1\">session</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">cancelRequestAnimationFrame</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">latestRequestId</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span>\n\n<span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">driver</span>: <span class=\"pl-en\">xrDriver</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">xrSession</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-type\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#type\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>type</h5>\n<p dir=\"auto\"><code>animate</code> will automatically detect the type of animation to use based on the options provided. But a specific type can be chosen manually by defining <code>type</code> as <code>\"keyframes\"</code>, <code>\"spring\"</code> or <code>\"decay\"</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n type: &quot;spring&quot;\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">type</span>: <span class=\"pl-s\">\"spring\"</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-lifecycle-events\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#lifecycle-events\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Lifecycle events</h4>\n<p dir=\"auto\">The following lifecycle events are available for <strong>all animations</strong>:</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-onupdate\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#onupdate\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>onUpdate</h5>\n<p dir=\"auto\">This is called every frame the animation fires with the latest computed value.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n onUpdate: latest =&gt; console.log(latest)\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">onUpdate</span>: <span class=\"pl-s1\">latest</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-smi\">console</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">log</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">latest</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-onplay\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#onplay\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>onPlay</h5>\n<p dir=\"auto\">This is called when the animation starts. Currently this automatically when <code>animate</code> is called.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n onPlay: () =&gt; {}\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">onPlay</span>: <span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">{</span><span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-oncomplete\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#oncomplete\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>onComplete</h5>\n<p dir=\"auto\">This is called when the animation successfully completes.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n onComplete:() =&gt; {}\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">onComplete</span>:<span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">{</span><span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-onrepeat\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#onrepeat\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>onRepeat</h5>\n<p dir=\"auto\">This is called when an animation repeats.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n repeat: 2,\n onRepeat: () =&gt; {}\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">repeat</span>: <span class=\"pl-c1\">2</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">onRepeat</span>: <span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">{</span><span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-onstop\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#onstop\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>onStop</h5>\n<p dir=\"auto\">This is called when the animation is stopped by the <code>stop</code> control.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const animation = animate({\n to: 100,\n onStop: () =&gt; {}\n})\n\nanimation.stop()\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">animation</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-en\">onStop</span>: <span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-kos\">{</span><span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-s1\">animation</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">stop</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-keyframes-options\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#keyframes-options\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Keyframes options</h4>\n<p dir=\"auto\">A keyframes animation is the default animation type and it can be defined either with a <code>from</code> and <code>to</code> option:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({ from: 0, to: 100 })\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">Or as a series of keyframes provided to the <code>to</code> option:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({ to: [0, 100, 200] })\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">to</span>: <span class=\"pl-kos\">[</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">200</span><span class=\"pl-kos\">]</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-to\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#to\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>to</h5>\n<p dir=\"auto\">A single value to animate to, or an array of values to animate through.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: [&quot;#0ff&quot;, &quot;#f00&quot;, &quot;#0f0&quot;]\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s\">\"#0ff\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"#f00\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"#0f0\"</span><span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">If <code>to</code> is an array, any defined <code>from</code> will be ignored.</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-duration\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#duration\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>duration</h5>\n<p dir=\"auto\">This defines the duration of the animation, in milliseconds.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n duration: 300\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">duration</span>: <span class=\"pl-c1\">300</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-ease\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#ease\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>ease</h5>\n<p dir=\"auto\">This is an easing function, or array of functions, to use when easing between each keyframe.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { animate, linear, easeInOut } from &quot;popmotion&quot;\n\nanimate({\n to: 100,\n ease: linear\n})\n\nanimate({\n to: [&quot;#fff&quot;, &quot;#000&quot;, &quot;#f00&quot;],\n ease: [linear, easeInOut]\n})\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">animate</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">linear</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">easeInOut</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">ease</span>: <span class=\"pl-s1\">linear</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n\n<span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s\">\"#fff\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"#000\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"#f00\"</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">ease</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s1\">linear</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">easeInOut</span><span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">If set as any array, the length of this array must be one shorter than the number of values being animated between.</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-offset\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#offset\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>offset</h5>\n<p dir=\"auto\">This is an array of values between <code>0</code> and <code>1</code> that defines at which point throughout the animation each keyframe should be reached.</p>\n<p dir=\"auto\">This array should be the same length as the number of defined keyframes.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: [&quot;#fff&quot;, &quot;#000&quot;, &quot;#f00&quot;],\n offset: [0, 0.2, 1]\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-kos\">[</span><span class=\"pl-s\">\"#fff\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"#000\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"#f00\"</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">offset</span>: <span class=\"pl-kos\">[</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">0.2</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-spring-options\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#spring-options\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Spring options</h4>\n<p dir=\"auto\">Springs are great for creating natural-feeling interfaces and dynamic interruptable animations.</p>\n<p dir=\"auto\">A spring animation will be used if any of the <code>stiffness</code>, <code>damping</code> or <code>mass</code> options are detected.</p>\n<p dir=\"auto\"><strong>Note:</strong> A spring simulation is inherently numerical so if it's given a color, array or object, it runs the animation from <code>0</code> to <code>100</code> and interpolates that to the given values. This strategy is likely to be tweaked before the official release so animations made this way may change in feel.</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-to-1\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#to-1\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>to</h5>\n<p dir=\"auto\">A single value to animate to.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n type: &quot;spring&quot;\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">type</span>: <span class=\"pl-s\">\"spring\"</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">If <code>to</code> is an array, any defined <code>from</code> will be ignored.</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-stiffness\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#stiffness\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>stiffness</h5>\n<p dir=\"auto\">This defines the stiffness of the spring. A higher stiffness will result in a snappier animation.</p>\n<p dir=\"auto\">Defaults to <code>100</code></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n stiffness: 1000\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">stiffness</span>: <span class=\"pl-c1\">1000</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-damping\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#damping\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>damping</h5>\n<p dir=\"auto\">This is the opposing force to <code>stiffness</code>. As you reduce this value, relative to <code>stiffness</code>, the spring will become bouncier and the animation will last longer. Likewise, higher relative values will have less bounciness and result in shorter animations.</p>\n<p dir=\"auto\">Defaults to <code>10</code></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n damping: 50\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">damping</span>: <span class=\"pl-c1\">50</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-mass\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#mass\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>mass</h5>\n<p dir=\"auto\">This is the mass of the animating object. Heavier objects will take longer to speed up and slow down.</p>\n<p dir=\"auto\">Defaults to <code>1</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n mass: 2\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">mass</span>: <span class=\"pl-c1\">2</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-velocity\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#velocity\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>velocity</h5>\n<p dir=\"auto\">The initial velocity, in units per second, of the animation.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n velocity: 1000\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">1000</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-duration-1\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#duration-1\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>duration</h5>\n<p dir=\"auto\">The duration of the spring, in milliseconds.</p>\n<p dir=\"auto\">Will be overridden by <code>stiffness</code>, <code>mass</code> or <code>damping</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n duration: 1000\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">duration</span>: <span class=\"pl-c1\">1000</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-bounce\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#bounce\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>bounce</h5>\n<p dir=\"auto\">The bounciness of the spring, as a value between <code>0</code> and <code>1</code>, where <code>0</code> is no bounce.</p>\n<p dir=\"auto\">Will be overridden by <code>stiffness</code>, <code>mass</code> or <code>damping</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n bounce: 0.2\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">bounce</span>: <span class=\"pl-c1\">0.2</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-restdelta\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#restdelta\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>restDelta</h5>\n<p dir=\"auto\">The distance from the animation target at which the animation can be considered complete. When both <code>restDelta</code> and <code>restSpeed</code> are met, the animation completes.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n restDelta: 0.5\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">restDelta</span>: <span class=\"pl-c1\">0.5</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-restspeed\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#restspeed\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>restSpeed</h5>\n<p dir=\"auto\">The absolute velocity, in units per second, below which the animation can be considered complete. When both <code>restDelta</code> and <code>restSpeed</code> are met, the animation completes. Defaults to <code>10</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"animate({\n to: 100,\n restSpeed: 5\n})\"><pre><span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">restSpeed</span>: <span class=\"pl-c1\">5</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-playback-controls\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#playback-controls\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Playback controls</h4>\n<p dir=\"auto\"><code>animate</code> returns <code>PlaybackControls</code>, which can be used to control the playback of the animation.</p>\n<p dir=\"auto\">Currently this only includes a <code>stop</code> method, but may expand with more.</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-stop\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#stop\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>stop</h5>\n<p dir=\"auto\">Stops the animation.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const playback = animate({ from: 0, to: 100 })\nplayback.stop()\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">playback</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">animate</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-s1\">playback</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">stop</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-inertia\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#inertia\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>inertia</h3>\n<p dir=\"auto\">The <code>inertia</code> animation is used to gradually decelerate a number. Think smartphone scroll momentum.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-options-1\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#options-1\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Options</h4>\n<p dir=\"auto\">In addition to <code>animate</code>'s <code>from</code>, <code>onUpdate</code> and <code>onComplete</code> options, <code>inertia</code> also supports the following:</p>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-velocity-1\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#velocity-1\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>velocity</h5>\n<p dir=\"auto\">The initial velocity, in units per second, of the animation.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 0,\n velocity: 100\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">100</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-power\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#power\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>power</h5>\n<p dir=\"auto\">A constant with which to calculate a target value. Higher power = further target.</p>\n<p dir=\"auto\">Defaults to <code>0.8</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 0,\n power: 0.3\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">power</span>: <span class=\"pl-c1\">0.3</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-timeconstant\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#timeconstant\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>timeConstant</h5>\n<p dir=\"auto\">Adjusting the time constant will change the duration of the deceleration, thereby affecting its feel.</p>\n<p dir=\"auto\">Defaults to <code>350</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 0,\n velocity: 100,\n timeConstant: 400\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">timeConstant</span>: <span class=\"pl-c1\">400</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-modifytarget\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#modifytarget\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>modifyTarget</h5>\n<p dir=\"auto\">A function that receives the calculated target and returns a new one. Useful for snapping the target to a grid.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const roundToNearest = target =&gt; v =&gt; Math.ceil(v / target) * target\n\ninertia({\n from: 0,\n velocity: 100,\n modifyTarget: roundToNearest(100)\n})\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-en\">roundToNearest</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">target</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-s1\">v</span> <span class=\"pl-c1\">=&gt;</span> <span class=\"pl-v\">Math</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">ceil</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">v</span> <span class=\"pl-c1\">/</span> <span class=\"pl-s1\">target</span><span class=\"pl-kos\">)</span> <span class=\"pl-c1\">*</span> <span class=\"pl-s1\">target</span>\n\n<span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">modifyTarget</span>: <span class=\"pl-en\">roundToNearest</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">100</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-min\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#min\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>min</h5>\n<p dir=\"auto\">The minimum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 50,\n velocity: -100,\n min: 0\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">50</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">-</span><span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">min</span>: <span class=\"pl-c1\">0</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-max\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#max\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>max</h5>\n<p dir=\"auto\">The maximum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 50,\n velocity: 100,\n max: 100\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">50</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">max</span>: <span class=\"pl-c1\">100</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-bouncestiffness\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#bouncestiffness\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>bounceStiffness</h5>\n<p dir=\"auto\">This defines the stiffness of the spring when the animation hits either <code>min</code> or <code>max</code>. A higher stiffness will result in a snappier animation.</p>\n<p dir=\"auto\">Defaults to <code>500</code></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 0,\n velocity: 100,\n max: 50,\n bounceStiffness: 1000\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">max</span>: <span class=\"pl-c1\">50</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">bounceStiffness</span>: <span class=\"pl-c1\">1000</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-bouncedamping\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#bouncedamping\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>bounceDamping</h5>\n<p dir=\"auto\">This is the opposing force to <code>bounceStiffness</code>. As you reduce this value, relative to <code>bounceStiffness</code>, the spring will become bouncier and the animation will last longer. Likewise, higher relative values will have less bounciness and result in shorter animations.</p>\n<p dir=\"auto\">Defaults to <code>10</code></p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 0,\n velocity: 100,\n max: 50,\n bounceDamping: 300\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">max</span>: <span class=\"pl-c1\">50</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">bounceDamping</span>: <span class=\"pl-c1\">300</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h5 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-restdelta-1\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#restdelta-1\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>restDelta</h5>\n<p dir=\"auto\">The distance from the animation target at which the animation can be considered complete.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"inertia({\n from: 0,\n velocity: 100,\n restDelta: 0.5\n})\"><pre><span class=\"pl-en\">inertia</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">velocity</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">restDelta</span>: <span class=\"pl-c1\">0.5</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-iterators\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#iterators\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Iterators</h3>\n<p dir=\"auto\">Powering <code>animate</code> and <code>inertia</code> are the <code>keyframes</code>, <code>spring</code>, and <code>decay</code> <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol\" rel=\"nofollow\">iterators</a>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { keyframes, spring, decay } from &quot;popmotion&quot;;\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">keyframes</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">spring</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">decay</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span><span class=\"pl-kos\">;</span></pre></div>\n<p dir=\"auto\">Iterators give you the ability to run an animation with a high degree of control. For example, <a href=\"https://framer.com\" rel=\"nofollow\">Framer</a> uses the <code>spring</code> iterator to draw its animation editor visualiser by running it synchronously.</p>\n<p dir=\"auto\">Each can be initialised with the matching options above (<code>decay</code> with a subset of <code>inertia</code>'s options, excluding the <code>bounce-</code> options):</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const animation = spring({\n from: 0,\n to: 100,\n stiffness: 200\n})\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">animation</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">spring</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span>\n <span class=\"pl-c1\">from</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">to</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-c1\">stiffness</span>: <span class=\"pl-c1\">200</span>\n<span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">With the returned iterator, you can resolve the animation at a specific timestamp with its <code>next</code> method.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"// Resolve the animation at 200ms\nconst { value, done } = animation.next(200)\"><pre><span class=\"pl-c\">// Resolve the animation at 200ms</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-kos\">{</span> value<span class=\"pl-kos\">,</span> done <span class=\"pl-kos\">}</span> <span class=\"pl-c1\">=</span> <span class=\"pl-s1\">animation</span><span class=\"pl-kos\">.</span><span class=\"pl-en\">next</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">200</span><span class=\"pl-kos\">)</span></pre></div>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-easing\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#easing\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Easing</h2>\n<p dir=\"auto\">Popmotion includes a number of in-built easing functions, as well as factory functions to make entirely new ones.</p>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-functions\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#functions\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Functions</h3>\n<p dir=\"auto\">Each easing function can be imported like so:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { linear } from &quot;popmotion&quot;\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">linear</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span></pre></div>\n<p dir=\"auto\">Each function accepts a progress value between <code>0</code> and <code>1</code>, and returns a new one:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const progress = 0.5\nconst easedProgress = easeInOut(progress)\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">progress</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">0.5</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">easedProgress</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">easeInOut</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">progress</span><span class=\"pl-kos\">)</span></pre></div>\n<ul dir=\"auto\">\n<li><code>linear</code></li>\n<li><code>easeIn</code></li>\n<li><code>easeInOut</code></li>\n<li><code>easeOut</code></li>\n<li><code>circIn</code></li>\n<li><code>circInOut</code></li>\n<li><code>circOut</code></li>\n<li><code>backIn</code></li>\n<li><code>backInOut</code></li>\n<li><code>backOut</code></li>\n<li><code>anticipate</code></li>\n<li><code>bounceIn</code></li>\n<li><code>bounceInOut</code></li>\n<li><code>bounceOut</code></li>\n</ul>\n<h3 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-factories\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#factories\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Factories</h3>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-cubicbezier\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#cubicbezier\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>cubicBezier</h4>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { cubicBezier } from &quot;popmotion&quot;\n\nconst easing = cubicBezier(0, .42, 0, 1)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">cubicBezier</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">easing</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">cubicBezier</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">.42</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">New cubic bezier definitions can be created in the <a href=\"https://framer.com\" rel=\"nofollow\">Framer</a> animation editor and copy/pasted directly into this function.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-steps\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#steps\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>steps</h4>\n<p dir=\"auto\"><code>steps</code> returns an easing function that will convert the animation into a discrete series of steps.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { steps } from &quot;popmotion&quot;\n\nconst easing = steps(5)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">steps</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">easing</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">steps</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">5</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">It optionally accepts a second parameter, either <code>\"start\"</code> or <code>\"end\"</code> (default)that decides whether the steps are aligned with the start or end of the animation.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"steps(5, &quot;start&quot;)\"><pre><span class=\"pl-en\">steps</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">5</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"start\"</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-mirroreasing\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#mirroreasing\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>mirrorEasing</h4>\n<p dir=\"auto\">Mirrors an existing easing function.</p>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-reverseeasing\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#reverseeasing\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>reverseEasing</h4>\n<p dir=\"auto\">Reverses an existing easing function. For instance, providing it <code>easeIn</code> would return an <code>easeOut</code>.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { reverseEasing, linear } from &quot;popmotion&quot;\n\nconst reversed = reverseEasing(linear)\nreversed(1) // 0\nreversed(0.5) // 0.5\nreversed(0) // 1\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">reverseEasing</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">linear</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">reversed</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">reverseEasing</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">linear</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-s1\">reversed</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">1</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 0</span>\n<span class=\"pl-s1\">reversed</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0.5</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 0.5</span>\n<span class=\"pl-s1\">reversed</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 1</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-createexpoin\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#createexpoin\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>createExpoIn</h4>\n<p dir=\"auto\">Creates an easing function based on the exponent of the provided <code>power</code>. The higher the <code>power</code>, the stronger the easing.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createExpoIn } from &quot;popmotion&quot;\n\nconst expoIn = createExpoIn(4)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createExpoIn</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">expoIn</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createExpoIn</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">4</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">The returned easing function is an ease in, which means it starts slow and finished fast. <code>mirrorEasing</code> and <code>reverseEasing</code> can be used to create ease in out, and ease out variations:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const expoIn = createExpoIn(4)\nconst expoOut = mirrorEasing(easeIn)\nconst expoInOut = reverseEasing(easeIn)\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">expoIn</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createExpoIn</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">4</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">expoOut</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">mirrorEasing</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">easeIn</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">expoInOut</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">reverseEasing</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">easeIn</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-createbackin\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#createbackin\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>createBackIn</h4>\n<p dir=\"auto\">Creates an easing function with an overshoot. It accepts a <code>power</code> value, the higher the <code>power</code> the stronger the overshoot.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createBackIn } from &quot;popmotion&quot;\n\nconst backIn = createBackIn(4)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createBackIn</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">backIn</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createBackIn</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">4</span><span class=\"pl-kos\">)</span></pre></div>\n<p dir=\"auto\">The returned easing function is an ease in, which means the overshoot happens at the start of the animation. <code>mirrorEasing</code> and <code>reverseEasing</code> can be used to create ease in out, and ease out variations:</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"const backIn = createBackIn(4)\nconst backOut = mirrorEasing(easeIn)\nconst backInOut = reverseEasing(easeIn)\"><pre><span class=\"pl-k\">const</span> <span class=\"pl-s1\">backIn</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createBackIn</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">4</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">backOut</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">mirrorEasing</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">easeIn</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">backInOut</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">reverseEasing</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">easeIn</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-createanticipate\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#createanticipate\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>createAnticipate</h4>\n<p dir=\"auto\">Creates an easing that pulls back a little before animating out with an overshoot. The stronger the <code>power</code> the bigger the overshoot.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { createAnticipate } from &quot;popmotion&quot;\n\nconst anticipate = createAnticipate(4)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">createAnticipate</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">anticipate</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">createAnticipate</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">4</span><span class=\"pl-kos\">)</span></pre></div>\n<h2 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-utils\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#utils\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Utils</h2>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-angle\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#angle\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>angle</h4>\n<p dir=\"auto\">Returns an angle between two points, in degrees.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { angle } from &quot;popmotion&quot;\n\nangle(\n { x: 0, y: 0 },\n { x: 45, y: 100 }\n)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">angle</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">angle</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">45</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">100</span> <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-attract\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#attract\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>attract</h4>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { attract } from &quot;popmotion&quot;\n\nattract(5, 10, 12)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">attract</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">attract</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">5</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">10</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">12</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-attractexpo\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#attractexpo\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>attractExpo</h4>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { attractExpo } from &quot;popmotion&quot;\n\nattractExpo(5, 10, 12)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">attractExpo</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">attractExpo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">5</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">10</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">12</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-clamp\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#clamp\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>clamp</h4>\n<p dir=\"auto\">Clamp a value to within the given range.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { clamp } from &quot;popmotion&quot;\n\nconst min = 50\nconst max = 100\nclamp(min, max, 150) // 100\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">clamp</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">min</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">50</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">max</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">100</span>\n<span class=\"pl-en\">clamp</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">min</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">max</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">150</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 100</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-degreestoradians\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#degreestoradians\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>degreesToRadians</h4>\n<p dir=\"auto\">Converts degrees to radians.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { degreesToRadians } from &quot;popmotion&quot;\n\ndegreesToRadians(45) // 0.785...\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">degreesToRadians</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">degreesToRadians</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">45</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 0.785...</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-distance\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#distance\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>distance</h4>\n<p dir=\"auto\">Returns the distance between two numbers, two 2D points, or two 3D points.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { distance } from &quot;popmotion&quot;\n\ndistance(10, 50)\ndistance({ x: 0, y: 0 }, { x: 45, y: 100 })\ndistance({ x: 0, y: 0, z: 100 }, { x: 45, y: 100, z: 0 })\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">distance</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">distance</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">10</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">50</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-en\">distance</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">45</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">100</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span>\n<span class=\"pl-en\">distance</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">z</span>: <span class=\"pl-c1\">100</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span> <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">45</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">z</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-interpolate\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#interpolate\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>interpolate</h4>\n<p dir=\"auto\">Creates a function that will interpolate from an linear series of numbers, to a non-linear series of numbers, strings of the same numerical format, colours, or arrays/objects of those.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { interpolate } from &quot;popmotion&quot;\n\nconst mapXToOpacity = interpolate(\n [-100, 0, 100],\n [0, 1, 0]\n)\nmapXToOpacity(-50) // 0.5\n\nconst mapProgressToValues = interpolate(\n [0, 1],\n [\n { x: 0, color: &quot;#fff&quot; },\n { x: 100, color: &quot;#000&quot; }\n ]\n)\nmapProgressToValues(0.5) // { x: 50, color: &quot;#888&quot; }\n\nconst rescale = interpolate(\n [0, 1],\n [100, 200],\n { clamp: false }\n)\nrescale(2) // 300\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">interpolate</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">mapXToOpacity</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">interpolate</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-c1\">-</span><span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">100</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">0</span><span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">)</span>\n<span class=\"pl-s1\">mapXToOpacity</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">-</span><span class=\"pl-c1\">50</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 0.5</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">mapProgressToValues</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">interpolate</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span>\n <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">color</span>: <span class=\"pl-s\">\"#fff\"</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">color</span>: <span class=\"pl-s\">\"#000\"</span> <span class=\"pl-kos\">}</span>\n <span class=\"pl-kos\">]</span>\n<span class=\"pl-kos\">)</span>\n<span class=\"pl-s1\">mapProgressToValues</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0.5</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// { x: 50, color: \"#888\" }</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">rescale</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">interpolate</span><span class=\"pl-kos\">(</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">[</span><span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">200</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">,</span>\n <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">clamp</span>: <span class=\"pl-c1\">false</span> <span class=\"pl-kos\">}</span>\n<span class=\"pl-kos\">)</span>\n<span class=\"pl-s1\">rescale</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">2</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 300</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-options-2\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#options-2\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>Options</h4>\n<p dir=\"auto\"><code>interpolate</code> accepts an optional third argument, an object of options.</p>\n<ul dir=\"auto\">\n<li><code>clamp</code>: Clamps values to within given range. Defaults to <code>true</code>.</li>\n<li><code>ease</code>: An <code>Easing</code> function, or array of easing functions, to ease the interpolation of each segment.</li>\n<li><code>mixer</code>: A function that, when provided a <code>from</code> and <code>to</code> value, will return a new function that accepts a progress value between <code>0</code> and <code>1</code> to mix between those two values. For integration with libraries like Flubber.</li>\n</ul>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-ispoint\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#ispoint\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>isPoint</h4>\n<p dir=\"auto\">Returns <code>true</code> if the provided argument is a 2D point.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { isPoint } from &quot;popmotion&quot;\n\nisPoint({ x: 0 }) // false\nisPoint({ x: 0, y: 0 }) // true\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">isPoint</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">isPoint</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// false</span>\n<span class=\"pl-en\">isPoint</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// true</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-ispoint3d\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#ispoint3d\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>isPoint3D</h4>\n<p dir=\"auto\">Returns <code>true</code> if the provided argument is a 3D point.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { isPoint3D } from &quot;popmotion&quot;\n\nisPoint3D({ x: 0 }) // false\nisPoint3D({ x: 0, y: 0 }) // false\nisPoint3D({ x: 0, y: 0, z: 0 }) // true\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">isPoint3D</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">isPoint3D</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// false</span>\n<span class=\"pl-en\">isPoint3D</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// false</span>\n<span class=\"pl-en\">isPoint3D</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">z</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// true</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-mix\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#mix\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>mix</h4>\n<p dir=\"auto\">Will mix between two values, given <code>progress</code> as a third argument.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { mix } from &quot;popmotion&quot;\n\nmix(0, 100, 0.5) // 50\nmix(0, 100, 2) // 200\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">mix</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">mix</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">0.5</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 50</span>\n<span class=\"pl-en\">mix</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">2</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 200</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-mixcolor\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#mixcolor\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>mixColor</h4>\n<p dir=\"auto\">Returns a function that, when provided a <code>progress</code> value, will mix between two colors. Accepts hex, rgba and hsla colors.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { mixColor } from &quot;popmotion&quot;\n\nmixColor(&quot;#000&quot;, &quot;#fff&quot;)(0.5) // &quot;rgba(125, 125, 125, 1)&quot;\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">mixColor</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">mixColor</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"#000\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"#fff\"</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0.5</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// \"rgba(125, 125, 125, 1)\"</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-mixcomplex\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#mixcomplex\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>mixComplex</h4>\n<p dir=\"auto\">Returns a function that, when provided a <code>progress</code> value, will mix between two strings with the same order of numbers and colors.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { mixComplex } from &quot;popmotion&quot;\n\nmixComplex(&quot;100px #fff&quot;, &quot;0px #000&quot;)(0.5) // &quot;50px rgba(125, 125, 125, 1)&quot;\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">mixComplex</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">mixComplex</span><span class=\"pl-kos\">(</span><span class=\"pl-s\">\"100px #fff\"</span><span class=\"pl-kos\">,</span> <span class=\"pl-s\">\"0px #000\"</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0.5</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// \"50px rgba(125, 125, 125, 1)\"</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-pointfromvector\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#pointfromvector\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>pointFromVector</h4>\n<p dir=\"auto\">Given a point, angle in degrees, and distance, will return a new point.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { pointFromVector } from &quot;popmotion&quot;\n\nconst point = { x: 0, y: 0 }\nconst angle = 45\nconst distance = 100\n\npointFromVector(point, angle, distance)\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">pointFromVector</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">point</span> <span class=\"pl-c1\">=</span> <span class=\"pl-kos\">{</span> <span class=\"pl-c1\">x</span>: <span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">y</span>: <span class=\"pl-c1\">0</span> <span class=\"pl-kos\">}</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">angle</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">45</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">distance</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">100</span>\n\n<span class=\"pl-en\">pointFromVector</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">point</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">angle</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">distance</span><span class=\"pl-kos\">)</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-progress\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#progress\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>progress</h4>\n<p dir=\"auto\">Given a min and a max range, and a value, will return the <code>progress</code> of the value within the range as normalised to a <code>0</code>-<code>1</code> range.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { progress } from &quot;popmotion&quot;\n\nconst min = 100\nconst max = 200\nprogress(min, max, 150) // 0.5\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">progress</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">min</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">100</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">max</span> <span class=\"pl-c1\">=</span> <span class=\"pl-c1\">200</span>\n<span class=\"pl-en\">progress</span><span class=\"pl-kos\">(</span><span class=\"pl-s1\">min</span><span class=\"pl-kos\">,</span> <span class=\"pl-s1\">max</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">150</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 0.5</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-radianstodegrees\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#radianstodegrees\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>radiansToDegrees</h4>\n<p dir=\"auto\">Converts radians to degrees.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { radiansToDegrees } from &quot;popmotion&quot;\n\nradiansToDegrees(0.785) // 45\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">radiansToDegrees</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">radiansToDegrees</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0.785</span><span class=\"pl-kos\">)</span> <span class=\"pl-c\">// 45</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-snap\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#snap\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>snap</h4>\n<p dir=\"auto\">Creates a function that will snap numbers to the nearest in a provided array or to a regular interval.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { snap } from &quot;popmotion&quot;\n\n// Snap to regular intervals\nconst snapTo = snap(45);\n\nsnapTo(1); // 0\nsnapTo(40); // 45\nsnapTo(50); // 45\nsnapTo(80); // 90\n\n// Snap to values in an array\nconst snapTo = snap([-100, -50, 100, 200]);\n\nsnapTo(-200); // -100\nsnapTo(-76); // -100\nsnapTo(-74); // -50\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">snap</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-c\">// Snap to regular intervals</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">snapTo</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">snap</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">45</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-s1\">snapTo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">1</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 0</span>\n<span class=\"pl-s1\">snapTo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">40</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 45</span>\n<span class=\"pl-s1\">snapTo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">50</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 45</span>\n<span class=\"pl-s1\">snapTo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">80</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 90</span>\n\n<span class=\"pl-c\">// Snap to values in an array</span>\n<span class=\"pl-k\">const</span> <span class=\"pl-s1\">snapTo</span> <span class=\"pl-c1\">=</span> <span class=\"pl-en\">snap</span><span class=\"pl-kos\">(</span><span class=\"pl-kos\">[</span><span class=\"pl-c1\">-</span><span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">-</span><span class=\"pl-c1\">50</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">100</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">200</span><span class=\"pl-kos\">]</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span>\n\n<span class=\"pl-s1\">snapTo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">-</span><span class=\"pl-c1\">200</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// -100</span>\n<span class=\"pl-s1\">snapTo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">-</span><span class=\"pl-c1\">76</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// -100</span>\n<span class=\"pl-s1\">snapTo</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">-</span><span class=\"pl-c1\">74</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// -50</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-todecimal\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#todecimal\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>toDecimal</h4>\n<p dir=\"auto\">Rounds a number to a specific decimal place.</p>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { toDecimal } from &quot;popmotion&quot;\n\ntoDecimal(3.3333); // 3.33\ntoDecimal(6.6666, 1); // 6.67\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">toDecimal</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">toDecimal</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">3.3333</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 3.33</span>\n<span class=\"pl-en\">toDecimal</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">6.6666</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 6.67</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-velocityperframe\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#velocityperframe\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>velocityPerFrame</h4>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { velocityPerFrame } from &quot;popmotion&quot;\n\nvelocityPerFrame(50, 16.7); // 0.835\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">velocityPerFrame</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">velocityPerFrame</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">50</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">16.7</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 0.835</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-velocitypersecond\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#velocitypersecond\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>velocityPerSecond</h4>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { velocityPerSecond } from &quot;popmotion&quot;\n\nvelocityPerSecond(1, 16.7); // 59.880...\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">velocityPerSecond</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">velocityPerSecond</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">1</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">16.7</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 59.880...</span></pre></div>\n<h4 tabindex=\"-1\" dir=\"auto\"><a id=\"user-content-wrap\" class=\"anchor\" aria-hidden=\"true\" tabindex=\"-1\" href=\"#wrap\"><svg class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"><path d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"></path></svg></a>wrap</h4>\n<div class=\"highlight highlight-source-js notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"import { wrap } from &quot;popmotion&quot;\n\nwrap(0, 1, 0.5); // 0.5\nwrap(0, 1, 1.5); // 0.5\"><pre><span class=\"pl-k\">import</span> <span class=\"pl-kos\">{</span> <span class=\"pl-s1\">wrap</span> <span class=\"pl-kos\">}</span> <span class=\"pl-k\">from</span> <span class=\"pl-s\">\"popmotion\"</span>\n\n<span class=\"pl-en\">wrap</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">0.5</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 0.5</span>\n<span class=\"pl-en\">wrap</span><span class=\"pl-kos\">(</span><span class=\"pl-c1\">0</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1</span><span class=\"pl-kos\">,</span> <span class=\"pl-c1\">1.5</span><span class=\"pl-kos\">)</span><span class=\"pl-kos\">;</span> <span class=\"pl-c\">// 0.5</span></pre></div>\n</article>",
"loaded": true,
"timedOut": false,
"errorMessage": null,
"headerInfo": {
"toc": [
{
"level": 1,
"text": "",
"anchor": "",
"htmlText": ""
},
{
"level": 3,
"text": "The animator's toolbox",
"anchor": "the-animators-toolbox",
"htmlText": "The animator's toolbox"
},
{
"level": 2,
"text": "Quick start",
"anchor": "quick-start",
"htmlText": "Quick start"
},
{
"level": 2,
"text": "Animation",
"anchor": "animation",
"htmlText": "Animation"
},
{
"level": 3,
"text": "animate",
"anchor": "animate",
"htmlText": "animate"
},
{
"level": 4,
"text": "Options",
"anchor": "options",
"htmlText": "Options"
},
{
"level": 5,
"text": "from",
"anchor": "from",
"htmlText": "from"
},
{
"level": 5,
"text": "elapsed",
"anchor": "elapsed",
"htmlText": "elapsed"
},
{
"level": 5,
"text": "repeat",
"anchor": "repeat",
"htmlText": "repeat"
},
{
"level": 5,
"text": "repeatDelay",
"anchor": "repeatdelay",
"htmlText": "repeatDelay"
},
{
"level": 5,
"text": "repeatType",
"anchor": "repeattype",
"htmlText": "repeatType"
},
{
"level": 5,
"text": "driver",
"anchor": "driver",
"htmlText": "driver"
},
{
"level": 5,
"text": "type",
"anchor": "type",
"htmlText": "type"
},
{
"level": 4,
"text": "Lifecycle events",
"anchor": "lifecycle-events",
"htmlText": "Lifecycle events"
},
{
"level": 5,
"text": "onUpdate",
"anchor": "onupdate",
"htmlText": "onUpdate"
},
{
"level": 5,
"text": "onPlay",
"anchor": "onplay",
"htmlText": "onPlay"
},
{
"level": 5,
"text": "onComplete",
"anchor": "oncomplete",
"htmlText": "onComplete"
},
{
"level": 5,
"text": "onRepeat",
"anchor": "onrepeat",
"htmlText": "onRepeat"
},
{
"level": 5,
"text": "onStop",
"anchor": "onstop",
"htmlText": "onStop"
},
{
"level": 4,
"text": "Keyframes options",
"anchor": "keyframes-options",
"htmlText": "Keyframes options"
},
{
"level": 5,
"text": "to",
"anchor": "to",
"htmlText": "to"
},
{
"level": 5,
"text": "duration",
"anchor": "duration",
"htmlText": "duration"
},
{
"level": 5,
"text": "ease",
"anchor": "ease",
"htmlText": "ease"
},
{
"level": 5,
"text": "offset",
"anchor": "offset",
"htmlText": "offset"
},
{
"level": 4,
"text": "Spring options",
"anchor": "spring-options",
"htmlText": "Spring options"
},
{
"level": 5,
"text": "to",
"anchor": "to-1",
"htmlText": "to"
},
{
"level": 5,
"text": "stiffness",
"anchor": "stiffness",
"htmlText": "stiffness"
},
{
"level": 5,
"text": "damping",
"anchor": "damping",
"htmlText": "damping"
},
{
"level": 5,
"text": "mass",
"anchor": "mass",
"htmlText": "mass"
},
{
"level": 5,
"text": "velocity",
"anchor": "velocity",
"htmlText": "velocity"
},
{
"level": 5,
"text": "duration",
"anchor": "duration-1",
"htmlText": "duration"
},
{
"level": 5,
"text": "bounce",
"anchor": "bounce",
"htmlText": "bounce"
},
{
"level": 5,
"text": "restDelta",
"anchor": "restdelta",
"htmlText": "restDelta"
},
{
"level": 5,
"text": "restSpeed",
"anchor": "restspeed",
"htmlText": "restSpeed"
},
{
"level": 4,
"text": "Playback controls",
"anchor": "playback-controls",
"htmlText": "Playback controls"
},
{
"level": 5,
"text": "stop",
"anchor": "stop",
"htmlText": "stop"
},
{
"level": 3,
"text": "inertia",
"anchor": "inertia",
"htmlText": "inertia"
},
{
"level": 4,
"text": "Options",
"anchor": "options-1",
"htmlText": "Options"
},
{
"level": 5,
"text": "velocity",
"anchor": "velocity-1",
"htmlText": "velocity"
},
{
"level": 5,
"text": "power",
"anchor": "power",
"htmlText": "power"
},
{
"level": 5,
"text": "timeConstant",
"anchor": "timeconstant",
"htmlText": "timeConstant"
},
{
"level": 5,
"text": "modifyTarget",
"anchor": "modifytarget",
"htmlText": "modifyTarget"
},
{
"level": 5,
"text": "min",
"anchor": "min",
"htmlText": "min"
},
{
"level": 5,
"text": "max",
"anchor": "max",
"htmlText": "max"
},
{
"level": 5,
"text": "bounceStiffness",
"anchor": "bouncestiffness",
"htmlText": "bounceStiffness"
},
{
"level": 5,
"text": "bounceDamping",
"anchor": "bouncedamping",
"htmlText": "bounceDamping"
},
{
"level": 5,
"text": "restDelta",
"anchor": "restdelta-1",
"htmlText": "restDelta"
},
{
"level": 3,
"text": "Iterators",
"anchor": "iterators",
"htmlText": "Iterators"
},
{
"level": 2,
"text": "Easing",
"anchor": "easing",
"htmlText": "Easing"
},
{
"level": 3,
"text": "Functions",
"anchor": "functions",
"htmlText": "Functions"
},
{
"level": 3,
"text": "Factories",
"anchor": "factories",
"htmlText": "Factories"
},
{
"level": 4,
"text": "cubicBezier",
"anchor": "cubicbezier",
"htmlText": "cubicBezier"
},
{
"level": 4,
"text": "steps",
"anchor": "steps",
"htmlText": "steps"
},
{
"level": 4,
"text": "mirrorEasing",
"anchor": "mirroreasing",
"htmlText": "mirrorEasing"
},
{
"level": 4,
"text": "reverseEasing",
"anchor": "reverseeasing",
"htmlText": "reverseEasing"
},
{
"level": 4,
"text": "createExpoIn",
"anchor": "createexpoin",
"htmlText": "createExpoIn"
},
{
"level": 4,
"text": "createBackIn",
"anchor": "createbackin",
"htmlText": "createBackIn"
},
{
"level": 4,
"text": "createAnticipate",
"anchor": "createanticipate",
"htmlText": "createAnticipate"
},
{
"level": 2,
"text": "Utils",
"anchor": "utils",
"htmlText": "Utils"
},
{
"level": 4,
"text": "angle",
"anchor": "angle",
"htmlText": "angle"
},
{
"level": 4,
"text": "attract",
"anchor": "attract",
"htmlText": "attract"
},
{
"level": 4,
"text": "attractExpo",
"anchor": "attractexpo",
"htmlText": "attractExpo"
},
{
"level": 4,
"text": "clamp",
"anchor": "clamp",
"htmlText": "clamp"
},
{
"level": 4,
"text": "degreesToRadians",
"anchor": "degreestoradians",
"htmlText": "degreesToRadians"
},
{
"level": 4,
"text": "distance",
"anchor": "distance",
"htmlText": "distance"
},
{
"level": 4,
"text": "interpolate",
"anchor": "interpolate",
"htmlText": "interpolate"
},
{
"level": 4,
"text": "Options",
"anchor": "options-2",
"htmlText": "Options"
},
{
"level": 4,
"text": "isPoint",
"anchor": "ispoint",
"htmlText": "isPoint"
},
{
"level": 4,
"text": "isPoint3D",
"anchor": "ispoint3d",
"htmlText": "isPoint3D"
},
{
"level": 4,
"text": "mix",
"anchor": "mix",
"htmlText": "mix"
},
{
"level": 4,
"text": "mixColor",
"anchor": "mixcolor",
"htmlText": "mixColor"
},
{
"level": 4,
"text": "mixComplex",
"anchor": "mixcomplex",
"htmlText": "mixComplex"
},
{
"level": 4,
"text": "pointFromVector",
"anchor": "pointfromvector",
"htmlText": "pointFromVector"
},
{
"level": 4,
"text": "progress",
"anchor": "progress",
"htmlText": "progress"
},
{
"level": 4,
"text": "radiansToDegrees",
"anchor": "radianstodegrees",
"htmlText": "radiansToDegrees"
},
{
"level": 4,
"text": "snap",
"anchor": "snap",
"htmlText": "snap"
},
{
"level": 4,
"text": "toDecimal",
"anchor": "todecimal",
"htmlText": "toDecimal"
},
{
"level": 4,
"text": "velocityPerFrame",
"anchor": "velocityperframe",
"htmlText": "velocityPerFrame"
},
{
"level": 4,
"text": "velocityPerSecond",
"anchor": "velocitypersecond",
"htmlText": "velocityPerSecond"
},
{
"level": 4,
"text": "wrap",
"anchor": "wrap",
"htmlText": "wrap"
}
],
"siteNavLoginPath": "/login?return_to=https%3A%2F%2Fgithub.com%2FPopmotion%2Fpopmotion"
}
},
{
"displayName": "CODE_OF_CONDUCT.md",
"repoName": "popmotion",
"refName": "master",
"path": "CODE_OF_CONDUCT.md",
"preferredFileType": "code_of_conduct",
"tabName": "Code of conduct",
"richText": null,
"loaded": false,
"timedOut": false,
"errorMessage": null,
"headerInfo": {
"toc": null,
"siteNavLoginPath": "/login?return_to=https%3A%2F%2Fgithub.com%2FPopmotion%2Fpopmotion"
}
}
],
"overviewFilesProcessingTime": 30.555669
}
},
"appPayload": {
"helpUrl": "https://docs.github.com",
"findFileWorkerPath": "/assets-cdn/worker/find-file-worker-32bb159cc57c.js",
"findInFileWorkerPath": "/assets-cdn/worker/find-in-file-worker-c6704d501c10.js",
"githubDevUrl": null,
"enabled_features": {
"code_nav_ui_events": false,
"copilot_conversational_ux": false,
"copilot_conversational_ux_embedding_update": false,
"copilot_popover_file_editor_header": false,
"copilot_smell_icebreaker_ux": true,
"copilot_workspace": false,
"codeview_firefox_inert": true
}
}
}
}
{
"accept-ranges": "bytes",
"cache-control": "max-age=0, private, must-revalidate",
"content-encoding": "gzip",
"content-security-policy": "default-src 'none'; base-uri 'self'; child-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com api.githubcopilot.com objects-origin.githubusercontent.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.com/assets-cdn/worker/ gist.github.com/assets-cdn/worker/",
"content-type": "text/html; charset=utf-8",
"date": "Mon, 26 Feb 2024 10:54:28 GMT",
"etag": "a61a94559570d4adb22299e72dee39ba",
"referrer-policy": "no-referrer-when-downgrade",
"server": "GitHub.com",
"set-cookie": "logged_in=no; Path=/; Domain=github.com; Expires=Wed, 26 Feb 2025 10:54:28 GMT; HttpOnly; Secure; SameSite=Lax",
"strict-transport-security": "max-age=31536000; includeSubdomains; preload",
"transfer-encoding": "chunked",
"vary": "X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Encoding, Accept, X-Requested-With",
"x-content-type-options": "nosniff",
"x-frame-options": "deny",
"x-github-request-id": "8E3A:4C2B:1B19CA9:267D512:65DC6DE4",
"x-xss-protection": "0"
}