{"id":13428435,"url":"https://github.com/popmotion/popmotion","last_synced_at":"2026-04-02T02:07:52.932Z","repository":{"id":19785585,"uuid":"23044617","full_name":"Popmotion/popmotion","owner":"Popmotion","description":"Simple animation libraries for delightful user interfaces","archived":false,"fork":false,"pushed_at":"2024-03-12T00:37:37.000Z","size":50094,"stargazers_count":20117,"open_issues_count":49,"forks_count":671,"subscribers_count":224,"default_branch":"master","last_synced_at":"2025-05-12T13:06:16.943Z","etag":null,"topics":["animation","css","javascript-motion-engine","motion","physics","popmotion","svg","tween"],"latest_commit_sha":null,"homepage":"https://popmotion.io","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Popmotion.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-17T16:23:07.000Z","updated_at":"2025-05-10T04:39:00.000Z","dependencies_parsed_at":"2024-06-18T10:58:15.051Z","dependency_job_id":null,"html_url":"https://github.com/Popmotion/popmotion","commit_stats":{"total_commits":2760,"total_committers":73,"mean_commits":37.80821917808219,"dds":"0.44637681159420295","last_synced_commit":"adf681efd8568ada018ce68082dbd585f25c4c7d"},"previous_names":["inventingwithmonster/redshift","sirhound/redshift"],"tags_count":160,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Popmotion%2Fpopmotion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Popmotion%2Fpopmotion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Popmotion%2Fpopmotion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Popmotion%2Fpopmotion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Popmotion","download_url":"https://codeload.github.com/Popmotion/popmotion/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253745151,"owners_count":21957317,"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","css","javascript-motion-engine","motion","physics","popmotion","svg","tween"],"created_at":"2024-07-31T01:00:57.184Z","updated_at":"2025-12-12T03:24:21.872Z","avatar_url":"https://github.com/Popmotion.png","language":"JavaScript","readme":"# \u003ca href=\"https://popmotion.io\"\u003e\u003cimg src=\"https://user-images.githubusercontent.com/7850794/90245722-80926e80-de33-11ea-9c39-ea6c5b344217.png\" height=\"52\" width=\"243\" alt=\"Popmotion\" /\u003e\u003c/a\u003e\n\n### The animator's toolbox\n\n[![npm version](https://img.shields.io/npm/v/popmotion.svg?style=flat-square)](https://www.npmjs.com/package/popmotion)\n[![npm downloads](https://img.shields.io/npm/dm/popmotion.svg?style=flat-square)](https://www.npmjs.com/package/popmotion)\n[![Twitter Follow](https://img.shields.io/twitter/follow/popmotionjs.svg?style=social\u0026label=Follow)](http://twitter.com/popmotionjs)\n\nPopmotion is:\n- **Powerful**: It supports keyframe and spring animations for numbers, colors and complex strings.\n- **Low level**: It's designed to be composable and portable into any JavaScript environment, with an eye on worklets in the future.\n- **Stable**: It's written in TypeScript and enjoys over 95% test coverage.\n- **Tiny**: `animate` is just ~4.5kb, and every function is individually importable.\n\n\u003c!-- Documentation --\u003e\n\n## Quick start\n\n```bash\nnpm install popmotion\n```\n\n```javascript\nimport { animate } from \"popmotion\"\n\nanimate({\n  from: 0,\n  to: 100,\n  onUpdate: latest =\u003e console.log(latest)\n})\n```\n\n## Animation\n\n### animate\n\n`animate` performs a keyframes or spring animation.\n\n```javascript\nimport { animate } from \"popmotion\"\n\nanimate({\n  from: 0, \n  to: 100,\n  onUpdate: latest =\u003e console.log(latest)\n})\n```\n\nIt can animate numbers:\n\n```javascript\nanimate({ from: 0, to: 100 })\n```\n\nOr strings of the same type:\n\n```javascript\nanimate({ from: \"0px\", to: \"100px\" })\nanimate({ from: \"#fff\", to: \"#000\" })\n```\n\nThe 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:\n\n```javascript\nanimate({\n  from: \"0px 0px 0px rgba(0, 0, 0, 0)\",\n  to: \"10px 10px 0px rgba(0, 0, 0, 0.2)\"\n})\n```\n\n\u003c!--\nArrays of the above:\n\n```javascript\nanimate({\n  from: [0, \"#fff\"],\n  to: [100, \"#000\"]\n})\n```\n\nAnd objects of the above:\n\n```javascript\nanimate({\n  from: { x: 0, backgroundColor: \"#fff\" },\n  to: { x: 100, backgroundColor: \"#000\" }\n})\n```\n--\u003e\n\nThe 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\"`.\n\n#### Options\n\nThese options can be set for **all animations**:\n\n##### from\n\nAn initial value to start the animation from.\n\nDefaults to `0`\n\n```javascript\nanimate({\n  from: \"linear-gradient(#e66465, #9198e5)\",\n  to: \"linear-gradient(#9198e5, #e66465)\"\n})\n```\n\n##### elapsed\n\nSets an initial elapsed time, in milliseconds. Set to a negative value for a delay.\n\n```javascript\nanimate({\n  to: 100,\n  elapsed: -300\n})\n```\n\n##### repeat\n\nThe number of times to repeat the animation. Set to `Infinity` to repeat forever.\n\n```javascript\nanimate({\n  to: 100,\n  repeat: 2\n})\n```\n\n##### repeatDelay\n\nThe duration, in milliseconds, to wait before repeating the animation.\n\n```javascript\nanimate({\n  to: 100,\n  repeat: 2,\n  repeatDelay: 200\n})\n```\n\n##### repeatType\n\nEither `\"loop\"`, `\"mirror\"` or `\"reverse\"`. Defaults to `\"loop\"`.\n\n- `\"loop\"`: Repeats the animation from `0`.\n- `\"mirror\":` Swaps the `from`/`to` values alternately.\n- `\"reverse\":` Reverses the animation alternately.\n\n```javascript\nanimate({\n  to: 100,\n  repeat: 2,\n  repeatType: \"reverse\"\n})\n```\n\n##### driver\n\nBy default, the animation will be driven by a `requestAnimationFrame` loop. `driver` can specify a different source.\n\nA `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.\n\n```javascript\nconst xrDriver = session =\u003e update =\u003e {\n  let latestRequestId = 0\n  let prevTimestamp = performance.now()\n  \n  const step = timestamp =\u003e {\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 () =\u003e session.cancelRequestAnimationFrame(latestRequestId)\n}\n\nanimate({\n  to: 100,\n  driver: xrDriver(xrSession)\n})\n```\n\n##### type\n\n`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\"`.\n\n```jsx\nanimate({\n  to: 100,\n  type: \"spring\"\n})\n```\n\n#### Lifecycle events\n\nThe following lifecycle events are available for **all animations**:\n\n##### onUpdate\n\nThis is called every frame the animation fires with the latest computed value.\n\n```javascript\nanimate({\n  to: 100,\n  onUpdate: latest =\u003e console.log(latest)\n})\n```\n\n##### onPlay\n\nThis is called when the animation starts. Currently this automatically when `animate` is called.\n\n```javascript\nanimate({\n  to: 100,\n  onPlay: () =\u003e {}\n})\n```\n\n##### onComplete\n\nThis is called when the animation successfully completes.\n\n```javascript\nanimate({\n  to: 100,\n  onComplete:() =\u003e {}\n})\n```\n\n##### onRepeat\n\nThis is called when an animation repeats.\n\n```javascript\nanimate({\n  to: 100,\n  repeat: 2,\n  onRepeat: () =\u003e {}\n})\n```\n\n##### onStop\n\nThis is called when the animation is stopped by the `stop` control.\n\n```javascript\nconst animation = animate({\n  to: 100,\n  onStop: () =\u003e {}\n})\n\nanimation.stop()\n```\n\n#### Keyframes options\n\nA keyframes animation is the default animation type and it can be defined either with a `from` and `to` option:\n\n```javascript\nanimate({ from: 0, to: 100 })\n```\n\nOr as a series of keyframes provided to the `to` option:\n\n```javascript\nanimate({ to: [0, 100, 200] })\n```\n\n##### to\n\nA single value to animate to, or an array of values to animate through.\n\n```javascript\nanimate({\n  to: [\"#0ff\", \"#f00\", \"#0f0\"]\n})\n```\n\nIf `to` is an array, any defined `from` will be ignored.\n\n##### duration\n\nThis defines the duration of the animation, in milliseconds.\n\n```javascript\nanimate({\n  to: 100,\n  duration: 300\n})\n```\n\n##### ease\n\nThis is an easing function, or array of functions, to use when easing between each keyframe.\n\n```javascript\nimport { animate, linear, easeInOut } from \"popmotion\"\n\nanimate({\n  to: 100,\n  ease: linear\n})\n\nanimate({\n  to: [\"#fff\", \"#000\", \"#f00\"],\n  ease: [linear, easeInOut]\n})\n```\n\nIf set as any array, the length of this array must be one shorter than the number of values being animated between.\n\n##### offset\n\nThis is an array of values between `0` and `1` that defines at which point throughout the animation each keyframe should be reached.\n\nThis array should be the same length as the number of defined keyframes.\n\n```javascript\nanimate({\n  to: [\"#fff\", \"#000\", \"#f00\"],\n  offset: [0, 0.2, 1]\n})\n```\n\n#### Spring options\n\nSprings are great for creating natural-feeling interfaces and dynamic interruptable animations.\n\nA spring animation will be used if any of the `stiffness`, `damping` or `mass` options are detected.\n\n**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.\n\n##### to\n\nA single value to animate to.\n\n```javascript\nanimate({\n  to: 100,\n  type: \"spring\"\n})\n```\n\nIf `to` is an array, any defined `from` will be ignored.\n\n##### stiffness\n\nThis defines the stiffness of the spring. A higher stiffness will result in a snappier animation.\n\nDefaults to `100`\n\n```javascript\nanimate({\n  to: 100,\n  stiffness: 1000\n})\n```\n\n##### damping\n\nThis 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.\n\nDefaults to `10`\n\n```javascript\nanimate({\n  to: 100,\n  damping: 50\n})\n```\n\n##### mass\n\nThis is the mass of the animating object. Heavier objects will take longer to speed up and slow down.\n\nDefaults to `1`.\n\n```javascript\nanimate({\n  to: 100,\n  mass: 2\n})\n```\n\n##### velocity\n\nThe initial velocity, in units per second, of the animation.\n\n```javascript\nanimate({\n  to: 100,\n  velocity: 1000\n})\n```\n\n##### duration\n\nThe duration of the spring, in milliseconds.\n\nWill be overridden by `stiffness`, `mass` or `damping`.\n\n```javascript\nanimate({\n  to: 100,\n  duration: 1000\n})\n```\n\n##### bounce\n\nThe bounciness of the spring, as a value between `0` and `1`, where `0` is no bounce.\n\nWill be overridden by `stiffness`, `mass` or `damping`.\n\n```javascript\nanimate({\n  to: 100,\n  bounce: 0.2\n})\n```\n\n##### restDelta\n\nThe distance from the animation target at which the animation can be considered complete. When both `restDelta` and `restSpeed` are met, the animation completes.\n\n```javascript\nanimate({\n  to: 100,\n  restDelta: 0.5\n})\n```\n\n##### restSpeed\n\nThe 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`.\n\n```javascript\nanimate({\n  to: 100,\n  restSpeed: 5\n})\n```\n\n#### Playback controls\n\n`animate` returns `PlaybackControls`, which can be used to control the playback of the animation.\n\nCurrently this only includes a `stop` method, but may expand with more.\n\n##### stop\n\nStops the animation.\n\n```javascript\nconst playback = animate({ from: 0, to: 100 })\nplayback.stop()\n```\n\n### inertia\n\nThe `inertia` animation is used to gradually decelerate a number. Think smartphone scroll momentum.\n\n#### Options\n\nIn addition to `animate`'s `from`, `onUpdate` and `onComplete` options, `inertia` also supports the following:\n\n##### velocity\n\nThe initial velocity, in units per second, of the animation.\n\n```javascript\ninertia({\n  from: 0,\n  velocity: 100\n})\n```\n\n##### power\n\nA constant with which to calculate a target value. Higher power = further target.\n\nDefaults to `0.8`.\n\n```javascript\ninertia({\n  from: 0,\n  power: 0.3\n})\n```\n\n##### timeConstant\n\nAdjusting the time constant will change the duration of the deceleration, thereby affecting its feel.\n\nDefaults to `350`.\n\n```javascript\ninertia({\n  from: 0,\n  velocity: 100,\n  timeConstant: 400\n})\n```\n\n##### modifyTarget\n\nA function that receives the calculated target and returns a new one. Useful for snapping the target to a grid.\n\n```javascript\nconst roundToNearest = target =\u003e v =\u003e Math.ceil(v / target) * target\n\ninertia({\n  from: 0,\n  velocity: 100,\n  modifyTarget: roundToNearest(100)\n})\n```\n\n##### min\n\nThe minimum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.\n\n```javascript\ninertia({\n  from: 50,\n  velocity: -100,\n  min: 0\n})\n```\n\n##### max\n\nThe maximum value at which the animation will switch from gradual deceleration and use a spring animation to snap to this point.\n\n```javascript\ninertia({\n  from: 50,\n  velocity: 100,\n  max: 100\n})\n```\n\n##### bounceStiffness\n\nThis defines the stiffness of the spring when the animation hits either `min` or `max`. A higher stiffness will result in a snappier animation.\n\nDefaults to `500`\n\n```javascript\ninertia({\n  from: 0,\n  velocity: 100,\n  max: 50,\n  bounceStiffness: 1000\n})\n```\n\n##### bounceDamping\n\nThis 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.\n\nDefaults to `10`\n\n```javascript\ninertia({\n  from: 0,\n  velocity: 100,\n  max: 50,\n  bounceDamping: 300\n})\n```\n\n##### restDelta\n\nThe distance from the animation target at which the animation can be considered complete.\n\n```javascript\ninertia({\n  from: 0,\n  velocity: 100,\n  restDelta: 0.5\n})\n```\n\n### Iterators\n\nPowering `animate` and `inertia` are the `keyframes`, `spring`, and `decay` [iterators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol).\n\n```javascript\nimport { keyframes, spring, decay } from \"popmotion\";\n```\n\nIterators give you the ability to run an animation with a high degree of control. For example, [Framer](https://framer.com) uses the `spring` iterator to draw its animation editor visualiser by running it synchronously.\n\nEach can be initialised with the matching options above (`decay` with a subset of `inertia`'s options, excluding the `bounce-` options):\n\n```javascript\nconst animation = spring({\n  from: 0,\n  to: 100,\n  stiffness: 200\n})\n```\n\nWith the returned iterator, you can resolve the animation at a specific timestamp with its `next` method.\n\n```javascript\n// Resolve the animation at 200ms\nconst { value, done } = animation.next(200)\n```\n\n## Easing\n\nPopmotion includes a number of in-built easing functions, as well as factory functions to make entirely new ones.\n\n### Functions\n\nEach easing function can be imported like so:\n\n```javascript\nimport { linear } from \"popmotion\"\n```\n\nEach function accepts a progress value between `0` and `1`, and returns a new one:\n\n```javascript\nconst progress = 0.5\nconst easedProgress = easeInOut(progress)\n```\n\n - `linear`\n - `easeIn`\n - `easeInOut`\n - `easeOut`\n - `circIn`\n - `circInOut`\n - `circOut`\n - `backIn`\n - `backInOut`\n - `backOut`\n - `anticipate`\n - `bounceIn`\n - `bounceInOut`\n - `bounceOut`\n\n### Factories\n\n#### cubicBezier\n\n```javascript\nimport { cubicBezier } from \"popmotion\"\n\nconst easing = cubicBezier(0, .42, 0, 1)\n```\n\nNew cubic bezier definitions can be created in the [Framer](https://framer.com) animation editor and copy/pasted directly into this function.\n\n#### steps\n\n`steps` returns an easing function that will convert the animation into a discrete series of steps.\n\n```javascript\nimport { steps } from \"popmotion\"\n\nconst easing = steps(5)\n```\n\nIt 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.\n\n```javascript\nsteps(5, \"start\")\n```\n\n#### mirrorEasing\n\nMirrors an existing easing function. \n\n#### reverseEasing\n\nReverses an existing easing function. For instance, providing it `easeIn` would return an `easeOut`.\n\n```javascript\nimport { reverseEasing, linear } from \"popmotion\"\n\nconst reversed = reverseEasing(linear)\nreversed(1) // 0\nreversed(0.5) // 0.5\nreversed(0) // 1\n```\n\n#### createExpoIn\n\nCreates an easing function based on the exponent of the provided `power`. The higher the `power`, the stronger the easing.\n\n```javascript\nimport { createExpoIn } from \"popmotion\"\n\nconst expoIn = createExpoIn(4)\n```\n\nThe 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:\n\n```javascript\nconst expoIn = createExpoIn(4)\nconst expoOut = mirrorEasing(easeIn)\nconst expoInOut = reverseEasing(easeIn)\n```\n\n#### createBackIn\n\nCreates an easing function with an overshoot. It accepts a `power` value, the higher the `power` the stronger the overshoot.\n\n```javascript\nimport { createBackIn } from \"popmotion\"\n\nconst backIn = createBackIn(4)\n```\n\nThe 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:\n\n```javascript\nconst backIn = createBackIn(4)\nconst backOut = mirrorEasing(easeIn)\nconst backInOut = reverseEasing(easeIn)\n```\n\n#### createAnticipate\n\nCreates an easing that pulls back a little before animating out with an overshoot. The stronger the `power` the bigger the overshoot.\n\n```javascript\nimport { createAnticipate } from \"popmotion\"\n\nconst anticipate = createAnticipate(4)\n```\n\n## Utils\n\n#### angle\n\nReturns an angle between two points, in degrees.\n\n```javascript\nimport { angle } from \"popmotion\"\n\nangle(\n  { x: 0, y: 0 },\n  { x: 45, y: 100 }\n)\n```\n\n#### attract\n\n\n```javascript\nimport { attract } from \"popmotion\"\n\nattract(5, 10, 12)\n```\n\n#### attractExpo\n\n```javascript\nimport { attractExpo } from \"popmotion\"\n\nattractExpo(5, 10, 12)\n```\n\n#### clamp\n\nClamp a value to within the given range.\n\n```javascript\nimport { clamp } from \"popmotion\"\n\nconst min = 50\nconst max = 100\nclamp(min, max, 150) // 100\n```\n\n#### degreesToRadians\n\nConverts degrees to radians.\n\n```javascript\nimport { degreesToRadians } from \"popmotion\"\n\ndegreesToRadians(45) // 0.785...\n```\n\n#### distance\n\nReturns the distance between two numbers, two 2D points, or two 3D points.\n\n```javascript\nimport { distance } from \"popmotion\"\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 })\n```\n\n#### interpolate\n\nCreates 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.\n\n```javascript\nimport { interpolate } from \"popmotion\"\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: \"#fff\" },\n    { x: 100, color: \"#000\" }\n  ]\n)\nmapProgressToValues(0.5) // { x: 50, color: \"#888\" }\n\nconst rescale = interpolate(\n  [0, 1],\n  [100, 200],\n  { clamp: false }\n)\nrescale(2) // 300\n```\n\n#### Options\n\n`interpolate` accepts an optional third argument, an object of options.\n\n- `clamp`: Clamps values to within given range. Defaults to `true`.\n- `ease`: An `Easing` function, or array of easing functions, to ease the interpolation of each segment.\n- `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.\n\n#### isPoint\n\nReturns `true` if the provided argument is a 2D point.\n\n```javascript\nimport { isPoint } from \"popmotion\"\n\nisPoint({ x: 0 }) // false\nisPoint({ x: 0, y: 0 }) // true\n```\n\n#### isPoint3D\n\nReturns `true` if the provided argument is a 3D point.\n\n```javascript\nimport { isPoint3D } from \"popmotion\"\n\nisPoint3D({ x: 0 }) // false\nisPoint3D({ x: 0, y: 0 }) // false\nisPoint3D({ x: 0, y: 0, z: 0 }) // true\n```\n\n#### mix\n\nWill mix between two values, given `progress` as a third argument.\n\n```javascript\nimport { mix } from \"popmotion\"\n\nmix(0, 100, 0.5) // 50\nmix(0, 100, 2) // 200\n```\n\n#### mixColor\n\nReturns a function that, when provided a `progress` value, will mix between two colors. Accepts hex, rgba and hsla colors.\n\n```javascript\nimport { mixColor } from \"popmotion\"\n\nmixColor(\"#000\", \"#fff\")(0.5) // \"rgba(125, 125, 125, 1)\"\n```\n\n#### mixComplex\n\nReturns a function that, when provided a `progress` value, will mix between two strings with the same order of numbers and colors.\n\n```javascript\nimport { mixComplex } from \"popmotion\"\n\nmixComplex(\"100px #fff\", \"0px #000\")(0.5) // \"50px rgba(125, 125, 125, 1)\"\n```\n\n#### pointFromVector\n\nGiven a point, angle in degrees, and distance, will return a new point.\n\n```javascript\nimport { pointFromVector } from \"popmotion\"\n\nconst point = { x: 0, y: 0 }\nconst angle = 45\nconst distance = 100\n\npointFromVector(point, angle, distance)\n```\n\n#### progress\n\nGiven 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.\n\n```javascript\nimport { progress } from \"popmotion\"\n\nconst min = 100\nconst max = 200\nprogress(min, max, 150) // 0.5\n```\n\n#### radiansToDegrees\n\nConverts radians to degrees.\n\n```javascript\nimport { radiansToDegrees } from \"popmotion\"\n\nradiansToDegrees(0.785) // 45\n```\n\n#### snap\n\nCreates a function that will snap numbers to the nearest in a provided array or to a regular interval.\n\n```javascript\nimport { snap } from \"popmotion\"\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\n```\n\n#### toDecimal\n\nRounds a number to a specific decimal place.\n\n```javascript\nimport { toDecimal } from \"popmotion\"\n\ntoDecimal(3.3333); // 3.33\ntoDecimal(6.6666, 1); // 6.67\n```\n\n#### velocityPerFrame\n\n```javascript\nimport { velocityPerFrame } from \"popmotion\"\n\nvelocityPerFrame(50, 16.7); // 0.835\n```\n\n#### velocityPerSecond\n\n```javascript\nimport { velocityPerSecond } from \"popmotion\"\n\nvelocityPerSecond(1, 16.7); // 59.880...\n```\n\n#### wrap\n\n```javascript\nimport { wrap } from \"popmotion\"\n\nwrap(0, 1, 0.5); // 0.5\nwrap(0, 1, 1.5); // 0.5\n```\n\n","funding_links":[],"categories":["Programming Languages","Components \u0026\u0026 Librarys"],"sub_categories":["JavaScript","Animations"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpopmotion%2Fpopmotion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpopmotion%2Fpopmotion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpopmotion%2Fpopmotion/lists"}