@ceale/util 1.10.0 → 1.11.1

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/dist/cjs/index.js CHANGED
@@ -272,7 +272,11 @@ var quadraticCurve;
272
272
  const oneMinusT = 1 - t;
273
273
  return 2 * oneMinusT * t * p1y + t * t;
274
274
  };
275
- quadraticCurve.solveTForX = (p1, x, iterations = 8) => {
275
+ quadraticCurve.solveTForX = (p1, x, iterations = 15) => {
276
+ if (x <= 0)
277
+ return 0;
278
+ if (x >= 1)
279
+ return 1;
276
280
  let tMin = 0;
277
281
  let tMax = 1;
278
282
  let tGuess;
@@ -287,6 +291,10 @@ var quadraticCurve;
287
291
  }
288
292
  return (tMin + tMax) / 2;
289
293
  };
294
+ quadraticCurve.solveYForX = (p1, x, iterations = 15) => {
295
+ const t = quadraticCurve.solveTForX(p1, x, iterations);
296
+ return quadraticCurve.solveY(p1, t);
297
+ };
290
298
  })(quadraticCurve ||= {});
291
299
  var cubicCurve;
292
300
  ((cubicCurve) => {
@@ -304,7 +312,11 @@ var cubicCurve;
304
312
  const t2 = t * t;
305
313
  return 3 * oneMinusT * oneMinusT * t * p1y + 3 * oneMinusT * t2 * p2y + t2 * t;
306
314
  };
307
- cubicCurve.solveTForX = ([p1, p2], x, iterations = 12) => {
315
+ cubicCurve.solveTForX = ([p1, p2], x, iterations = 20) => {
316
+ if (x <= 0)
317
+ return 0;
318
+ if (x >= 1)
319
+ return 1;
308
320
  let tMin = 0;
309
321
  let tMax = 1;
310
322
  let tGuess;
@@ -319,15 +331,25 @@ var cubicCurve;
319
331
  }
320
332
  return (tMin + tMax) / 2;
321
333
  };
334
+ cubicCurve.solveYForX = ([p1, p2], x, iterations = 20) => {
335
+ const t = cubicCurve.solveTForX([p1, p2], x, iterations);
336
+ return cubicCurve.solveY([p1, p2], t);
337
+ };
322
338
  })(cubicCurve ||= {});
323
339
 
