@thi.ng/ramp 3.1.34 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2024-08-18T14:11:34Z
3
+ - **Last updated**: 2024-09-05T12:23:14Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,21 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [3.3.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/ramp@3.3.0) (2024-09-05)
13
+
14
+ #### 🚀 Features
15
+
16
+ - add easing ramp implementations ([1e23b61](https://github.com/thi-ng/umbrella/commit/1e23b61))
17
+ - add `easing()`
18
+ - add `EASING_N` / `EASING_V`
19
+ - update pkg exports
20
+
21
+ ## [3.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/ramp@3.2.0) (2024-08-28)
22
+
23
+ #### 🚀 Features
24
+
25
+ - add IRamp.removeStopAtIndex() ([05c965f](https://github.com/thi-ng/umbrella/commit/05c965f))
26
+
12
27
  ### [3.1.24](https://github.com/thi-ng/umbrella/tree/@thi.ng/ramp@3.1.24) (2024-06-21)
13
28
 
14
29
  #### ♻️ Refactoring
package/README.md CHANGED
@@ -34,9 +34,15 @@ Extensible keyframe interpolation/tweening of arbitrary, nested types.
34
34
  ![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/ramp/readme.png)
35
35
 
36
36
  This package can perform keyframe interpolation for ramps of numeric values,
37
- n-dimensional vectors and nested objects of the same. It provides linear and
38
- cubic hermite interpolation out of the box, but can be extended by implementing
39
- a simple interface to achieve other interpolation methods.
37
+ n-dimensional vectors and nested objects of the same. It provides several
38
+ interpolation methods out of the box, but can be extended by implementing a
39
+ simple interface to achieve other interpolation methods.
40
+
41
+ Built-in interpolation modes:
42
+
43
+ - [linear](https://docs.thi.ng/umbrella/ramp/functions/linear.html)
44
+ - [cubic hermite](https://docs.thi.ng/umbrella/ramp/functions/hermite.html)
45
+ - [arbitrary easing functions](https://docs.thi.ng/umbrella/ramp/functions/easing.html)
40
46
 
41
47
  ## Status
42
48
 
@@ -70,7 +76,7 @@ For Node.js REPL:
70
76
  const ramp = await import("@thi.ng/ramp");
71
77
  ```
72
78
 
73
- Package sizes (brotli'd, pre-treeshake): ESM: 1.87 KB
79
+ Package sizes (brotli'd, pre-treeshake): ESM: 2.00 KB
74
80
 
75
81
  ## Dependencies
76
82
 
@@ -102,27 +108,30 @@ directory are using this package:
102
108
  ### Numeric
103
109
 
104
110
  ```ts tangle:export/readme.ts
105
- import { linear, hermite } from "@thi.ng/ramp";
111
+ import { linear, hermite, easing } from "@thi.ng/ramp";
112
+
113
+ const stops = [[0.1, 0], [0.5, 1], [0.9, 0]];
106
114
 
107
- const rampL = linear([[0.1, 0], [0.5, 1], [0.9, 0]]);
108
- const rampH = hermite([[0.1, 0], [0.5, 1], [0.9, 0]]);
115
+ const rampL = linear(stops);
116
+ const rampH = hermite(stops);
117
+ const rampE = easing(stops);
109
118
 
110
119
  for(let i = 0; i <= 10; i++) {
111
120
  const t = i / 10;
112
- console.log(t, rampL.at(t).toFixed(2), rampH.at(t).toFixed(2));
121
+ console.log(t, rampL.at(t).toFixed(3), rampH.at(t).toFixed(3), rampE.at(t).toFixed(3));
113
122
  }
114
123
 
115
- // 0 0.00 0.00
116
- // 0.1 0.00 0.00
117
- // 0.2 0.25 0.16
118
- // 0.3 0.50 0.50
119
- // 0.4 0.75 0.84
120
- // 0.5 1.00 1.00
121
- // 0.6 0.75 0.84
122
- // 0.7 0.50 0.50
123
- // 0.8 0.25 0.16
124
- // 0.9 0.00 0.00
125
- // 1 0.00 0.00
124
+ // 0 0.000 0.000 0.000
125
+ // 0.1 0.000 0.000 0.000
126
+ // 0.2 0.250 0.156 0.016
127
+ // 0.3 0.500 0.500 0.500
128
+ // 0.4 0.750 0.844 0.984
129
+ // 0.5 1.000 1.000 1.000
130
+ // 0.6 0.750 0.844 0.984
131
+ // 0.7 0.500 0.500 0.500
132
+ // 0.8 0.250 0.156 0.016
133
+ // 0.9 0.000 0.000 0.000
134
+ // 1 0.000 0.000 0.000
126
135
  ```
127
136
 
128
137
  ### nD vectors
package/api.d.ts CHANGED
@@ -48,6 +48,7 @@ export interface IRamp<T> extends IReadonlyRamp<T> {
48
48
  stops: Frame<T>[];
49
49
  setStopAt(t: number, y: T, eps?: number): boolean;
50
50
  removeStopAt(t: number, eps?: number): boolean;
51
+ removeStopAtIndex(i: number): boolean;
51
52
  closestIndex(t: number, eps?: number): number;
52
53
  clampedIndexTime(i: number, t: number, eps?: number): number;
53
54
  }
package/easing.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import type { FnN } from "@thi.ng/api";
2
+ import type { Vec } from "@thi.ng/vectors";
3
+ import type { Frame, RampImpl, RampOpts, VecAPI } from "./api.js";
4
+ import { Ramp } from "./ramp.js";
5
+ /**
6
+ * Syntax sugar for creating a numeric {@link Ramp} using the {@link EASING_N}
7
+ * ramp interpolation impl (supporting arbitrary easing functions), given
8
+ * `stops` (aka keyframes, minimum 2 required) and options.
9
+ *
10
+ * @remarks
11
+ * Easing functions remap time values in the [0,1] range. By default uses
12
+ * [`easeInOut5()`](https://docs.thi.ng/umbrella/math/functions/easeInOut5.html).
13
+ *
14
+ * For vector-valued ramps, use {@link ramp} with {@link EASING_V}.
15
+ *
16
+ * @param stops
17
+ * @param opts
18
+ */
19
+ export declare const easing: (stops: Frame<number>[], opts?: Partial<RampOpts & {
20
+ easing: FnN;
21
+ }>) => Ramp<number>;
22
+ /**
23
+ * Higher-order ramp interpolation implementation supporting arbitrary `easing`
24
+ * function to control keyframe interpolation.
25
+ *
26
+ * @remarks
27
+ * Easing functions remap time values in the [0,1] range. By default uses
28
+ * [`easeInOut5()`](https://docs.thi.ng/umbrella/math/functions/easeInOut5.html).
29
+ *
30
+ * @param easing
31
+ */
32
+ export declare const EASING_N: (easing?: FnN) => RampImpl<number>;
33
+ /**
34
+ * Vector version of {@link EASING_N}. Use with any of the supplied vector APIs:
35
+ * {@link VEC} (arbitrary size), {@link VEC2}, {@link VEC3} or {@link VEC4}.
36
+ *
37
+ * @remarks
38
+ * Easing functions remap time values in the [0,1] range. By default uses
39
+ * [`easeInOut5()`](https://docs.thi.ng/umbrella/math/functions/easeInOut5.html).
40
+ *
41
+ * @param vec
42
+ * @param easing
43
+ */
44
+ export declare const EASING_V: <T extends Vec>(vec: VecAPI, easing?: FnN) => RampImpl<T>;
45
+ //# sourceMappingURL=easing.d.ts.map
package/easing.js ADDED
@@ -0,0 +1,30 @@
1
+ import { easeInOut5 } from "@thi.ng/math/easing";
2
+ import { norm } from "@thi.ng/math/fit";
3
+ import { mix } from "@thi.ng/math/mix";
4
+ import { Ramp } from "./ramp.js";
5
+ const easing = (stops, opts) => new Ramp(EASING_N(opts?.easing), stops, opts);
6
+ const EASING_N = (easing2 = easeInOut5) => {
7
+ return {
8
+ min: (acc, x) => Math.min(acc ?? Infinity, x),
9
+ max: (acc, x) => Math.max(acc ?? -Infinity, x),
10
+ at: (stops, i, t) => {
11
+ const a = stops[i];
12
+ const b = stops[i + 1];
13
+ return mix(a[1], b[1], easing2(norm(t, a[0], b[0])));
14
+ }
15
+ };
16
+ };
17
+ const EASING_V = (vec, easing2 = easeInOut5) => ({
18
+ min: (acc, x) => vec.min(acc, acc || vec.vecOf(Infinity), x),
19
+ max: (acc, x) => vec.max(acc, acc || vec.vecOf(-Infinity), x),
20
+ at: (stops, i, t) => {
21
+ const a = stops[i];
22
+ const b = stops[i + 1];
23
+ return vec.mixN([], a[1], b[1], easing2(norm(t, a[0], b[0])));
24
+ }
25
+ });
26
+ export {
27
+ EASING_N,
28
+ EASING_V,
29
+ easing
30
+ };
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./api.js";
2
2
  export * from "./domain.js";
3
+ export * from "./easing.js";
3
4
  export * from "./group.js";
4
5
  export * from "./hermite.js";
5
6
  export * from "./linear.js";
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./api.js";
2
2
  export * from "./domain.js";
3
+ export * from "./easing.js";
3
4
  export * from "./group.js";
4
5
  export * from "./hermite.js";
5
6
  export * from "./linear.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/ramp",
3
- "version": "3.1.34",
3
+ "version": "3.3.0",
4
4
  "description": "Extensible keyframe interpolation/tweening of arbitrary, nested types",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -40,9 +40,9 @@
40
40
  "@thi.ng/arrays": "^2.10.0",
41
41
  "@thi.ng/compare": "^2.4.1",
42
42
  "@thi.ng/errors": "^2.5.15",
43
- "@thi.ng/math": "^5.11.8",
44
- "@thi.ng/transducers": "^9.2.0",
45
- "@thi.ng/vectors": "^7.11.10"
43
+ "@thi.ng/math": "^5.11.9",
44
+ "@thi.ng/transducers": "^9.2.2",
45
+ "@thi.ng/vectors": "^7.12.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@microsoft/api-extractor": "^7.47.5",
@@ -95,6 +95,9 @@
95
95
  "./domain": {
96
96
  "default": "./domain.js"
97
97
  },
98
+ "./easing": {
99
+ "default": "./easing.js"
100
+ },
98
101
  "./group": {
99
102
  "default": "./group.js"
100
103
  },
@@ -117,5 +120,5 @@
117
120
  "thi.ng": {
118
121
  "year": 2019
119
122
  },
120
- "gitHead": "bfbc227cf5ca2d3c2984b3d4713eebd6225cbd54\n"
123
+ "gitHead": "9f71f7f82fed2a980078a96bdafd2e706f526c75\n"
121
124
  }
package/ramp.d.ts CHANGED
@@ -31,6 +31,7 @@ export declare class Ramp<T> implements ICopy<IRamp<T>>, IEmpty<IRamp<T>>, IRamp
31
31
  timeBounds(): [number, number];
32
32
  setStopAt(t: number, val: T, eps?: number): boolean;
33
33
  removeStopAt(t: number, eps?: number): boolean;
34
+ removeStopAtIndex(i: number): boolean;
34
35
  closestIndex(t: number, eps?: number): number;
35
36
  clampedIndexTime(i: number, t: number, eps?: number): number;
36
37
  sort(): void;
package/ramp.js CHANGED
@@ -78,14 +78,13 @@ class Ramp {
78
78
  return false;
79
79
  }
80
80
  removeStopAt(t, eps = 0.01) {
81
- if (this.stops.length > 2) {
82
- const i = this.closestIndex(t, eps);
83
- if (i !== -1) {
84
- this.stops.splice(i, 1);
85
- return true;
86
- }
87
- }
88
- return false;
81
+ return this.stops.length > 2 ? this.removeStopAtIndex(this.closestIndex(t, eps)) : false;
82
+ }
83
+ removeStopAtIndex(i) {
84
+ const stops = this.stops;
85
+ if (i < 0 || i >= stops.length || stops.length <= 2) return false;
86
+ stops.splice(i, 1);
87
+ return true;
89
88
  }
90
89
  closestIndex(t, eps = 0.01) {
91
90
  const stops = this.stops;