troika-animation
Advanced tools
Comparing version 0.16.0 to 0.17.0
@@ -1,2 +0,2 @@ | ||
import {number, color} from '../src/Interpolators' | ||
import {number, color} from '../src/Interpolators.js' | ||
@@ -45,2 +45,2 @@ test('number interpolator', () => { | ||
}) | ||
}) | ||
}) |
@@ -1,3 +0,3 @@ | ||
import MultiTween from '../src/MultiTween' | ||
import Tween from '../src/Tween' | ||
import MultiTween from '../src/MultiTween.js' | ||
import Tween from '../src/Tween.js' | ||
@@ -4,0 +4,0 @@ |
@@ -1,2 +0,2 @@ | ||
import Tween from '../src/Tween' | ||
import Tween from '../src/Tween.js' | ||
@@ -289,2 +289,2 @@ | ||
}) | ||
}) | ||
}) |
@@ -11,7 +11,5 @@ /* | ||
var pow = Math.pow; | ||
var PI = Math.PI; | ||
var sqrt = Math.sqrt; | ||
var HALF_PI = PI / 2; | ||
var TWO_PI = PI * 2; | ||
const {pow, PI, sqrt} = Math; | ||
const HALF_PI = PI / 2; | ||
const TWO_PI = PI * 2; | ||
@@ -21,67 +19,76 @@ | ||
function makeInOut(inFn, outFn) { | ||
return function (t) { return t < 0.5 ? inFn(t * 2) * 0.5 : outFn(t * 2 - 1) * 0.5 + 0.5; } | ||
return t => t < 0.5 ? inFn(t * 2) * 0.5 : outFn(t * 2 - 1) * 0.5 + 0.5 | ||
} | ||
function makeExpIn(exp) { | ||
return function (t) { return pow(t, exp); } | ||
return t => pow(t, exp) | ||
} | ||
function makeExpOut(exp) { | ||
return function (t) { return 1 - pow(1 - t, exp); } | ||
return t => 1 - pow(1 - t, exp) | ||
} | ||
function makeExpInOut(exp) { | ||
return function (t) { return t < 0.5 ? | ||
return t => t < 0.5 ? | ||
pow(t * 2, exp) * 0.5 : | ||
(1 - pow(1 - (t * 2 - 1), exp)) * 0.5 + 0.5; } | ||
(1 - pow(1 - (t * 2 - 1), exp)) * 0.5 + 0.5 | ||
} | ||
var linear = function (t) { return t; }; | ||
const linear = t => t; | ||
var easeInQuad = makeExpIn(2); | ||
var easeOutQuad = makeExpOut(2); | ||
var easeInOutQuad = makeExpInOut(2); | ||
const easeInQuad = makeExpIn(2); | ||
const easeOutQuad = makeExpOut(2); | ||
const easeInOutQuad = makeExpInOut(2); | ||
var easeInCubic = makeExpIn(3); | ||
var easeOutCubic = makeExpOut(3); | ||
var easeInOutCubic = makeExpInOut(3); | ||
const easeInCubic = makeExpIn(3); | ||
const easeOutCubic = makeExpOut(3); | ||
const easeInOutCubic = makeExpInOut(3); | ||
var easeInQuart = makeExpIn(4); | ||
var easeOutQuart = makeExpOut(4); | ||
var easeInOutQuart = makeExpInOut(4); | ||
const easeInQuart = makeExpIn(4); | ||
const easeOutQuart = makeExpOut(4); | ||
const easeInOutQuart = makeExpInOut(4); | ||
var easeInQuint = makeExpIn(5); | ||
var easeOutQuint = makeExpOut(5); | ||
var easeInOutQuint = makeExpInOut(5); | ||
const easeInQuint = makeExpIn(5); | ||
const easeOutQuint = makeExpOut(5); | ||
const easeInOutQuint = makeExpInOut(5); | ||
var easeInSine = function (t) { return 1 - Math.cos(t * (HALF_PI)); }; | ||
var easeOutSine = function (t) { return Math.sin(t * (HALF_PI)); }; | ||
var easeInOutSine = function (t) { return -0.5 * (Math.cos(PI * t) - 1); }; | ||
const easeInSine = t => 1 - Math.cos(t * (HALF_PI)); | ||
const easeOutSine = t => Math.sin(t * (HALF_PI)); | ||
const easeInOutSine = t => -0.5 * (Math.cos(PI * t) - 1); | ||
var easeInExpo = function (t) { return (t === 0) ? 0 : pow(2, 10 * (t - 1)); }; | ||
const easeInExpo = t => | ||
(t === 0) ? 0 : pow(2, 10 * (t - 1)); | ||
var easeOutExpo = function (t) { return (t === 1) ? 1 : 1 - pow(2, -10 * t); }; | ||
const easeOutExpo = t => | ||
(t === 1) ? 1 : 1 - pow(2, -10 * t); | ||
var easeInOutExpo = function (t) { return (t === 0 || t === 1) ? t : | ||
const easeInOutExpo = t => | ||
(t === 0 || t === 1) ? t : | ||
t < 0.5 ? | ||
pow(2, 10 * (t * 2 - 1)) * 0.5 : | ||
(1 - pow(2, -10 * (t * 2 - 1))) * 0.5 + 0.5; }; | ||
(1 - pow(2, -10 * (t * 2 - 1))) * 0.5 + 0.5; | ||
var easeInCirc = function (t) { return 1 - sqrt(1 - t * t); }; | ||
const easeInCirc = t => | ||
1 - sqrt(1 - t * t); | ||
var easeOutCirc = function (t) { return sqrt(1 - pow(t - 1, 2)); }; | ||
const easeOutCirc = t => | ||
sqrt(1 - pow(t - 1, 2)); | ||
var easeInOutCirc = makeInOut(easeInCirc, easeOutCirc); | ||
const easeInOutCirc = makeInOut(easeInCirc, easeOutCirc); | ||
var easeInElastic = function (t) { return (t === 0 || t === 1) ? t : 1 - easeOutElastic(1 - t); }; | ||
const easeInElastic = t => | ||
(t === 0 || t === 1) ? t : 1 - easeOutElastic(1 - t); | ||
var easeOutElastic = function (t) { return (t === 0 || t === 1) ? t : | ||
Math.pow(2, -10 * t) * Math.sin((t - 0.075) * TWO_PI / 0.3) + 1; }; | ||
const easeOutElastic = t => | ||
(t === 0 || t === 1) ? t : | ||
Math.pow(2, -10 * t) * Math.sin((t - 0.075) * TWO_PI / 0.3) + 1; | ||
var easeInOutElastic = makeInOut(easeInElastic, easeOutElastic); | ||
const easeInOutElastic = makeInOut(easeInElastic, easeOutElastic); | ||
var easeInBack = function (t) { return t * t * (2.70158 * t - 1.70158); }; | ||
const easeInBack = t => | ||
t * t * (2.70158 * t - 1.70158); | ||
var easeOutBack = function (t) { return (t -= 1) * t * (2.70158 * t + 1.70158) + 1; }; | ||
const easeOutBack = t => | ||
(t -= 1) * t * (2.70158 * t + 1.70158) + 1; | ||
var easeInOutBack = function (t) { | ||
var s = 1.70158 * 1.525; | ||
const easeInOutBack = t => { | ||
const s = 1.70158 * 1.525; | ||
return (t *= 2) < 1 ? | ||
@@ -92,5 +99,7 @@ 0.5 * (t * t * ((s + 1) * t - s)) : | ||
var easeInBounce = function (t) { return 1 - easeOutBounce(1 - t); }; | ||
const easeInBounce = t => | ||
1 - easeOutBounce(1 - t); | ||
var easeOutBounce = function (t) { return t < (1 / 2.75) ? | ||
const easeOutBounce = t => | ||
t < (1 / 2.75) ? | ||
(7.5625 * t * t) : | ||
@@ -101,5 +110,5 @@ t < (2 / 2.75) ? | ||
(7.5625 * (t -= (2.25 / 2.75)) * t + .9375) : | ||
(7.5625 * (t -= (2.625 / 2.75)) * t + .984375); }; | ||
(7.5625 * (t -= (2.625 / 2.75)) * t + .984375); | ||
var easeInOutBounce = makeInOut(easeInBounce, easeOutBounce); | ||
const easeInOutBounce = makeInOut(easeInBounce, easeOutBounce); | ||
@@ -259,9 +268,9 @@ // Aliases...? | ||
*/ | ||
var colorValueToNumber = (function() { | ||
var colorCanvas, colorCanvasCtx; | ||
const colorValueToNumber = (function() { | ||
let colorCanvas, colorCanvasCtx; | ||
// Cache for evaluated string values | ||
var stringCache = Object.create(null); | ||
var stringCacheSize = 0; | ||
var stringCacheMaxSize = 2048; | ||
let stringCache = Object.create(null); | ||
let stringCacheSize = 0; | ||
const stringCacheMaxSize = 2048; | ||
@@ -286,4 +295,4 @@ return function(value) { | ||
colorCanvasCtx.fillRect(0, 0, 1, 1); | ||
var colorData = colorCanvasCtx.getImageData(0, 0, 1, 1).data; | ||
var result = rgbToNumber(colorData[0], colorData[1], colorData[2]); | ||
const colorData = colorCanvasCtx.getImageData(0, 0, 1, 1).data; | ||
const result = rgbToNumber(colorData[0], colorData[1], colorData[2]); | ||
@@ -323,4 +332,4 @@ // Enforce max cache size - for now this invalidates the entire cache when reaching | ||
var linear$1 = function (v) { return v; }; | ||
var maxSafeInteger = 0x1fffffffffffff; | ||
const linear$1 = v => v; | ||
const maxSafeInteger = 0x1fffffffffffff; | ||
@@ -351,57 +360,52 @@ /** | ||
*/ | ||
var Tween = function Tween(callback, fromValue, toValue, duration, delay, easing, iterations, direction, interpolate) { | ||
if ( duration === void 0 ) duration=750; | ||
if ( delay === void 0 ) delay=0; | ||
if ( easing === void 0 ) easing=linear$1; | ||
if ( iterations === void 0 ) iterations=1; | ||
if ( direction === void 0 ) direction='forward'; | ||
if ( interpolate === void 0 ) interpolate='number'; | ||
class Tween { | ||
constructor(callback, fromValue, toValue, duration=750, delay=0, easing=linear$1, iterations=1, direction='forward', interpolate='number') { | ||
this.callback = callback; | ||
this.fromValue = fromValue; | ||
this.toValue = toValue; | ||
this.duration = duration; | ||
this.delay = delay; | ||
this.easing = typeof easing === 'string' ? (Easings[easing] || linear$1) : easing; | ||
this.iterations = iterations; | ||
this.direction = direction; | ||
this.interpolate = typeof interpolate === 'function' ? interpolate : Interpolators[interpolate] || number; | ||
this.callback = callback; | ||
this.fromValue = fromValue; | ||
this.toValue = toValue; | ||
this.duration = duration; | ||
this.delay = delay; | ||
this.easing = typeof easing === 'string' ? (Easings[easing] || linear$1) : easing; | ||
this.iterations = iterations; | ||
this.direction = direction; | ||
this.interpolate = typeof interpolate === 'function' ? interpolate : Interpolators[interpolate] || number; | ||
/** | ||
* @property totalElapsed | ||
* @type {number} | ||
* The total duration of this tween from 0 to its completion, taking into account its `duration`, `delay`, and | ||
* `iterations`. This is calculated once upon instantiation, and may be used to determine whether the tween is | ||
* finished or not at a given time. | ||
*/ | ||
this.totalElapsed = this.iterations < maxSafeInteger ? this.delay + (this.duration * this.iterations) : maxSafeInteger; | ||
} | ||
/** | ||
* @property totalElapsed | ||
* @type {number} | ||
* The total duration of this tween from 0 to its completion, taking into account its `duration`, `delay`, and | ||
* `iterations`. This is calculated once upon instantiation, and may be used to determine whether the tween is | ||
* finished or not at a given time. | ||
* For a given elapsed time relative to the start of the tween, calculates the value at that time and calls the | ||
* `callback` function with that value. If the given time is during the `delay` period, the callback will not be | ||
* invoked. | ||
* @param {number} time | ||
*/ | ||
this.totalElapsed = this.iterations < maxSafeInteger ? this.delay + (this.duration * this.iterations) : maxSafeInteger; | ||
}; | ||
/** | ||
* For a given elapsed time relative to the start of the tween, calculates the value at that time and calls the | ||
* `callback` function with that value. If the given time is during the `delay` period, the callback will not be | ||
* invoked. | ||
* @param {number} time | ||
*/ | ||
Tween.prototype.gotoElapsedTime = function gotoElapsedTime (time) { | ||
var duration = this.duration; | ||
var delay = this.delay; | ||
if (time >= delay) { | ||
time = Math.min(time, this.totalElapsed) - delay; //never go past final value | ||
var progress = (time % duration) / duration; | ||
if (progress === 0 && time !== 0) { progress = 1; } | ||
progress = this.easing(progress); | ||
if (this.direction === 'reverse' || (this.direction === 'alternate' && Math.ceil(time / duration) % 2 === 0)) { | ||
progress = 1 - progress; | ||
gotoElapsedTime(time) { | ||
let duration = this.duration; | ||
let delay = this.delay; | ||
if (time >= delay) { | ||
time = Math.min(time, this.totalElapsed) - delay; //never go past final value | ||
let progress = (time % duration) / duration; | ||
if (progress === 0 && time !== 0) progress = 1; | ||
progress = this.easing(progress); | ||
if (this.direction === 'reverse' || (this.direction === 'alternate' && Math.ceil(time / duration) % 2 === 0)) { | ||
progress = 1 - progress; | ||
} | ||
this.callback(this.interpolate(this.fromValue, this.toValue, progress)); | ||
} | ||
this.callback(this.interpolate(this.fromValue, this.toValue, progress)); | ||
} | ||
}; | ||
/** | ||
* Like `gotoElapsedTime` but goes to the very end of the tween. | ||
*/ | ||
Tween.prototype.gotoEnd = function gotoEnd () { | ||
this.gotoElapsedTime(this.totalElapsed); | ||
}; | ||
/** | ||
* Like `gotoElapsedTime` but goes to the very end of the tween. | ||
*/ | ||
gotoEnd() { | ||
this.gotoElapsedTime(this.totalElapsed); | ||
} | ||
} | ||
@@ -412,7 +416,7 @@ /** | ||
*/ | ||
var MultiTween = /*@__PURE__*/(function (Tween) { | ||
function MultiTween(tweens, duration, delay, easing, iterations, direction) { | ||
class MultiTween extends Tween { | ||
constructor(tweens, duration, delay, easing, iterations, direction) { | ||
if (typeof duration !== 'number') { | ||
// Calculate duration based on the longest individual total duration | ||
duration = tweens.reduce(function (dur, tween) { return Math.max(dur, tween.totalElapsed); }, 0); | ||
duration = tweens.reduce((dur, tween) => Math.max(dur, tween.totalElapsed), 0); | ||
} | ||
@@ -425,3 +429,3 @@ if (duration === Infinity) { | ||
// Tween the total duration time | ||
Tween.call(this, null, 0, duration, duration, delay, easing, iterations, direction); | ||
super(null, 0, duration, duration, delay, easing, iterations, direction); | ||
if (tweens.length === 1) { | ||
@@ -436,7 +440,3 @@ this.callback = tweens[0].gotoElapsedTime.bind(tweens[0]); | ||
if ( Tween ) MultiTween.__proto__ = Tween; | ||
MultiTween.prototype = Object.create( Tween && Tween.prototype ); | ||
MultiTween.prototype.constructor = MultiTween; | ||
MultiTween.prototype._syncTweens = function _syncTweens (time) { | ||
_syncTweens(time) { | ||
// NOTE: forward iteration is important here so the tweens are evaluated in order | ||
@@ -447,10 +447,8 @@ // of when they end; that way later tweens will take precedence over earlier ones. | ||
// slightly prior to their end state. | ||
for (var i = 0, len = this.tweens.length; i < len; i++) { | ||
for (let i = 0, len = this.tweens.length; i < len; i++) { | ||
this.tweens[i].gotoElapsedTime(time); | ||
} | ||
}; | ||
} | ||
} | ||
return MultiTween; | ||
}(Tween)); | ||
function endTimeComparator(a, b) { | ||
@@ -460,5 +458,5 @@ return a.totalElapsed - b.totalElapsed | ||
var runners = []; | ||
var nextFrameTimer = null; | ||
var hasStoppedRunners = false; | ||
let runners = []; | ||
let nextFrameTimer = null; | ||
let hasStoppedRunners = false; | ||
@@ -471,3 +469,3 @@ function noop() {} | ||
function tick() { | ||
var now = Date.now(); | ||
let now = Date.now(); | ||
nextFrameTimer = null; | ||
@@ -483,3 +481,3 @@ | ||
// Sync each runner, filtering out empty ones as we go | ||
for (var i = runners.length; i-- > 0;) { | ||
for (let i = runners.length; i-- > 0;) { | ||
runners[i]._tick(now); | ||
@@ -492,3 +490,3 @@ } | ||
var _scheduler = window; | ||
let _scheduler = window; | ||
@@ -541,120 +539,122 @@ /** | ||
*/ | ||
var Runner = function Runner() { | ||
this.tweens = []; | ||
}; | ||
class Runner { | ||
constructor() { | ||
this.tweens = []; | ||
} | ||
Runner.prototype.destructor = function destructor () { | ||
this.tweens = null; | ||
stopRunner(this); | ||
this.start = this.stop = this.pause = this._tick = noop; | ||
}; | ||
/** | ||
* Add a tween to the runner. It will be invoked on the next frame, not immediately. | ||
* @param {Tween} tween | ||
*/ | ||
Runner.prototype.start = function start (tween) { | ||
// If previously paused, update start time to account for the duration of the pause | ||
if (tween.runner$paused && tween.runner$started) { | ||
tween.runner$started += (Date.now() - tween.runner$paused); | ||
} else { | ||
this.tweens.push(tween); | ||
destructor() { | ||
this.tweens = null; | ||
stopRunner(this); | ||
this.start = this.stop = this.pause = this._tick = noop; | ||
} | ||
tween.runner$paused = null; | ||
tween.runner$stopped = false; | ||
// add runner to running runners | ||
startRunner(this); | ||
}; | ||
/** | ||
* Add a tween to the runner. It will be invoked on the next frame, not immediately. | ||
* @param {Tween} tween | ||
*/ | ||
start(tween) { | ||
// If previously paused, update start time to account for the duration of the pause | ||
if (tween.runner$paused && tween.runner$started) { | ||
tween.runner$started += (Date.now() - tween.runner$paused); | ||
} else { | ||
this.tweens.push(tween); | ||
} | ||
tween.runner$paused = null; | ||
tween.runner$stopped = false; | ||
/** | ||
* Remove a tween from the runner. | ||
* @param tween | ||
*/ | ||
Runner.prototype.stop = function stop (tween) { | ||
// queue tween for removal from list on next tick | ||
tween.runner$stopped = true; | ||
tween.runner$paused = null; | ||
}; | ||
// add runner to running runners | ||
startRunner(this); | ||
} | ||
/** | ||
* Pause a tween; call `runner.start(tween)` to unpause it | ||
* @param tween | ||
*/ | ||
Runner.prototype.pause = function pause (tween) { | ||
if (!tween.runner$paused) { | ||
tween.runner$paused = Date.now(); | ||
/** | ||
* Remove a tween from the runner. | ||
* @param tween | ||
*/ | ||
stop(tween) { | ||
// queue tween for removal from list on next tick | ||
tween.runner$stopped = true; | ||
tween.runner$paused = null; | ||
} | ||
}; | ||
/** | ||
* Stop all running tweens. | ||
*/ | ||
Runner.prototype.stopAll = function stopAll () { | ||
if (this.tweens) { | ||
this.tweens.forEach(this.stop, this); | ||
/** | ||
* Pause a tween; call `runner.start(tween)` to unpause it | ||
* @param tween | ||
*/ | ||
pause(tween) { | ||
if (!tween.runner$paused) { | ||
tween.runner$paused = Date.now(); | ||
} | ||
} | ||
}; | ||
Runner.prototype._tick = function _tick (now) { | ||
var tweens = this.tweens; | ||
var hasStoppedTweens = false; | ||
var hasRunningTweens = false; | ||
/** | ||
* Stop all running tweens. | ||
*/ | ||
stopAll() { | ||
if (this.tweens) { | ||
this.tweens.forEach(this.stop, this); | ||
} | ||
} | ||
// Sync each tween, filtering out old finished ones as we go | ||
for (var i = 0, len = tweens.length; i < len; i++) { | ||
var tween = tweens[i]; | ||
if (!tween.runner$stopped && !tween.runner$paused) { | ||
// Sync the tween to current time | ||
var elapsed = now - (tween.runner$started || (tween.runner$started = now)); | ||
tween.gotoElapsedTime(elapsed); | ||
hasRunningTweens = true; | ||
_tick(now) { | ||
let tweens = this.tweens; | ||
let hasStoppedTweens = false; | ||
let hasRunningTweens = false; | ||
// Queue for removal if we're past its end time | ||
if (elapsed > tween.totalElapsed) { | ||
this.stop(tween); | ||
if (tween.onDone) { | ||
tween.onDone(); | ||
// Sync each tween, filtering out old finished ones as we go | ||
for (let i = 0, len = tweens.length; i < len; i++) { | ||
let tween = tweens[i]; | ||
if (!tween.runner$stopped && !tween.runner$paused) { | ||
// Sync the tween to current time | ||
let elapsed = now - (tween.runner$started || (tween.runner$started = now)); | ||
tween.gotoElapsedTime(elapsed); | ||
hasRunningTweens = true; | ||
// Queue for removal if we're past its end time | ||
if (elapsed > tween.totalElapsed) { | ||
this.stop(tween); | ||
if (tween.onDone) { | ||
tween.onDone(); | ||
} | ||
} | ||
} | ||
if (tween.runner$stopped) { | ||
hasStoppedTweens = true; | ||
} | ||
} | ||
if (tween.runner$stopped) { | ||
hasStoppedTweens = true; | ||
if (hasRunningTweens) { | ||
this.onTick(); | ||
} | ||
} | ||
if (hasRunningTweens) { | ||
this.onTick(); | ||
} | ||
// Prune list if needed | ||
// TODO perhaps batch this up so it happens less often | ||
if (hasStoppedTweens) { | ||
this.tweens = tweens.filter(isTweenNotStopped); | ||
// Prune list if needed | ||
// TODO perhaps batch this up so it happens less often | ||
if (hasStoppedTweens) { | ||
this.tweens = tweens.filter(isTweenNotStopped); | ||
// remove runner from running runners if it has no tweens left | ||
if (!this.tweens.length) { | ||
stopRunner(this); | ||
if (this.onDone) { | ||
this.onDone(); | ||
// remove runner from running runners if it has no tweens left | ||
if (!this.tweens.length) { | ||
stopRunner(this); | ||
if (this.onDone) { | ||
this.onDone(); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
/** | ||
* Override to specify a function that will be called at the end of every frame, after all | ||
* tweens have been updated. | ||
*/ | ||
Runner.prototype.onTick = function onTick () { | ||
// abstract | ||
}; | ||
/** | ||
* Override to specify a function that will be called at the end of every frame, after all | ||
* tweens have been updated. | ||
*/ | ||
onTick() { | ||
// abstract | ||
} | ||
/** | ||
* Override to specify a function that will be called after all running tweens have completed. | ||
*/ | ||
Runner.prototype.onDone = function onDone () { | ||
// abstract | ||
}; | ||
/** | ||
* Override to specify a function that will be called after all running tweens have completed. | ||
*/ | ||
onDone() { | ||
// abstract | ||
} | ||
} | ||
export { Easings, Interpolators, MultiTween, Runner, Tween, setAnimationScheduler }; |
{ | ||
"name": "troika-animation", | ||
"version": "0.16.0", | ||
"version": "0.17.0", | ||
"description": "Troika Animation Utilities", | ||
@@ -17,3 +17,3 @@ "author": "Jason Johnston <jason.johnston@protectwise.com>", | ||
"module:es2015": "src/index.js", | ||
"gitHead": "b17e3967b2166f102cabc6cd4bf46f5a725a8910" | ||
"gitHead": "31909f4beed23f5913aa380db1dd3c1802798b39" | ||
} |
@@ -1,11 +0,101 @@ | ||
# `troika-animation` | ||
# Troika Animation | ||
> TODO: description | ||
This package provides a small library for "tweening" values over time, heavily optimized for performance. It is used by the Troika framework behind the scenes for its declarative `transition` and `animation` features, but can also be used as a standalone library. | ||
## Installation | ||
If you're using the Troika framework, you don't need to install this directly. If you want to use it standalone, you can get it from [NPM](https://www.npmjs.com/package/troika-animation): | ||
```sh | ||
npm install troika-animation | ||
``` | ||
## Usage | ||
To animate a value, you basically need to: | ||
1. Create a `Tween` describing the start and end values, how the value should change over time, and a callback to invoke on each frame | ||
2. Create a `Runner` | ||
3. Start the tween in the runner | ||
### Tween | ||
> See the JSDoc comments in [Tween.js](./src/Tween.js) for more details about each parameter. | ||
```js | ||
import { Tween } from 'troika-animation' | ||
function onTweenFrame(tweenedValue) { | ||
// ...do something with the tweenedValue | ||
} | ||
const tween = new Tween( | ||
onTweenFrame, // callback | ||
-100, // fromValue | ||
100, // toValue | ||
5000, // duration in ms | ||
0, // delay | ||
'easeOutExpo', // easing | ||
1, // iterations | ||
'forward', // direction | ||
'number' // interpolation | ||
) | ||
``` | ||
import troikaAnimation from 'troika-animation'; | ||
// TODO: DEMONSTRATE API | ||
### MultiTween | ||
This is a specialized `Tween` that, instead of managing a value, manages a list of other `Tween`s. It essentially creates a sub-timeline, whose playback is controlled as a whole. For example you can apply an `easing` to the entire set of tweens as a whole, stretch out their duration, repeat them, etc. | ||
```js | ||
import { MultiTween, Tween } from 'troika-animation' | ||
const tween1 = new Tween(/*...*/) | ||
const tween2 = new Tween(/*...*/) | ||
const multiTween = new MultiTween( | ||
[tween1, tween2], // list of tweens | ||
5000, // duration | ||
0, // delay | ||
'easeInOutExpo', // easing | ||
10, // iterations | ||
'alternate' // direction | ||
) | ||
``` | ||
### Runner | ||
> Also see the JSDoc comments in [Runner.js](./src/Runner.js) | ||
```js | ||
import { Tween, Runner } from 'troika-animation' | ||
const tween = new Tween(/*...*/) | ||
const runner = new Runner() | ||
runner.start(tween) | ||
``` | ||
### Easings | ||
When constructing a Tween, the `easing` parameter controls the rate of change over time. You can either specify a string, referring to the name of one of the built-in easing functions, or you can provide a custom easing function. | ||
#### Built-in named easings | ||
The built-in named easings can be found in [Easings.js](./src/Easings.js). These may be familiar, as they mostly match the ones provided by the popular [jQuery Easing Plugin](https://github.com/danro/jquery-easing/blob/master/jquery.easing.js) and [easings.net](https://easings.net). | ||
There is also an online [demo of troika-animation easings](https://troika-examples.netlify.com/#easings) that shows the curve for each. | ||
#### Custom easing functions | ||
An easing function takes a single parameter `t`, which refers to the fraction of time passed in the tween's duration from 0 to 1. It must return a number specifying the progress between the start and end values at `t`; 0 corresponds to the start value and 1 corresponds to the end value. Most easings stay in the range from 0 to 1 but some may exceed it. | ||
### Interpolation | ||
The tween `interpolation` parameter controls how the fractional value returned from the `easing` is applied to the start and end values to calculate the in-between value. In most cases you're probably tweening two numbers, which is handled as the default interpolation. But if you have a different type of value, you may need to change the interpolator. | ||
Two built-in interpolation types are provided, which can be referred to by their string names (see [Interpolators.js](./src/Interpolators.js)) | ||
- `"number"` - simple linear interpolation between two numeric values (the default). | ||
- `"color"` - interprets the start/end values as RGB colors, and interpolates each color channel independently. | ||
If you need a different interpolation, you can provide a custom function. It takes three parameters: the start value, the end value, and the progress between them (the output of the easing function.) It must return an in-between value of the appropriate type. |
@@ -1,2 +0,2 @@ | ||
import Tween from './Tween' | ||
import Tween from './Tween.js' | ||
@@ -3,0 +3,0 @@ |
@@ -1,3 +0,3 @@ | ||
import * as Easings from './Easings' | ||
import * as Interpolators from './Interpolators' | ||
import * as Easings from './Easings.js' | ||
import * as Interpolators from './Interpolators.js' | ||
@@ -4,0 +4,0 @@ const linear = v => v |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
93454
2099
102