324
340
  class QuadraticBezier {
325
341
  p1;
326
- constructor(p1) {
342
+ accuracy;
343
+ cache = new Map;
344
+ constructor(p1, accuracy = 4) {
327
345
  this.p1 = p1;
346
+ this.accuracy = accuracy;
328
347
  if (this.p1[0] < 0 || this.p1[0] > 1) {
329
348
  throw new BezierError("控制点P1的x坐标必须在[0, 1]之间");
330
349
  }
350
+ if (accuracy !== -1) {
351
+ this.accuracy = 10 ** accuracy;
352
+ }
331
353
  }
332
354
  solveX(t) {
333
355
  return quadraticCurve.solveX(this.p1, t);
@@ -336,23 +358,37 @@ class QuadraticBezier {
336
358
  return quadraticCurve.solveY(this.p1, t);
337
359
  }
338
360
  solveYForX(x) {
339
- const t = quadraticCurve.solveTForX(this.p1, x);
340
- return this.solveY(t);
361
+ if (this.accuracy === -1)
362
+ return quadraticCurve.solveYForX(this.p1, x);
363
+ else {
364
+ const roughX = Math.round(x * this.accuracy);
365
+ return this.cache.get(roughX) ?? (() => {
366
+ const y = quadraticCurve.solveYForX(this.p1, x);
367
+ this.cache.set(roughX, y);
368
+ return y;
369
+ })();
370
+ }
341
371
  }
342
372
  }
343
373
 
344
374
  class CubicBezier {
345
375
  p1;
346
376
  p2;
347
- constructor(p1, p2) {
377
+ accuracy;
378
+ cache = new Map;
379
+ constructor(p1, p2, accuracy = 4) {
348
380
  this.p1 = p1;
349
381
  this.p2 = p2;
382
+ this.accuracy = accuracy;
350
383
  if (this.p1[0] < 0 || this.p1[0] > 1) {
351
384
  throw new BezierError("控制点P1的x坐标必须在[0, 1]之间");
352
385
  }
353
386
  if (this.p2[0] < 0 || this.p2[0] > 1) {
354
387
  throw new BezierError("控制点P2的x坐标必须在[0, 1]之间");
355
388
  }
389
+ if (accuracy !== -1) {
390
+ this.accuracy = 10 ** accuracy;
391
+ }
356
392
  }
357
393
  solveX(t) {
358
394
  return cubicCurve.solveX([this.p1, this.p2], t);
@@ -361,7 +397,15 @@ class CubicBezier {
361
397
  return cubicCurve.solveY([this.p1, this.p2], t);
362
398
  }
363
399
  solveYForX(x) {
364
- const t = cubicCurve.solveTForX([this.p1, this.p2], x);
365
- return this.solveY(t);
400
+ if (this.accuracy === -1)
401
+ return cubicCurve.solveYForX([this.p1, this.p2], x);
402
+ else {
403
+ const roughX = Math.round(x * this.accuracy);
404
+ return this.cache.get(roughX) ?? (() => {
405
+ const y = cubicCurve.solveYForX([this.p1, this.p2], x);
406
+ this.cache.set(roughX, y);
407
+ return y;
408
+ })();
409
+ }
366
410
  }
367
411
  }
package/dist/esm/index.js CHANGED
@@ -226,7 +226,11 @@ var quadraticCurve;
226
226
  const oneMinusT = 1 - t;
227
227
  return 2 * oneMinusT * t * p1y + t * t;
228
228
  };
229
- quadraticCurve.solveTForX = (p1, x, iterations = 8) => {
229
+ quadraticCurve.solveTForX = (p1, x, iterations = 15) => {
230
+ if (x <= 0)
231
+ return 0;
232
+ if (x >= 1)
233
+ return 1;
230
234
  let tMin = 0;
231
235
  let tMax = 1;
232
236
  let tGuess;
@@ -241,6 +245,10 @@ var quadraticCurve;
241
245
  }
242
246
  return (tMin + tMax) / 2;
243
247
  };
248
+ quadraticCurve.solveYForX = (p1, x, iterations = 15) => {
249
+ const t = quadraticCurve.solveTForX(p1, x, iterations);
250
+ return quadraticCurve.solveY(p1, t);
251
+ };
244
252
  })(quadraticCurve ||= {});
245
253
  var cubicCurve;
246
254
  ((cubicCurve) => {
@@ -258,7 +266,11 @@ var cubicCurve;
258
266
  const t2 = t * t;
259
267
  return 3 * oneMinusT * oneMinusT * t * p1y + 3 * oneMinusT * t2 * p2y + t2 * t;
260
268
  };
261
- cubicCurve.solveTForX = ([p1, p2], x, iterations = 12) => {
269
+ cubicCurve.solveTForX = ([p1, p2], x, iterations = 20) => {
270
+ if (x <= 0)
271
+ return 0;
272
+ if (x >= 1)
273
+ return 1;
262
274
  let tMin = 0;
263
275
  let tMax = 1;
264
276
  let tGuess;
@@ -273,15 +285,25 @@ var cubicCurve;
273
285
  }
274
286
  return (tMin + tMax) / 2;
275
287
  };
288
+ cubicCurve.solveYForX = ([p1, p2], x, iterations = 20) => {
289
+ const t = cubicCurve.solveTForX([p1, p2], x, iterations);
290
+ return cubicCurve.solveY([p1, p2], t);
291
+ };
276
292
  })(cubicCurve ||= {});
277
293
 
