{"id":14961214,"url":"https://github.com/okikio/spring-easing","last_synced_at":"2025-10-24T20:31:25.555Z","repository":{"id":38993135,"uuid":"449877660","full_name":"okikio/spring-easing","owner":"okikio","description":"Quick and easy spring animation. Works with other animation libraries (gsap, animejs, framer motion, motion one, @okikio/animate, etc...)  or the Web Animation API (WAAPI).","archived":false,"fork":false,"pushed_at":"2023-08-25T16:21:46.000Z","size":5840,"stargazers_count":72,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-31T04:04:06.884Z","etag":null,"topics":["animation","animejs","easing","framer-motion","motion-one","spring","spring-easing","typescript","waapi","web-animations-api"],"latest_commit_sha":null,"homepage":"https://spring-easing.okikio.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/okikio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-19T22:37:39.000Z","updated_at":"2025-01-21T09:21:11.000Z","dependencies_parsed_at":"2023-01-17T18:15:27.077Z","dependency_job_id":null,"html_url":"https://github.com/okikio/spring-easing","commit_stats":null,"previous_names":[],"tags_count":11,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okikio%2Fspring-easing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okikio%2Fspring-easing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okikio%2Fspring-easing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okikio%2Fspring-easing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/okikio","download_url":"https://codeload.github.com/okikio/spring-easing/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238035385,"owners_count":19405682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","animejs","easing","framer-motion","motion-one","spring","spring-easing","typescript","waapi","web-animations-api"],"created_at":"2024-09-24T13:24:12.619Z","updated_at":"2025-10-24T20:31:20.507Z","avatar_url":"https://github.com/okikio.png","language":"TypeScript","readme":"# spring-easing\n\n[![Open Bundle](https://bundlejs.com/badge-light.svg)](https://bundlejs.com/?q=spring-easing\u0026bundle \"Check the total bundle size of spring-easing with whichever animation library you choose.\")\n\n\u003c!-- ![](https://deno.bundlejs.com/badge?q=spring-easing) --\u003e\n\n[NPM](https://www.npmjs.com/package/spring-easing) \u003cspan style=\"padding-inline: 1rem\"\u003e|\u003c/span\u003e [Deno](https://deno.land/x/spring_easing) \u003cspan style=\"padding-inline: 1rem\"\u003e|\u003c/span\u003e [GitHub](https://github.com/okikio/spring-easing#readme) \u003cspan style=\"padding-inline: 1rem\"\u003e|\u003c/span\u003e [Docs](https://spring-easing.okikio.dev) \u003cspan style=\"padding-inline: 1rem\"\u003e|\u003c/span\u003e [License](#license)\n\nQuick and easy spring animations. Works with other animation libraries ([gsap](https://greensock.com/), [animejs](https://animejs.com/), [@okikio/animate](http://npmjs.com/@okikio/animate), [motion one](https://motion.dev/), [framer motion](https://www.framer.com/docs/animation/), etc...) or the [Web Animation API (WAAPI)](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API), you can learn more in the [Usage](#use-with-animation-libraries) section.\n\n`spring-easing` works by generating arrays of `frame`'s which when placed in linear order creates a smooth spring like animation.\n\n\u003e A `frame` represent a single frame of an animation\n\n\u003e _**Note**: the `spring-easing` package also supports 4 extra variants of [`spring`](https://spring-easing.okikio.dev/functions/SpringFrame), namely [`spring-in`](https://spring-easing.okikio.dev/functions/SpringInFrame), [`spring-out`](https://spring-easing.okikio.dev/functions/SpringOutFrame), [`spring-out-in`](https://spring-easing.okikio.dev/functions/SpringOutInFrame), and [`spring-in-out`](https://spring-easing.okikio.dev/functions/SpringInOutFrame), you can use these easing to create some really unique spring like animations._\n\n\u003c!-- \u003e You can also read the [blog post](https://blog.okikio.dev/spring-easing), created for it's launch. --\u003e\n\nYou can create animation's like this with `spring-easing`,\n\n\u003cimg src=\"media/assets/spring-easing-demo-video.gif\" width=\"1920\" loading=\"lazy\" alt=\"A demo of the various spring-easings available\" align=\"center\" style=\"border-radius: 1rem; \n    aspect-ratio: auto 1920 / 899;\" /\u003e\n\n\u003c!-- https://github.com/okikio/spring-easing/assets/17222836/3813945f-b301-4399-8383-bbab227c3f68\n\n\u003cvideo controls autoplay align=\"center\" style=\"border-radius: 1rem; aspect-ratio: auto 1920 / 899;\"\u003e\n  \u003csource src=\"media/assets/spring-easing-demo-video.mp4\" type=\"video/mp4\"\u003e\n\u003c/video\u003e --\u003e\n\n\u003e _Check out the spring easing variants on [Codepen](https://codepen.io/okikio/pen/MWEMEgJ)._\n\n\u003e _**Attention**: This entire library is a lightweight version of the [`CustomEasing`](https://native.okikio.dev/animate/api/custom-easing/) implemented in [`@okikio/animate`](https://native.okikio.dev/animate), which supports only string and number interpolation. If you'd like the complete `CustomEasing` with color interpolation, complex value interpolation, and more, go through the source code as a [Github Gist](https://gist.github.com/okikio/bed53ed621cb7f60e9a8b1ef92897471#file-custom-easing-ts), which is licensed under the MIT license._\n\n## Installation\n\n### Node\n\n```bash\nnpm install spring-easing\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003eOthers\u003c/summary\u003e\n\n```bash\nyarn add spring-easing\n```\n\nor\n\n```bash\npnpm install spring-easing\n```\n\n\u003c/details\u003e\n\n### Deno\n\n```ts\nimport { SpringEasing } from \"https://deno.land/x/spring_easing/mod.ts\";\n```\n\n## Usage\n\n```ts\nimport { SpringEasing } from \"spring-easing\";\n// or\nimport SpringEasing from \"spring-easing\";\n```\n\nYou can also use it directly through a script tag:\n\n```html\n\u003cscript src=\"https://unpkg.com/spring-easing\" type=\"module\"\u003e\u003c/script\u003e\n\u003cscript type=\"module\"\u003e\n  // You can then use it like this\n  const { SpringEasing } = window.SpringEasing;\n\u003c/script\u003e\n```\n\nYou can also use it via a CDN, e.g.\n\n```ts\nimport { SpringEasing } from \"https://esm.run/spring-easing\";\n// or\nimport { SpringEasing } from \"https://esm.sh/spring-easing\";\n// or\nimport { SpringEasing } from \"https://unpkg.com/spring-easing\";\n// or\nimport { SpringEasing } from \"https://cdn.skypack.dev/spring-easing\";\n// or\nimport { SpringEasing } from \"https://deno.bundlejs.com/file?q=spring-easing\";\n// or any number of other CDN's\n```\n\n### Use with Animation Libraries\n\n\u003e _**Note:** I cannot guarantee that every animation library works with `spring-easing`, for example, if an animation library doesn't support array values as keyframes, it won't work well with `spring-easing`._\n\nThe libraries that have been tested are:\n\n| Animation Library                                                                                | Support                                                                                                                                                       | Demo                                             |\n| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |\n| [GSAP](https://greensock.com/)                                                                   | ✅ Yes - [Wrap Method](\u003chttps://greensock.com/docs/v3/GSAP/UtilityMethods/wrap()\u003e)                                                                            | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n| [animejs](https://animejs.com)                                                                   | ✅ Yes - [Array Keyframes](https://animejs.com/documentation/#animationKeyframes)                                                                             | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n| [Framer Motion](https://www.framer.com/motion/)                                                  | ✅ Yes - [Array Keyframes](https://www.framer.com/docs/animation/##keyframes)                                                                                 | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n| [Motion One](https://motion.dev)                                                                 | ✅ Yes - [Array Keyframes](https://motion.dev/dom/animate#keyframes)                                                                                          | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n| [@okikio/animate](https://okikio.github.io/native/packages/animate)                              | ✅ Yes - [Array Keyframes](https://okikio.github.io/native/packages/animate/#animations)                                                                      | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n| [Web Animation API (WAAPI)](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API) | ✅ Yes - [Array Keyframes](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Keyframe_Formats#:~:text=An-,object,-containing%20key%2Dvalue) | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n| [Linear Easing (CSS)](https://linear-easing-generator.netlify.app)                               | ✅ Yes - [CSS Spring Easing](#CSSSpringEasing)                                                                                                                | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n| [Linear Easing (WAAPI)](https://linear-easing-generator.netlify.app)                             | ✅ Yes - [CSS Spring Easing](#CSSSpringEasing)                                                                                                                | [Codepen](https://codepen.io/okikio/pen/MWEMEgJ) |\n\ne.g.\n\n```ts\nimport anime from \"animejs\";\nimport { SpringEasing, SpringOutFrame } from \"spring-easing\";\n\n// Note: this is the return value of `SpringEasing` and `GenerateSpringFrames`\nlet [translateX, duration] = SpringEasing([0, 250], {\n  easing: \"spring-out-in(1, 100, 10, 0)\",\n  // You can change the size of Array for the SpringEasing function to generate\n  numPoints: 200,\n  // The number of decimal places to round, final values in the generated Array\n  // This option doesn't exist on `GenerateSpringFrames`\n  decimal: 5,\n});\n\nanime({\n  targets: \"div\",\n\n  // Using spring easing animate from [0 to 250] using `spring-out-in`\n  translateX,\n\n  // You can interpolate between strings\n  // You can set the easing without an easing options object\n  // You can interpolate between more than 2 values\n  // Remember the `0` index of `SpringEasing` is an array of spring animation keyframes\n  rotate: SpringEasing(\n    [\"0turn\", 1, 0, 0.5],\n    [SpringOutFrame, 1, 100, 10, 0]\n  )[0],\n\n  // TIP... Use linear easing for the proper springy effect\n  easing: \"linear\",\n\n  // The optimal duration for this specific spring configuration, e.g. mass, velocity, damping, etc...\n  duration,\n});\n```\n\nOr\n\n```ts\nimport { CSSSpringEasing } from \"spring-easing\";\n\nlet [easings, duration] = CSSSpringEasing({\n  easing: \"spring-out-in(1, 100, 10, 0)\",\n  // The number of decimal places to round to\n  decimal: 5,\n});\n\ndocument.querySelector('div').animate({\n  // Using spring easing animate from [0 to 250] using `spring-out-in`\n  translate: [\"0\", \"250px\"],\n\n  // You can interpolate between strings\n  // You can set the easing without an easing options object\n  // You can interpolate between more than 2 values\n  // Remember the `0` index of `SpringEasing` is an array of spring animation keyframes\n  rotate: [\"0turn\", \"1turn\", \"0turn\", \"0.5turn\"],\n}, {\n  // TIP... Use linear easing for the proper springy effect\n  easing: `linear(${easings})`,\n\n  // The optimal duration for this specific spring configuration, e.g. mass, velocity, damping, etc...\n  duration,\n});\n```\n\n\u003e _**Note**: make sure to read the comments above, as they are valuable resources for understanding what is happening._\n\n\u003e Check out this demo on [Codepen](https://codepen.io/okikio/pen/MWEdzNg)\n\n## Showcase\n\nA couple sites/projects that use `spring-easing`:\n\n- [`postcss-spring-easing`](https://github.com/okikio/postcss-spring-easing)\n- Your site/project here...\n\n## API\n\n\u003cdetails open\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003cem\u003eWhat's New...\u003c/em\u003e\u003c/strong\u003e\u003c/summary\u003e\n\n\u003e **`NEW`** CSS Spring Easing \u0026 support for the `linear()` easing function\n\u003e\n\u003e ### CSSSpringEasing\n\u003e\n\u003e Generates a string that represents a set of values used with the linear-easing function to replicate spring animations,\n\u003e you can check out the linear-easing playground here https://linear-easing-generator.netlify.app/\n\u003e Or check out a demo on Codepen https://codepen.io/okikio/pen/vYVaEXM\n\u003e\n\u003e CSS Spring Easing has 4 properties they are `easing` (all spring frame functions are supported), `numPoints` (the size of the Array the frmae function should create), `decimal` (the number of decimal places of the values within said Array) and `quality` (how detailed/smooth the spring easing should be)..\n\u003e\n\u003e | Properties  | Default Value           |\n\u003e | ----------- | ----------------------- |\n\u003e | `easing`    | `spring(1, 100, 10, 0)` |\n\u003e | `numPoints` | `50`                    |\n\u003e | `decimal`   | `3`                     |\n\u003e | `quality`   | `0.85`                  |\n\u003e\n\u003e `CSSSpringEasing` is meant to be used with the `linear-easing()` function to replicate spring animations.\n\u003e It is based on the work done by [Jake Archibald](https://github.com/jakearchibald) in his [Linear Easing Generator](https://github.com/jakearchibald/linear-easing-generator).\n\u003e\n\u003e \u003e **Note**: This feature will only work on versions of browsers from ~a month ago (`Chrome \u0026 Edge 113`, and `Firefox 112`) except for `Safari` which doesn't support it yet.\n\u003e\n\u003e ```ts\n\u003e import { CSSSpringEasing } from \"spring-easing\";\n\u003e\n\u003e let [easing, duration] = CSSSpringEasing({\n\u003e   easing: \"spring-out-in(1, 100, 10, 0)\",\n\u003e\n\u003e   // You can change the size of Array for the SpringEasing function to generate\n\u003e   numPoints: 200,\n\u003e\n\u003e   // The number of decimal places to round, final values in the generated Array\n\u003e   // This option doesn't exist on {@link GenerateSpringFrames}\n\u003e   decimal: 5,\n\u003e\n\u003e   // How detailed/smooth the spring easing should be\n\u003e   // 0 means not smooth at all (shorter easing string)\n\u003e   // 1 means as smooth as possible (this means the resulting easing will be a longer string)\n\u003e   quality: 0.85,\n\u003e });\n\u003e\n\u003e document.querySelector(\"div\").animate(\n\u003e   {\n\u003e     translate: [\"0px\", \"250px\"],\n\u003e     rotate: [\"0turn\", \"1turn\", \"0turn\", \"0.5turn\"],\n\u003e   },\n\u003e   {\n\u003e     easing: `linear(${easing})`,\n\u003e\n\u003e     // The optimal duration for this specific spring\n\u003e     duration,\n\u003e   }\n\u003e );\n\u003e ```\n\u003e\n\u003e \u003e **Note**: You can also use custom easings with `CSSSpringEasing` e.g.\n\u003e\n\u003e ```ts\n\u003e import {\n\u003e   CSSSpringEasing,\n\u003e   limit,\n\u003e   registerEasingFunctions,\n\u003e } from \"spring-easing\";\n\u003e\n\u003e registerEasingFunctions({\n\u003e   bounce: (t) =\u003e {\n\u003e     let pow2: number,\n\u003e       b = 4;\n\u003e     while (t \u003c ((pow2 = Math.pow(2, --b)) - 1) / 11) {}\n\u003e     return (\n\u003e       1 / Math.pow(4, 3 - b) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - t, 2)\n\u003e     );\n\u003e   },\n\u003e   elastic: (t, params: number[] = []) =\u003e {\n\u003e     let [amplitude = 1, period = 0.5] = params;\n\u003e     const a = limit(amplitude, 1, 10);\n\u003e     const p = limit(period, 0.1, 2);\n\u003e     if (t === 0 || t === 1) return t;\n\u003e     return (\n\u003e       -a *\n\u003e       Math.pow(2, 10 * (t - 1)) *\n\u003e       Math.sin(\n\u003e         ((t - 1 - (p / (Math.PI * 2)) * Math.asin(1 / a)) * (Math.PI * 2)) / p\n\u003e       )\n\u003e     );\n\u003e   },\n\u003e });\n\u003e\n\u003e CSSSpringEasing(\"bounce\"); // [\"0, 0.013, 0.015, 0.006 8.1%, 0.046 13.5%, 0.06, 0.062, 0.054, 0.034, 0.003 27%, 0.122, 0.206 37.8%, 0.232, 0.246, 0.25, 0.242, 0.224, 0.194, 0.153 56.8%, 0.039 62.2%, 0.066 64.9%, 0.448 73%, 0.646, 0.801 83.8%, 0.862 86.5%, 0.95 91.9%, 0.978, 0.994, 1\", ...]\n\u003e CSSSpringEasing(\"elastic(1, 0.5)\"); // [\"0, -0.005 32.4%, 0.006 40.5%, 0.034 51.4%, 0.033 56.8%, 0.022, 0.003, -0.026 64.9%, -0.185 75.7%, -0.204, -0.195, -0.146, -0.05, 0.1 89.2%, 1\", ...]\n\u003e ```\n\u003e\n\u003e ### getOptimizedPoints\n\u003e\n\u003e This function generates an optimized set of points to be used with the `linear-easing()` function\n\u003e using the Ramer-Douglas-Peucker algorithm and rounds the x and y values of the resulting points.\n\u003e\n\u003e ```ts\n\u003e import { getOptimizedPoints } from \"spring-easing\";\n\u003e\n\u003e const points = [\n\u003e   [0, 0],\n\u003e   [0.1, 0.2],\n\u003e   [0.5, 1],\n\u003e   [0.9, 0.2],\n\u003e   [1, 0],\n\u003e ];\n\u003e const round = 2;\n\u003e const simplify = 0.1;\n\u003e\n\u003e console.log(getOptimizedPoints(points, simplify, round)); //= [[0, 0], [0.5, 1], [1, 0]]\n\u003e ```\n\u003e\n\u003e ### getLinearSyntax\n\u003e\n\u003e This function converts a given set of points into an array of strings in a this format `[\"value percent%\", ...]` e.g. `[\"0\", \"0.25 13.8%\", \"0.6 45.6%\", \"0.1\", \"0.4 60%\", ...]`.\n\u003e It's used to generate the syntax for the `linear-easing` function.\n\u003e\n\u003e ```ts\n\u003e import { getLinearSyntax } from \"spring-easing\";\n\u003e\n\u003e const points = [\n\u003e   [0, 0],\n\u003e   [0.1, 0.2],\n\u003e   [0.5, 1],\n\u003e   [0.9, 0.2],\n\u003e   [1, 0],\n\u003e ];\n\u003e const round = 2;\n\u003e\n\u003e console.log(getLinearSyntax(points, round)); //= [ '0', '0.2 10%', '1', '0.2 90%', '0' ]\n\u003e ```\n\n\u003e **`RE-INSTATED`** _Added batch version of `SpringEasing` and the Interpolation functions which use a new syntax._\n\u003e\n\u003e _The other version of `spring-easing` interpolation functions follow this syntax `(t, values, decimal) =\u003e string | number | any`, batch interpolation function use this new syntax `(arr_t, values, decimal) =\u003e string[] | number[] | any[]`._\n\u003e\n\u003e _The key difference between both syntaxes are the parameters each function takes and the return value of each function._\n\u003e\n\u003e _The older syntax returned instantaneous frame values at a specific t-value, but the new syntax returns all the frames that make the entire animation, allowing for performance optimizations that couldn't be done before._\n\u003e\n\u003e _For the most part this shouldn't leave too much of an effect, but for those high-perf. applications this new batch synatax should prove useful._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e function batchInterpolateNumber(\n\u003e   arr_t: number[],\n\u003e   values: number[],\n\u003e   decimal = 3\n\u003e ) {\n\u003e   // nth index\n\u003e   const n = values.length - 1;\n\u003e\n\u003e   return arr_t.map((t) =\u003e {\n\u003e     // The current index given t\n\u003e     const i = limit(Math.floor(t * n), 0, n - 1);\n\u003e\n\u003e     const start = values[i];\n\u003e     const end = values[i + 1];\n\u003e     const progress = (t - i / n) * n;\n\u003e\n\u003e     return toFixed(scale(progress, start, end), decimal);\n\u003e   });\n\u003e }\n\u003e\n\u003e BatchSpringEasing([0, 250], `spring`, batchInterpolateNumber);\n\u003e ```\n\n\u003e **`RE-INSTATED`** _There is a new `toAnimationFrames` function that converts interpolation functions written in this style `(t, values, decimal) =\u003e { ... }` to work in `BatchSpringEasing`._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e import {\n\u003e   BatchSpringEasing,\n\u003e   toAnimationFrames,\n\u003e   toFixed,\n\u003e   scale,\n\u003e   limit,\n\u003e } from \"spring-easing\";\n\u003e\n\u003e function interpolateNumber(t: number, values: number[], decimal = 3) {\n\u003e   // nth index\n\u003e   const n = values.length - 1;\n\u003e\n\u003e   // The current index given t\n\u003e   const i = limit(Math.floor(t * n), 0, n - 1);\n\u003e\n\u003e   const start = values[i];\n\u003e   const end = values[i + 1];\n\u003e   const progress = (t - i / n) * n;\n\u003e\n\u003e   return toFixed(scale(progress, start, end), decimal);\n\u003e }\n\u003e\n\u003e function interpolatePixels(t: number, values: number[], decimal = 3) {\n\u003e   const result = interpolateNumber(t, values, decimal);\n\u003e   return `${result}px`;\n\u003e }\n\u003e\n\u003e BatchSpringEasing([0, 250], \"spring\", toAnimationFrames(interpolatePixels));\n\u003e ```\n\n\u003e **`NEW`** _Optimized perf. of spring generation w/ help from [@jakearchibald](https://twitter.com/jaffathecake)_\n\n\u003e **`NEW`** _`mass`, `stiffness`, `damping`, and `velocity` now have a smaller minimum limit of `0.0001` instead of `0.1`_\n\n\u003e **`REVERT`** _The new interpolation syntax has been reverted and removed; `instantNumber`, etc... functions have been renamed to `interpolateNumber`, etc..._\n\n\u003e **`NEW`** _Re-introduced instantaneous interpolation functions._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e import {\n\u003e   interpolateNumber,\n\u003e   interpolateString,\n\u003e   interpolateSequence,\n\u003e   interpolateComplex,\n\u003e } from \"spring-easing\";\n\u003e ```\n\u003e\n\u003e These functions represent the interpolated value at a specific instance in time, where time is represented by `t` with a range of `0` to `1`.\n\u003e You can use these functions as building blocks to create your own custom interpolation functions.\n\n\u003e **`NEW`** _(deprecated) `interpolateUsingIndex` is now an alias of `interpolateSequence`, it still keeps the same functionality._\n\u003e The recommendation is to use `interpolateSequence` instead of `interpolateUsingIndex`, but you can still keep using `interpolateUsingIndex`, but beware it can be removed in future versions.\n\n\u003e \u003cstrike\u003e **`NEW`** _Re-introduced instantaneous interpolation functions._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e import {\n\u003e   instantNumber,\n\u003e   instantString,\n\u003e   instantSequence,\n\u003e   instanceComplex,\n\u003e } from \"spring-easing\";\n\u003e ```\n\u003e\n\u003e These functions represent the interpolated value at a specific instance in time, where time is represented by `t` with a range of `0` to `1`.\n\u003e You can use these functions as building blocks to create your own custom interpolation functions.\n\u003e\n\u003e \u003c/strike\u003e\n\n\u003e \u003cstrike\u003e **`BREAKING CHANGE`** _Interpolation functions use a new syntax._\n\u003e\n\u003e _In older versions of `spring-easing` interpolation functions used to follow a syntax called the instantaneous interpolation function `(t, values, decimal) =\u003e string | number | any`, the new syntax is called interpolation function `(frames, values, decimal) =\u003e string[] | number[] | any[]`._\n\u003e\n\u003e _The key difference between both syntaxes are the parameters each function takes and the return value of each function._\n\u003e\n\u003e _The older syntax returned instantaneous frame values at a specific t-value, but the new syntax returns all the frames that make the entire animation, allowing for performance optimizations that couldn't be done before._\n\u003e\n\u003e _For the most part this shouldn't leave too much of an effect as all the built-in interpolation functions have been updated to use the new synatax._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e function interpolateNumber(frames: number[], values: number[], decimal = 3) {\n\u003e   // nth index\n\u003e   const n = values.length - 1;\n\u003e\n\u003e   return frames.map((t) =\u003e {\n\u003e     // The current index given t\n\u003e     const i = limit(Math.floor(t * n), 0, n - 1);\n\u003e\n\u003e     const start = values[i];\n\u003e     const end = values[i + 1];\n\u003e     const progress = (t - i / n) * n;\n\u003e\n\u003e     return toFixed(scale(progress, start, end), decimal);\n\u003e   });\n\u003e }\n\u003e\n\u003e SpringEasing([0, 250], `spring`, interpolateNumber);\n\u003e ```\n\u003e\n\u003e \u003c/strike\u003e\n\n\u003e \u003cstrike\u003e **`NEW`** _There is a new `toAnimationFrames` function that be used on instantaneous interpolation functions, to transform them into complete animation interpolation functions._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e import {\n\u003e   SpringEasing,\n\u003e   toAnimationFrames,\n\u003e   toFixed,\n\u003e   scale,\n\u003e   limit,\n\u003e } from \"spring-easing\";\n\u003e\n\u003e function interpolateNumber(t: number, values: number[], decimal = 3) {\n\u003e   // nth index\n\u003e   const n = values.length - 1;\n\u003e\n\u003e   // The current index given t\n\u003e   const i = limit(Math.floor(t * n), 0, n - 1);\n\u003e\n\u003e   const start = values[i];\n\u003e   const end = values[i + 1];\n\u003e   const progress = (t - i / n) * n;\n\u003e\n\u003e   return toFixed(scale(progress, start, end), decimal);\n\u003e }\n\u003e\n\u003e function interpolatePixels(t: number, values: number[], decimal = 3) {\n\u003e   const result = interpolateNumber(t, values, decimal);\n\u003e   return `${result}px`;\n\u003e }\n\u003e\n\u003e SpringEasing([0, 250], \"spring\", toAnimationFrames(interpolatePixels));\n\u003e ```\n\u003e\n\u003e \u003c/strike\u003e\n\n\u003e **`NEW`** _Easily register new easing functions._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e import { SpringEasing, registerEasingFunction } from \"spring-easing\";\n\u003e\n\u003e registerEasingFunction(\"linear\", (t) =\u003e t);\n\u003e registerEasingFunctions({\n\u003e   quad: (t) =\u003e Math.pow(t, 2),\n\u003e   cubic: (t) =\u003e Math.pow(t, 3),\n\u003e });\n\u003e\n\u003e SpringEasing([0, 250], \"linear\");\n\u003e\n\u003e SpringEasing([0, 250], \"quad\");\n\u003e ```\n\n\u003e **`NEW`** _SpringEasing now support interpolating between strings. It treats the units of the first value as the units for the rest of the values to interpolate between._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e SpringEasing([\"0turn\", \"1px\", \"18rem\", \"125deg\", 25], ...)\n\u003e ```\n\u003e\n\u003e _**Important** All the values above get transformed to `[\"0turn\", \"1turn\", \"18turn\", \"125turn\", \"25turn\"]`, before being interpolated._\n\n\u003e **`NEW`** _`interpolateStrings`, `interpolateUsingIndex`, and `interpolateComplex`, are now built-in, they allow for supporting string keyframes._\n\n\u003e **`NEW`** _Custom interpolation functions are now supported._\n\u003e e.g.\n\u003e\n\u003e ```ts\n\u003e import { interpolateNumber, toFixed, scale, limit } from \"spring-easing\";\n\u003e // ...\n\u003e export function interpolateColor(t: number, values: string[], decimal = 3) {\n\u003e   const color = transpose(...values.map((v) =\u003e rgba(v))).map(\n\u003e     (colors: number[], i) =\u003e {\n\u003e       const result = interpolateNumber(t, colors);\n\u003e       return i \u003c 3 ? Math.round(result) : toFixed(result, decimal);\n\u003e     }\n\u003e   );\n\u003e\n\u003e   return `rgba(${color.join()})`;\n\u003e }\n\u003e\n\u003e SpringEasing([\"red\", \"green\", \"#4f4\"], \"spring\", interpolateColor);\n\u003e ```\n\u003e\n\u003e _**Important** The logic for color interpolation is defined in this [tests/utils/interpolate-color.ts](https://github.com/okikio/spring-easing/blob/main/tests/utils/interpolate-color.ts)._\n\n\u003c/details\u003e\n\nThe API of `spring-easing` is pretty straight forward, the `SpringEasing` function generates an array of values using a frame functions, which in turn creates the effect of spring easing.\n\nTo use this properly make sure to set the easing animation option to \"linear\".\nCheck out a demo of `SpringEasing` at \u003chttps://codepen.io/okikio/pen/MWEdzNg\u003e\n\n`SpringEasing` has 3 properties they are `easing` (all the easings from [EasingFunctions](https://spring-easing.okikio.dev/variables/easingfunctions) are supported on top of frame functions like `SpringFrame`, `SpringFrameOut`, etc..), `numPoints` (the size of the Array the frame function should create), and `decimal` (the number of decimal places of the values within said Array).\n\n| Properties  | Default Value           |\n| ----------- | ----------------------- |\n| `easing`    | `spring(1, 100, 10, 0)` |\n| `numPoints` | `50`                    |\n| `decimal`   | `3`                     |\n\nBy default, Spring Easing support easings in the form,\n\n| constant | accelerate         | decelerate | accelerate-decelerate | decelerate-accelerate |\n| :------- | :----------------- | :--------- | :-------------------- | :-------------------- |\n|          | spring / spring-in | spring-out | spring-in-out         | spring-out-in         |\n\nAll **Spring** easing's can be configured using theses parameters,\n\n`spring-*(mass, stiffness, damping, velocity)`\n\nEach parameter comes with these defaults\n\n| Parameter | Default Value |\n| --------- | ------------- |\n| mass      | `1`           |\n| stiffness | `100`         |\n| damping   | `10`          |\n| velocity  | `0`           |\n\nTo understand what each of the parameters of `SpringEasing` mean and how they work I suggest looking through the [SpringEasing API Documentation](https://spring-easing.okikio.dev/functions/springeasing)\n\n\u003e _**Note:** the return value of the `SpringEasing` function is actually `[Array of keyframes, duration]`, in that order._\n\nFor a full understanding of what is happening in the library, pleace check out the [API site](https://spring-easing.okikio.dev/modules) for detailed API documentation.\n\n## Browser Support\n\n| Chrome | Edge | Firefox | Safari | IE  |\n| ------ | ---- | ------- | ------ | --- |\n| 4+     | 12+  | 4+      | 4+     | 10+ |\n\nNative support for `spring-easing` is great as it doesn't use any browser specific or nodejs specific API's, you should be good to use `spring-easing` in any environment.\n\n\u003e Note: `CSSSpringEasing` is meant for browsers which have support for the `linear()` easing function,\n\u003e which as of right now is `Chrome \u0026 Edge 113` + `Firefox 112`, Safari doesn't support it yet.\n\n## Contributing\n\nI encourage you to use [pnpm](https://pnpm.io/configuring) to contribute to this repo, but you can also use [yarn](https://classic.yarnpkg.com/lang/en/) or [npm](https://npmjs.com) if you prefer.\n\nInstall all necessary packages\n\n```bash\nnpm install\n```\n\nThen run tests\n\n```bash\nnpm test\n```\n\nBuild project\n\n```bash\nnpm run build\n```\n\nPreview API Docs\n\n```bash\nnpm run typedoc \u0026\u0026 npm run preview\n```\n\n\u003e _**Note**: this project uses [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard for commits, so, please format your commits using the rules it sets out._\n\n## License\n\nSee the [LICENSE](./LICENSE) file for license rights and limitations (MIT).\n\nThe `CSSSpringEasing`, `getOptimizedPoints` and `getLinearSyntax` function are based of the work done by [Jake Archibald](https://github.com/jakearchibald/linear-easing-generator) in his [Linear Easing Generator](https://linear-easing-generator.netlify.app/)\nand are thus licensed under the [Apache License 2.0](https://github.com/jakearchibald/linear-easing-generator/blob/main/LICENSE).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokikio%2Fspring-easing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fokikio%2Fspring-easing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokikio%2Fspring-easing/lists"}