Skip to content

Commit

Permalink
feat(math): add lens(), invCircular() interpolators
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Sep 4, 2020
1 parent 5a14144 commit 56dce17
Showing 1 changed file with 47 additions and 4 deletions.
51 changes: 47 additions & 4 deletions packages/math/src/mix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,58 @@ export const tween = (f: (t: number) => number, from: number, to: number) => (
) => mix(from, to, f(t));

/**
* Circular interpolation: `sqrt(1 - (1 - t)^2)`
* Circular interpolation (ease out): `sqrt(1 - (1 - t)^2)`
*
* @param t - interpolation factor (0.0 .. 1.0)
* Reference: https://www.desmos.com/calculator/tisoiazdrw
*
* @param t - interpolation factor [0..1]
*/
export const circular = (t: number) => {
t = 1 - t;
return Math.sqrt(1 - t * t);
};

/**
* Inverse/flipped version of {@link circular} (ease in).
*
* Reference: https://www.desmos.com/calculator/tisoiazdrw
*
* @param t - interpolation factor [0..1]
*/
export const invCircular = (t: number) => 1 - circular(1 - t);

/**
* Zoomlens interpolation with customizable lens position, behavior and
* strength.
*
* @remarks
* Lens position must be given in (0..1) interval. Lens strength must be in
* [-1,1] range. If negative, the lens will be bundling values near `pos`, if
* positive the lens has dilating characteristics and will spread values near
* `pos` towards the edges.
*
* @example
* ```ts
* // interpolated position in [100..400] interval for given `t`
* y = mix(100, 400, lens(0.5, 1, t));
*
* // or build tween function via `tween()`
* f = tween(partial(lens, 0.5, 1), 100, 400);
*
* f(t)
* ```
*
* @param pos - lens pos
* @param strength - lens strength
* @param t - interpolation factor [0..1]
*/
export const lens = (pos: number, strength: number, t: number) => {
const impl = strength > 0 ? invCircular : circular;
const tp = 1 - pos;
const tl = t <= pos ? impl(t / pos) * pos : 1 - impl((1 - t) / tp) * tp;
return mix(t, tl, Math.abs(strength));
};

export const cosine = (t: number) => 1 - (Math.cos(t * PI) * 0.5 + 0.5);

export const decimated = (n: number, t: number) => Math.floor(t * n) / n;
Expand All @@ -201,7 +244,7 @@ export const bounce = (k: number, amp: number, t: number) => {
};

/**
* HOF exponential easing.
* Exponential easing.
*
* - `ease = 1` -> linear
* - `ease > 1` -> ease in
Expand All @@ -213,7 +256,7 @@ export const bounce = (k: number, amp: number, t: number) => {
export const ease = (ease: number, t: number) => Math.pow(t, ease);

/**
* HOF impulse generator. Peaks at `t=1/k`
* Impulse generator. Peaks at `t = 1/k`
*
* @param k - impulse width (higher values => shorter impulse)
*/
Expand Down

0 comments on commit 56dce17

Please sign in to comment.