278
294
  class QuadraticBezier {
279
295
  p1;
280
- constructor(p1) {
296
+ accuracy;
297
+ cache = new Map;
298
+ constructor(p1, accuracy = 4) {
281
299
  this.p1 = p1;
300
+ this.accuracy = accuracy;
282
301
  if (this.p1[0] < 0 || this.p1[0] > 1) {
283
302
  throw new BezierError("控制点P1的x坐标必须在[0, 1]之间");
284
303
  }
304
+ if (accuracy !== -1) {
305
+ this.accuracy = 10 ** accuracy;
306
+ }
285
307
  }
286
308
  solveX(t) {
287
309
  return quadraticCurve.solveX(this.p1, t);
@@ -290,23 +312,37 @@ class QuadraticBezier {
290
312
  return quadraticCurve.solveY(this.p1, t);
291
313
  }
292
314
  solveYForX(x) {
293
- const t = quadraticCurve.solveTForX(this.p1, x);
294
- return this.solveY(t);
315
+ if (this.accuracy === -1)
316
+ return quadraticCurve.solveYForX(this.p1, x);
317
+ else {
318
+ const roughX = Math.round(x * this.accuracy);
319
+ return this.cache.get(roughX) ?? (() => {
320
+ const y = quadraticCurve.solveYForX(this.p1, x);
321
+ this.cache.set(roughX, y);
322
+ return y;
323
+ })();
324
+ }
295
325
  }
296
326
  }
297
327
 
298
328
  class CubicBezier {
299
329
  p1;
300
330
  p2;
301
- constructor(p1, p2) {
331
+ accuracy;
332
+ cache = new Map;
333
+ constructor(p1, p2, accuracy = 4) {
302
334
  this.p1 = p1;
303
335
  this.p2 = p2;
336
+ this.accuracy = accuracy;
304
337
  if (this.p1[0] < 0 || this.p1[0] > 1) {
305
338
  throw new BezierError("控制点P1的x坐标必须在[0, 1]之间");
306
339
  }
307
340
  if (this.p2[0] < 0 || this.p2[0] > 1) {
308
341
  throw new BezierError("控制点P2的x坐标必须在[0, 1]之间");
309
342
  }
343
+ if (accuracy !== -1) {
344
+ this.accuracy = 10 ** accuracy;
345
+ }
310
346
  }
311
347
  solveX(t) {
312
348
  return cubicCurve.solveX([this.p1, this.p2], t);
@@ -315,8 +351,16 @@ class CubicBezier {
315
351
  return cubicCurve.solveY([this.p1, this.p2], t);
316
352
  }
317
353
  solveYForX(x) {
318
- const t = cubicCurve.solveTForX([this.p1, this.p2], x);
319
- return this.solveY(t);
354
+ if (this.accuracy === -1)
355
+ return cubicCurve.solveYForX([this.p1, this.p2], x);
356
+ else {
357
+ const roughX = Math.round(x * this.accuracy);
358
+ return this.cache.get(roughX) ?? (() => {
359
+ const y = cubicCurve.solveYForX([this.p1, this.p2], x);
360
+ this.cache.set(roughX, y);
361
+ return y;
362
+ })();
363
+ }
320
364
  }
321
365
  }
322
366
  export {
@@ -1,61 +1,84 @@
1
1
  type Point = [number, number];
2
2
  export declare namespace quadraticCurve {
3
3
  /**
4
- * [二次] 给定控制点 P1 和 t (时间),计算 x 坐标
4
+ * 给定控制点 P1 和 t (时间),计算 x 坐标
5
5
  * @param p1 控制点1 的坐标
6
6
  * @param t 时间比例 [0, 1]
7
7
  * @returns x 坐标
8
8
  */
9
9
  const solveX: (p1: Point, t: number) => number;
10
10
  /**
11
- * [二次] 给定控制点 P1 和 t (时间),计算 y 坐标
11
+ * 给定控制点 P1 和 t (时间),计算 y 坐标
12
12
  * @param p1 控制点1 坐标
13
13
  * @param t 时间比例 [0, 1]
14
14
  * @returns y 坐标
15
15
  */
16
16
  const solveY: (p1: Point, t: number) => number;
17
17
  /**
18
- * [二次] 给定控制点 P1 和 x (坐标),反向求解 t (时间)
18
+ * 给定控制点 P1 和 x (坐标),求解 t (时间)
19
19
  * 使用二分查找法
20
20
  * @param p1 控制点1 坐标
21
21
  * @param x 目标 x 坐标 [0, 1]
22
+ * @param iterations 可选,二分法求值迭代次数,默认15次
22
23
  * @returns 对应的时间 t
23
24
  */
24
25
  const solveTForX: (p1: Point, x: number, iterations?: number) => number;
26
+ /**
27
+ * 给定控制点 P1 和 x (坐标),求解 y (坐标)
28
+ * 使用二分查找法
29
+ * @param p1 控制点1 坐标
30
+ * @param x 目标 x 坐标 [0, 1]
31
+ * @returns 对应的时间 t
32
+ * @param iterations 可选,二分法求值迭代次数,默认15次
33
+ */
34
+ const solveYForX: (p1: Point, x: number, iterations?: number) => number;
25
35
  }
26
36
  export declare namespace cubicCurve {
27
37
  /**
28
- * [三次] 给定控制点 P1, P2 和 t (时间),计算 x 坐标
38
+ * 给定控制点 P1, P2 和 t (时间),计算 x 坐标
29
39
  * @param \[p1, p2] 控制点1 控制点2 的坐标
30
40
  * @param t 时间比例 [0, 1]
31
41
  * @returns x 坐标
32
42
  */
33
43
  const solveX: ([p1, p2]: [Point, Point], t: number) => number;
34
44
  /**
35
- * [三次] 给定控制点 P1, P2 和 t (时间),计算 y 坐标
45
+ * 给定控制点 P1, P2 和 t (时间),计算 y 坐标
36
46
  * @param \[p1, p2] 控制点1 控制点2 的坐标
37
47
  * @param t 时间比例 [0, 1]
38
48
  * @returns y 坐标
39
49
  */
40
50
  const solveY: ([p1, p2]: [Point, Point], t: number) => number;
41
51
  /**
42
- * [三次] 给定控制点 P1, P2 和 x (坐标),反向求解 t (时间)
52
+ * 给定控制点 P1, P2 和 x (坐标),求解 t (时间)
43
53
  * 使用二分查找法
44
54
  * @param \[p1, p2] 控制点1 控制点2 的坐标
45
55
  * @param x 目标 x 坐标 [0, 1]
46
56
  * @returns 对应的时间 t
57
+ * @param iterations 可选,二分法求值迭代次数,默认20次
47
58
  */
48
59
  const solveTForX: ([p1, p2]: [Point, Point], x: number, iterations?: number) => number;
60
+ /**
61
+ * 给定控制点 P1 和 x (坐标),求解 y (坐标)
62
+ * 使用二分查找法
63
+ * @param p1 控制点1 坐标
64
+ * @param x 目标 x 坐标 [0, 1]
65
+ * @returns 对应的时间 t
66
+ * @param iterations 可选,二分法求值迭代次数,默认20次
67
+ */
68
+ const solveYForX: ([p1, p2]: [Point, Point], x: number, iterations?: number) => number;
49
69
  }
50
70
  /**
51
71
  * 代表一个二次贝塞尔缓动曲线
52
72
  */
53
73
  export declare class QuadraticBezier {
54
74
  private readonly p1;
75
+ private accuracy;
76
+ cache: Map<number, number>;
55
77
  /**
56
78
  * @param p1 控制点 P1
79
+ * @param accuracy 缓存精度(`10^-accuracy`),默认为`4`,`-1`则表示不缓存
57
80
  */
58
- constructor(p1: Point);
81
+ constructor(p1: Point, accuracy?: number);
59
82
  /**
60
83
  * 根据时间 t [0, 1],计算 x 坐标
61
84
  */
@@ -75,11 +98,14 @@ export declare class QuadraticBezier {
75
98
  export declare class CubicBezier {
76
99
  private readonly p1;
77
100
  private readonly p2;
101
+ private accuracy;
102
+ cache: Map<number, number>;
78
103
  /**
79
104
  * @param p1 控制点 P1
80
105
  * @param p2 控制点 P2
106
+ * @param accuracy 缓存精度(`10^-accuracy`),默认为`4`,`-1`则表示不缓存
81
107
  */
82
- constructor(p1: Point, p2: Point);
108
+ constructor(p1: Point, p2: Point, accuracy?: number);
83
109
  /**
84
110
  * 根据时间 t [0, 1],计算 x 坐标
85
111
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ceale/util",
3
3
  "author": "Ceale",
4
- "version": "1.10.0",
4
+ "version": "1.11.1",
5
5
  "module": "index.ts",
6
6
  "type": "module",
7
7
  "main": "dist/esm/index.js",