toosoon-utils 4.2.3 → 4.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/README.md +499 -575
- package/lib/colors.d.ts +147 -66
- package/lib/colors.js +149 -63
- package/lib/constants.js +1 -1
- package/lib/dom.d.ts +1 -1
- package/lib/dom.js +1 -1
- package/lib/extras/colors/Color.d.ts +406 -0
- package/lib/extras/colors/Color.js +546 -0
- package/lib/extras/colors/ColorPalette.d.ts +105 -0
- package/lib/extras/colors/ColorPalette.js +124 -0
- package/lib/extras/colors/ColorScale.d.ts +257 -0
- package/lib/extras/colors/ColorScale.js +347 -0
- package/lib/extras/colors/_ColorScale.d.ts +62 -0
- package/lib/extras/colors/_ColorScale.js +156 -0
- package/lib/extras/colors/index.d.ts +3 -0
- package/lib/extras/colors/index.js +3 -0
- package/lib/extras/frame-rate/FrameRate.d.ts +1 -1
- package/lib/extras/frame-rate/FrameRate.js +2 -2
- package/lib/extras/geometry/Vector.d.ts +1 -1
- package/lib/extras/geometry/Vector2.d.ts +17 -11
- package/lib/extras/geometry/Vector2.js +29 -23
- package/lib/extras/geometry/Vector3.d.ts +5 -5
- package/lib/extras/geometry/Vector3.js +10 -10
- package/lib/extras/paths/Path.d.ts +3 -3
- package/lib/extras/paths/Path.js +10 -10
- package/lib/extras/paths/PathContext.d.ts +5 -10
- package/lib/extras/paths/PathContext.js +70 -99
- package/lib/extras/paths/PathSVG.d.ts +31 -25
- package/lib/extras/paths/PathSVG.js +36 -39
- package/lib/extras/paths/index.d.ts +1 -1
- package/lib/geometry.js +1 -1
- package/lib/maths.d.ts +19 -13
- package/lib/maths.js +23 -17
- package/lib/prng.d.ts +4 -4
- package/lib/prng.js +4 -4
- package/lib/random.d.ts +4 -4
- package/lib/random.js +4 -4
- package/lib/strings.d.ts +14 -8
- package/lib/strings.js +14 -8
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types.d.ts +15 -8
- package/package.json +14 -14
|
@@ -18,6 +18,10 @@ export default class Vector2 {
|
|
|
18
18
|
* Y-axis value of this vector
|
|
19
19
|
*/
|
|
20
20
|
y;
|
|
21
|
+
*[Symbol.iterator]() {
|
|
22
|
+
yield this.x;
|
|
23
|
+
yield this.y;
|
|
24
|
+
}
|
|
21
25
|
/**
|
|
22
26
|
* @param {number} [x=0] X-axis value
|
|
23
27
|
* @param {number} [y=0] Y-axis value
|
|
@@ -41,7 +45,7 @@ export default class Vector2 {
|
|
|
41
45
|
/**
|
|
42
46
|
* Set a given scalar value to all values of this vector
|
|
43
47
|
*
|
|
44
|
-
* @param {number} scalar Value to set for all
|
|
48
|
+
* @param {number} scalar Value to set for all values
|
|
45
49
|
* @returns {this}
|
|
46
50
|
*/
|
|
47
51
|
setScalar(scalar) {
|
|
@@ -306,13 +310,13 @@ export default class Vector2 {
|
|
|
306
310
|
return this.set(...Vector2.rotate(this, center, angle));
|
|
307
311
|
}
|
|
308
312
|
/**
|
|
309
|
-
*
|
|
313
|
+
* Linearly interpolate this vector values towards a given vector values
|
|
310
314
|
*
|
|
311
|
-
* @param {Vector2|Point2} vector Vector to interpolate values towards
|
|
312
315
|
* @param {number} t Normalized time value to interpolate
|
|
316
|
+
* @param {Vector2|Point2} vector Vector to interpolate values towards
|
|
313
317
|
* @returns {this}
|
|
314
318
|
*/
|
|
315
|
-
lerp([x, y]
|
|
319
|
+
lerp(t, [x, y]) {
|
|
316
320
|
this.x += (x - this.x) * t;
|
|
317
321
|
this.y += (y - this.y) * t;
|
|
318
322
|
return this;
|
|
@@ -467,7 +471,7 @@ export default class Vector2 {
|
|
|
467
471
|
* Set this vector values from a given array
|
|
468
472
|
*
|
|
469
473
|
* @param {number[]} values Values to set
|
|
470
|
-
* @returns
|
|
474
|
+
* @returns {this}
|
|
471
475
|
*/
|
|
472
476
|
fromArray([x, y]) {
|
|
473
477
|
this.x = x;
|
|
@@ -503,6 +507,24 @@ export default class Vector2 {
|
|
|
503
507
|
clone() {
|
|
504
508
|
return new Vector2(this.x, this.y);
|
|
505
509
|
}
|
|
510
|
+
/**
|
|
511
|
+
* X-axis value of this vector
|
|
512
|
+
*/
|
|
513
|
+
set width(width) {
|
|
514
|
+
this.x = width;
|
|
515
|
+
}
|
|
516
|
+
get width() {
|
|
517
|
+
return this.x;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Y-axis value of this vector
|
|
521
|
+
*/
|
|
522
|
+
set height(height) {
|
|
523
|
+
this.y = height;
|
|
524
|
+
}
|
|
525
|
+
get height() {
|
|
526
|
+
return this.y;
|
|
527
|
+
}
|
|
506
528
|
/**
|
|
507
529
|
* Add two vectors
|
|
508
530
|
*
|
|
@@ -569,7 +591,7 @@ export default class Vector2 {
|
|
|
569
591
|
return [x, y];
|
|
570
592
|
}
|
|
571
593
|
/**
|
|
572
|
-
*
|
|
594
|
+
* Linearly interpolate a point between two vectors
|
|
573
595
|
*
|
|
574
596
|
* @param {number} t Normalized time value to interpolate
|
|
575
597
|
* @param {Vector2|Point2} min Minimum boundaries
|
|
@@ -639,7 +661,7 @@ export default class Vector2 {
|
|
|
639
661
|
* @returns {number} Computed Euclidean distance
|
|
640
662
|
*/
|
|
641
663
|
static distance(vector1, vector2) {
|
|
642
|
-
return Math.sqrt(
|
|
664
|
+
return Math.sqrt(this.squaredDistance(vector1, vector2));
|
|
643
665
|
}
|
|
644
666
|
/**
|
|
645
667
|
* Calculate the squared distance between two vectors
|
|
@@ -702,20 +724,4 @@ export default class Vector2 {
|
|
|
702
724
|
const y = radius * Math.sin(angle);
|
|
703
725
|
return [x, y];
|
|
704
726
|
}
|
|
705
|
-
set width(width) {
|
|
706
|
-
this.x = width;
|
|
707
|
-
}
|
|
708
|
-
get width() {
|
|
709
|
-
return this.x;
|
|
710
|
-
}
|
|
711
|
-
set height(height) {
|
|
712
|
-
this.y = height;
|
|
713
|
-
}
|
|
714
|
-
get height() {
|
|
715
|
-
return this.y;
|
|
716
|
-
}
|
|
717
|
-
*[Symbol.iterator]() {
|
|
718
|
-
yield this.x;
|
|
719
|
-
yield this.y;
|
|
720
|
-
}
|
|
721
727
|
}
|
|
@@ -23,6 +23,7 @@ export default class Vector3 implements Vector<Vec3> {
|
|
|
23
23
|
* Z-axis value of this vector
|
|
24
24
|
*/
|
|
25
25
|
z: number;
|
|
26
|
+
[Symbol.iterator](): Iterator<number>;
|
|
26
27
|
/**
|
|
27
28
|
* @param {number} [x=0] X-axis value
|
|
28
29
|
* @param {number} [y=0] Y-axis value
|
|
@@ -198,13 +199,13 @@ export default class Vector3 implements Vector<Vec3> {
|
|
|
198
199
|
*/
|
|
199
200
|
negate(): this;
|
|
200
201
|
/**
|
|
201
|
-
*
|
|
202
|
+
* Linearly interpolate this vector values towards a given vector values
|
|
202
203
|
*
|
|
203
|
-
* @param {Vector3|Point3} vector Vector to interpolate values towards
|
|
204
204
|
* @param {number} t Normalized time value to interpolate
|
|
205
|
+
* @param {Vector3|Point3} vector Vector to interpolate values towards
|
|
205
206
|
* @returns {this}
|
|
206
207
|
*/
|
|
207
|
-
lerp([x, y, z]: Vec3
|
|
208
|
+
lerp(t: number, [x, y, z]: Vec3): this;
|
|
208
209
|
/**
|
|
209
210
|
* Convert this vector to a unit vector
|
|
210
211
|
*
|
|
@@ -384,7 +385,7 @@ export default class Vector3 implements Vector<Vec3> {
|
|
|
384
385
|
*/
|
|
385
386
|
static divide([x1, y1, z1]: Vec3, [x2, y2, z2]: Vec3): Point3;
|
|
386
387
|
/**
|
|
387
|
-
*
|
|
388
|
+
* Linearly interpolate a point between two vectors
|
|
388
389
|
*
|
|
389
390
|
* @param {number} t Normalized time value to interpolate
|
|
390
391
|
* @param {Vector3|Point3} min Minimum boundaries
|
|
@@ -488,6 +489,5 @@ export default class Vector3 implements Vector<Vec3> {
|
|
|
488
489
|
* @returns {Point3}
|
|
489
490
|
*/
|
|
490
491
|
static fromCylindricalCoords(theta: number, y: number, radius?: number): Point3;
|
|
491
|
-
[Symbol.iterator](): Iterator<number>;
|
|
492
492
|
}
|
|
493
493
|
export {};
|
|
@@ -22,6 +22,11 @@ export default class Vector3 {
|
|
|
22
22
|
* Z-axis value of this vector
|
|
23
23
|
*/
|
|
24
24
|
z;
|
|
25
|
+
*[Symbol.iterator]() {
|
|
26
|
+
yield this.x;
|
|
27
|
+
yield this.y;
|
|
28
|
+
yield this.z;
|
|
29
|
+
}
|
|
25
30
|
/**
|
|
26
31
|
* @param {number} [x=0] X-axis value
|
|
27
32
|
* @param {number} [y=0] Y-axis value
|
|
@@ -339,13 +344,13 @@ export default class Vector3 {
|
|
|
339
344
|
return this;
|
|
340
345
|
}
|
|
341
346
|
/**
|
|
342
|
-
*
|
|
347
|
+
* Linearly interpolate this vector values towards a given vector values
|
|
343
348
|
*
|
|
344
|
-
* @param {Vector3|Point3} vector Vector to interpolate values towards
|
|
345
349
|
* @param {number} t Normalized time value to interpolate
|
|
350
|
+
* @param {Vector3|Point3} vector Vector to interpolate values towards
|
|
346
351
|
* @returns {this}
|
|
347
352
|
*/
|
|
348
|
-
lerp([x, y, z]
|
|
353
|
+
lerp(t, [x, y, z]) {
|
|
349
354
|
this.x += (x - this.x) * t;
|
|
350
355
|
this.y += (y - this.y) * t;
|
|
351
356
|
this.z += (z - this.z) * t;
|
|
@@ -618,7 +623,7 @@ export default class Vector3 {
|
|
|
618
623
|
return [x, y, z];
|
|
619
624
|
}
|
|
620
625
|
/**
|
|
621
|
-
*
|
|
626
|
+
* Linearly interpolate a point between two vectors
|
|
622
627
|
*
|
|
623
628
|
* @param {number} t Normalized time value to interpolate
|
|
624
629
|
* @param {Vector3|Point3} min Minimum boundaries
|
|
@@ -691,7 +696,7 @@ export default class Vector3 {
|
|
|
691
696
|
* @returns {number} Computed Euclidean distance
|
|
692
697
|
*/
|
|
693
698
|
static distance(vector1, vector2) {
|
|
694
|
-
return Math.sqrt(
|
|
699
|
+
return Math.sqrt(this.squaredDistance(vector1, vector2));
|
|
695
700
|
}
|
|
696
701
|
/**
|
|
697
702
|
* Calculate the squared distance between two vectors
|
|
@@ -770,9 +775,4 @@ export default class Vector3 {
|
|
|
770
775
|
const z = radius * Math.cos(theta);
|
|
771
776
|
return [x, y, z];
|
|
772
777
|
}
|
|
773
|
-
*[Symbol.iterator]() {
|
|
774
|
-
yield this.x;
|
|
775
|
-
yield this.y;
|
|
776
|
-
yield this.z;
|
|
777
|
-
}
|
|
778
778
|
}
|
|
@@ -7,13 +7,13 @@ import { type Vector, Vector2, Vector3 } from '../geometry';
|
|
|
7
7
|
* @class Path
|
|
8
8
|
* @extends Curve
|
|
9
9
|
*/
|
|
10
|
-
export default class Path<V extends Vector = Vector2 | Vector3,
|
|
10
|
+
export default class Path<V extends Vector = Vector2 | Vector3, C extends Curve<V> = Curve<V>> extends Curve<V> {
|
|
11
11
|
readonly isPath = true;
|
|
12
12
|
readonly type: string;
|
|
13
13
|
/**
|
|
14
14
|
* Array of curves composing this path
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
curves: C[];
|
|
17
17
|
/**
|
|
18
18
|
* Array of points composing this path
|
|
19
19
|
*/
|
|
@@ -30,7 +30,7 @@ export default class Path<V extends Vector = Vector2 | Vector3, S extends Curve<
|
|
|
30
30
|
*
|
|
31
31
|
* @param {Curve} curve Curve to add
|
|
32
32
|
*/
|
|
33
|
-
add(curve:
|
|
33
|
+
add(curve: C): void;
|
|
34
34
|
/**
|
|
35
35
|
* Interpolate a point on this path
|
|
36
36
|
*
|
package/lib/extras/paths/Path.js
CHANGED
|
@@ -12,7 +12,7 @@ export default class Path extends Curve {
|
|
|
12
12
|
/**
|
|
13
13
|
* Array of curves composing this path
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
curves = [];
|
|
16
16
|
/**
|
|
17
17
|
* Array of points composing this path
|
|
18
18
|
*/
|
|
@@ -31,7 +31,7 @@ export default class Path extends Curve {
|
|
|
31
31
|
* @param {Curve} curve Curve to add
|
|
32
32
|
*/
|
|
33
33
|
add(curve) {
|
|
34
|
-
this.
|
|
34
|
+
this.curves.push(curve);
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Interpolate a point on this path
|
|
@@ -46,7 +46,7 @@ export default class Path extends Curve {
|
|
|
46
46
|
while (i < curveLengths.length) {
|
|
47
47
|
if (curveLengths[i] >= d) {
|
|
48
48
|
const delta = curveLengths[i] - d;
|
|
49
|
-
const curve = this.
|
|
49
|
+
const curve = this.curves[i];
|
|
50
50
|
const segmentLength = curve.getLength();
|
|
51
51
|
const u = segmentLength === 0 ? 0 : 1 - delta / segmentLength;
|
|
52
52
|
return curve.getPointAt(u);
|
|
@@ -54,7 +54,7 @@ export default class Path extends Curve {
|
|
|
54
54
|
i++;
|
|
55
55
|
}
|
|
56
56
|
console.warn(`Path.getPoint()`, `No point found in curve.`, this);
|
|
57
|
-
return this.
|
|
57
|
+
return this.curves[0].getPoint(0);
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
60
60
|
* Compute the curve shape into an array of points
|
|
@@ -65,8 +65,8 @@ export default class Path extends Curve {
|
|
|
65
65
|
getPoints(divisions = 40) {
|
|
66
66
|
const points = [];
|
|
67
67
|
let lastPoint = null;
|
|
68
|
-
for (let i = 0; i < this.
|
|
69
|
-
const curve = this.
|
|
68
|
+
for (let i = 0; i < this.curves.length; i++) {
|
|
69
|
+
const curve = this.curves[i];
|
|
70
70
|
let resolution = divisions;
|
|
71
71
|
if (curve instanceof LineCurve || curve instanceof LineCurve3) {
|
|
72
72
|
resolution = 1;
|
|
@@ -80,7 +80,7 @@ export default class Path extends Curve {
|
|
|
80
80
|
else if (curve instanceof EllipseCurve) {
|
|
81
81
|
resolution *= 2;
|
|
82
82
|
}
|
|
83
|
-
const pts = this.
|
|
83
|
+
const pts = this.curves[i].getPoints(resolution);
|
|
84
84
|
for (let j = 0; j < pts.length; j++) {
|
|
85
85
|
const point = pts[j];
|
|
86
86
|
if (point?.equals(lastPoint))
|
|
@@ -127,13 +127,13 @@ export default class Path extends Curve {
|
|
|
127
127
|
* @returns {number[]}
|
|
128
128
|
*/
|
|
129
129
|
getCurveLengths() {
|
|
130
|
-
if (this._cacheArcLengths.length === this.
|
|
130
|
+
if (this._cacheArcLengths.length === this.curves.length) {
|
|
131
131
|
return this._cacheArcLengths;
|
|
132
132
|
}
|
|
133
133
|
const lengths = [];
|
|
134
134
|
let sums = 0;
|
|
135
|
-
for (let i = 0, j = this.
|
|
136
|
-
sums += this.
|
|
135
|
+
for (let i = 0, j = this.curves.length; i < j; i++) {
|
|
136
|
+
sums += this.curves[i].getLength();
|
|
137
137
|
lengths.push(sums);
|
|
138
138
|
}
|
|
139
139
|
this._cacheArcLengths = lengths;
|
|
@@ -12,7 +12,6 @@ import Path from './Path';
|
|
|
12
12
|
export default class PathContext extends Path<Vector2> implements CanvasRenderingContext2D {
|
|
13
13
|
protected _currentPosition: Vector2;
|
|
14
14
|
protected _currentTransform: DOMMatrix;
|
|
15
|
-
protected _positionTransform: DOMMatrix;
|
|
16
15
|
private _transformStack;
|
|
17
16
|
/**
|
|
18
17
|
* Create a path from a given list of points
|
|
@@ -134,7 +133,7 @@ export default class PathContext extends Path<Vector2> implements CanvasRenderin
|
|
|
134
133
|
arc(cx: number, cy: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): this;
|
|
135
134
|
/**
|
|
136
135
|
* Draw an Arc curve from the current position, tangential to the 2 segments created by both control points
|
|
137
|
-
* Add an instance of {@link
|
|
136
|
+
* Add an instance of {@link EllipseCurve} to this path
|
|
138
137
|
*
|
|
139
138
|
* @param {number} x1 X-axis coordinate of the first control point
|
|
140
139
|
* @param {number} y1 Y-axis coordinate of the first control point
|
|
@@ -180,22 +179,18 @@ export default class PathContext extends Path<Vector2> implements CanvasRenderin
|
|
|
180
179
|
reset(): void;
|
|
181
180
|
protected _hasCurrentPosition(): boolean;
|
|
182
181
|
protected _setCurrentPosition(x: number, y: number): this;
|
|
183
|
-
protected _transformPoint(point: Point2
|
|
184
|
-
protected _transformPoints(points: Point2[]
|
|
185
|
-
protected _transformVector(vector: Point2
|
|
186
|
-
protected _transformEllipse(cx: number, cy: number, rx: number, ry: number, rotation: number
|
|
187
|
-
protected _inversePoint(point: Point2, matrix?: DOMMatrix): Point2;
|
|
182
|
+
protected _transformPoint(point: Point2): Point2;
|
|
183
|
+
protected _transformPoints(points: Point2[]): Point2[];
|
|
184
|
+
protected _transformVector(vector: Point2): Point2;
|
|
185
|
+
protected _transformEllipse(cx: number, cy: number, rx: number, ry: number, rotation: number): [number, number, number, number, number];
|
|
188
186
|
protected get _translateX(): number;
|
|
189
187
|
protected get _translateY(): number;
|
|
190
188
|
protected get _scaleX(): number;
|
|
191
189
|
protected get _scaleY(): number;
|
|
192
190
|
protected get _rotation(): number;
|
|
193
|
-
protected get _skewX(): number;
|
|
194
|
-
protected get _skewY(): number;
|
|
195
191
|
protected get _isTranslated(): boolean;
|
|
196
192
|
protected get _isScaled(): boolean;
|
|
197
193
|
protected get _isRotated(): boolean;
|
|
198
|
-
protected get _isSkewed(): boolean;
|
|
199
194
|
protected get _isUniform(): boolean;
|
|
200
195
|
protected get _isIdentity(): boolean;
|
|
201
196
|
canvas: CanvasRenderingContext2D['canvas'];
|
|
@@ -14,7 +14,6 @@ import Path from './Path';
|
|
|
14
14
|
export default class PathContext extends Path {
|
|
15
15
|
_currentPosition = new Vector2(NaN, NaN);
|
|
16
16
|
_currentTransform = new DOMMatrix();
|
|
17
|
-
_positionTransform = new DOMMatrix();
|
|
18
17
|
_transformStack = [];
|
|
19
18
|
/**
|
|
20
19
|
* Create a path from a given list of points
|
|
@@ -45,8 +44,8 @@ export default class PathContext extends Path {
|
|
|
45
44
|
* @return {this}
|
|
46
45
|
*/
|
|
47
46
|
closePath() {
|
|
48
|
-
const startPoint = this.
|
|
49
|
-
const endPoint = this.
|
|
47
|
+
const startPoint = this.curves[0]?.getPoint(0);
|
|
48
|
+
const endPoint = this.curves[this.curves.length - 1]?.getPoint(1);
|
|
50
49
|
if (!startPoint.equals(endPoint)) {
|
|
51
50
|
const curve = new LineCurve(endPoint.x, endPoint.y, startPoint.x, startPoint.y);
|
|
52
51
|
this.add(curve);
|
|
@@ -61,8 +60,8 @@ export default class PathContext extends Path {
|
|
|
61
60
|
* @return {this}
|
|
62
61
|
*/
|
|
63
62
|
moveTo(x, y) {
|
|
64
|
-
|
|
65
|
-
this._setCurrentPosition(
|
|
63
|
+
[x, y] = this._transformPoint([x, y]);
|
|
64
|
+
this._setCurrentPosition(x, y);
|
|
66
65
|
return this;
|
|
67
66
|
}
|
|
68
67
|
/**
|
|
@@ -74,12 +73,12 @@ export default class PathContext extends Path {
|
|
|
74
73
|
* @return {this}
|
|
75
74
|
*/
|
|
76
75
|
lineTo(x, y) {
|
|
77
|
-
|
|
76
|
+
[x, y] = this._transformPoint([x, y]);
|
|
78
77
|
if (!this._hasCurrentPosition())
|
|
79
|
-
return this._setCurrentPosition(
|
|
80
|
-
const curve = new LineCurve(this._currentPosition.x, this._currentPosition.y,
|
|
78
|
+
return this._setCurrentPosition(x, y);
|
|
79
|
+
const curve = new LineCurve(this._currentPosition.x, this._currentPosition.y, x, y);
|
|
81
80
|
this.add(curve);
|
|
82
|
-
this._setCurrentPosition(
|
|
81
|
+
this._setCurrentPosition(x, y);
|
|
83
82
|
return this;
|
|
84
83
|
}
|
|
85
84
|
/**
|
|
@@ -90,12 +89,12 @@ export default class PathContext extends Path {
|
|
|
90
89
|
* @returns {this}
|
|
91
90
|
*/
|
|
92
91
|
polylineTo(points) {
|
|
93
|
-
|
|
92
|
+
points = this._transformPoints(points);
|
|
94
93
|
if (!this._hasCurrentPosition())
|
|
95
|
-
this._setCurrentPosition(...
|
|
96
|
-
const curve = new PolylineCurve([this._currentPosition.toArray()].concat(
|
|
94
|
+
this._setCurrentPosition(...points[0]);
|
|
95
|
+
const curve = new PolylineCurve([this._currentPosition.toArray()].concat(points));
|
|
97
96
|
this.add(curve);
|
|
98
|
-
this._setCurrentPosition(...
|
|
97
|
+
this._setCurrentPosition(...points[points.length - 1]);
|
|
99
98
|
return this;
|
|
100
99
|
}
|
|
101
100
|
/**
|
|
@@ -109,13 +108,13 @@ export default class PathContext extends Path {
|
|
|
109
108
|
* @return {this}
|
|
110
109
|
*/
|
|
111
110
|
quadraticCurveTo(cpx, cpy, x2, y2) {
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
[cpx, cpy] = this._transformPoint([cpx, cpy]);
|
|
112
|
+
[x2, y2] = this._transformPoint([x2, y2]);
|
|
114
113
|
if (!this._hasCurrentPosition())
|
|
115
|
-
this._setCurrentPosition(
|
|
116
|
-
const curve = new QuadraticBezierCurve(this._currentPosition.x, this._currentPosition.y,
|
|
114
|
+
this._setCurrentPosition(cpx, cpy);
|
|
115
|
+
const curve = new QuadraticBezierCurve(this._currentPosition.x, this._currentPosition.y, cpx, cpy, x2, y2);
|
|
117
116
|
this.add(curve);
|
|
118
|
-
this._setCurrentPosition(
|
|
117
|
+
this._setCurrentPosition(x2, y2);
|
|
119
118
|
return this;
|
|
120
119
|
}
|
|
121
120
|
/**
|
|
@@ -131,14 +130,14 @@ export default class PathContext extends Path {
|
|
|
131
130
|
* @return {this}
|
|
132
131
|
*/
|
|
133
132
|
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x2, y2) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
133
|
+
[cp1x, cp1y] = this._transformPoint([cp1x, cp1y]);
|
|
134
|
+
[cp2x, cp2y] = this._transformPoint([cp2x, cp2y]);
|
|
135
|
+
[x2, y2] = this._transformPoint([x2, y2]);
|
|
137
136
|
if (!this._hasCurrentPosition())
|
|
138
|
-
this._setCurrentPosition(
|
|
139
|
-
const curve = new CubicBezierCurve(this._currentPosition.x, this._currentPosition.y,
|
|
137
|
+
this._setCurrentPosition(cp1x, cp1y);
|
|
138
|
+
const curve = new CubicBezierCurve(this._currentPosition.x, this._currentPosition.y, cp1x, cp1y, cp2x, cp2y, x2, y2);
|
|
140
139
|
this.add(curve);
|
|
141
|
-
this._setCurrentPosition(
|
|
140
|
+
this._setCurrentPosition(x2, y2);
|
|
142
141
|
return this;
|
|
143
142
|
}
|
|
144
143
|
/**
|
|
@@ -154,14 +153,14 @@ export default class PathContext extends Path {
|
|
|
154
153
|
* @return {this}
|
|
155
154
|
*/
|
|
156
155
|
catmullRomCurveTo(cp1x, cp1y, cp2x, cp2y, x2, y2) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
[cp1x, cp1y] = this._transformPoint([cp1x, cp1y]);
|
|
157
|
+
[cp2x, cp2y] = this._transformPoint([cp2x, cp2y]);
|
|
158
|
+
[x2, y2] = this._transformPoint([x2, y2]);
|
|
160
159
|
if (!this._hasCurrentPosition())
|
|
161
|
-
this._setCurrentPosition(
|
|
162
|
-
const curve = new CatmullRomCurve(this._currentPosition.x, this._currentPosition.y,
|
|
160
|
+
this._setCurrentPosition(cp1x, cp1y);
|
|
161
|
+
const curve = new CatmullRomCurve(this._currentPosition.x, this._currentPosition.y, cp1x, cp1y, cp2x, cp2y, x2, y2);
|
|
163
162
|
this.add(curve);
|
|
164
|
-
this._setCurrentPosition(
|
|
163
|
+
this._setCurrentPosition(x2, y2);
|
|
165
164
|
return this;
|
|
166
165
|
}
|
|
167
166
|
/**
|
|
@@ -172,12 +171,12 @@ export default class PathContext extends Path {
|
|
|
172
171
|
* @return {this}
|
|
173
172
|
*/
|
|
174
173
|
splineTo(points) {
|
|
175
|
-
|
|
174
|
+
points = this._transformPoints(points);
|
|
176
175
|
if (!this._hasCurrentPosition())
|
|
177
|
-
this._setCurrentPosition(...
|
|
178
|
-
const curve = new SplineCurve([this._currentPosition.toArray()].concat(
|
|
176
|
+
this._setCurrentPosition(...points[0]);
|
|
177
|
+
const curve = new SplineCurve([this._currentPosition.toArray()].concat(points));
|
|
179
178
|
this.add(curve);
|
|
180
|
-
this._setCurrentPosition(...
|
|
179
|
+
this._setCurrentPosition(...points[points.length - 1]);
|
|
181
180
|
return this;
|
|
182
181
|
}
|
|
183
182
|
/**
|
|
@@ -195,18 +194,16 @@ export default class PathContext extends Path {
|
|
|
195
194
|
* @return {this}
|
|
196
195
|
*/
|
|
197
196
|
ellipse(cx, cy, rx, ry, rotation, startAngle, endAngle, counterclockwise) {
|
|
198
|
-
|
|
199
|
-
const start = EllipseCurve.interpolate(0,
|
|
200
|
-
const end = EllipseCurve.interpolate(1,
|
|
201
|
-
if (
|
|
202
|
-
this.
|
|
203
|
-
|
|
204
|
-
const curve = new LineCurve(this._currentPosition.x, this._currentPosition.y, ...start);
|
|
205
|
-
this.add(curve);
|
|
197
|
+
[cx, cy, rx, ry, rotation] = this._transformEllipse(cx, cy, rx, ry, rotation);
|
|
198
|
+
const start = EllipseCurve.interpolate(0, cx, cy, rx, ry, rotation, startAngle, endAngle, counterclockwise);
|
|
199
|
+
const end = EllipseCurve.interpolate(1, cx, cy, rx, ry, rotation, startAngle, endAngle, counterclockwise);
|
|
200
|
+
if (this._hasCurrentPosition() && !this._currentPosition.equals(start)) {
|
|
201
|
+
const line = new LineCurve(this._currentPosition.x, this._currentPosition.y, ...start);
|
|
202
|
+
this.add(line);
|
|
206
203
|
}
|
|
207
|
-
if (
|
|
204
|
+
if (rx <= EPSILON && ry <= EPSILON)
|
|
208
205
|
return this;
|
|
209
|
-
const curve = new EllipseCurve(
|
|
206
|
+
const curve = new EllipseCurve(cx, cy, rx, ry, rotation, startAngle, endAngle, counterclockwise);
|
|
210
207
|
this.add(curve);
|
|
211
208
|
this._setCurrentPosition(...end);
|
|
212
209
|
return this;
|
|
@@ -227,25 +224,23 @@ export default class PathContext extends Path {
|
|
|
227
224
|
if (!this._isUniform || this._isRotated) {
|
|
228
225
|
return this.ellipse(cx, cy, radius, radius, 0, startAngle, endAngle, counterclockwise);
|
|
229
226
|
}
|
|
230
|
-
|
|
231
|
-
const start = EllipseCurve.interpolate(0,
|
|
232
|
-
const end = EllipseCurve.interpolate(1,
|
|
233
|
-
if (
|
|
234
|
-
this.
|
|
235
|
-
|
|
236
|
-
const curve = new LineCurve(this._currentPosition.x, this._currentPosition.y, ...start);
|
|
237
|
-
this.add(curve);
|
|
227
|
+
[cx, cy, radius] = this._transformEllipse(cx, cy, radius, radius, 0);
|
|
228
|
+
const start = EllipseCurve.interpolate(0, cx, cy, radius, radius, 0, startAngle, endAngle, counterclockwise);
|
|
229
|
+
const end = EllipseCurve.interpolate(1, cx, cy, radius, radius, 0, startAngle, endAngle, counterclockwise);
|
|
230
|
+
if (this._hasCurrentPosition() && !this._currentPosition.equals(start)) {
|
|
231
|
+
const line = new LineCurve(this._currentPosition.x, this._currentPosition.y, ...start);
|
|
232
|
+
this.add(line);
|
|
238
233
|
}
|
|
239
|
-
if (
|
|
234
|
+
if (radius <= EPSILON)
|
|
240
235
|
return this;
|
|
241
|
-
const curve = new ArcCurve(
|
|
236
|
+
const curve = new ArcCurve(cx, cy, radius, startAngle, endAngle, counterclockwise);
|
|
242
237
|
this.add(curve);
|
|
243
238
|
this._setCurrentPosition(...end);
|
|
244
239
|
return this;
|
|
245
240
|
}
|
|
246
241
|
/**
|
|
247
242
|
* Draw an Arc curve from the current position, tangential to the 2 segments created by both control points
|
|
248
|
-
* Add an instance of {@link
|
|
243
|
+
* Add an instance of {@link EllipseCurve} to this path
|
|
249
244
|
*
|
|
250
245
|
* @param {number} x1 X-axis coordinate of the first control point
|
|
251
246
|
* @param {number} y1 Y-axis coordinate of the first control point
|
|
@@ -345,7 +340,6 @@ export default class PathContext extends Path {
|
|
|
345
340
|
bottomLeftRadius = Math.min(bottomLeftRadius, maxRadius);
|
|
346
341
|
const curve = new PathContext({ autoClose: true });
|
|
347
342
|
curve.setTransform(this.getTransform());
|
|
348
|
-
this.add(curve);
|
|
349
343
|
// Top-Right corner
|
|
350
344
|
if (topRightRadius > 0) {
|
|
351
345
|
curve.lineTo(x + width - topRightRadius, y);
|
|
@@ -378,6 +372,7 @@ export default class PathContext extends Path {
|
|
|
378
372
|
else {
|
|
379
373
|
curve.lineTo(x, y);
|
|
380
374
|
}
|
|
375
|
+
this.add(curve);
|
|
381
376
|
return this;
|
|
382
377
|
}
|
|
383
378
|
setTransform(a, b, c, d, e, f) {
|
|
@@ -426,43 +421,39 @@ export default class PathContext extends Path {
|
|
|
426
421
|
}
|
|
427
422
|
_setCurrentPosition(x, y) {
|
|
428
423
|
this._currentPosition.set(x, y);
|
|
429
|
-
this._positionTransform = this.getTransform();
|
|
430
424
|
return this;
|
|
431
425
|
}
|
|
432
426
|
// ****************************
|
|
433
427
|
// Matrix transformations
|
|
434
428
|
// ****************************
|
|
435
|
-
_transformPoint(point
|
|
436
|
-
if (
|
|
429
|
+
_transformPoint(point) {
|
|
430
|
+
if (this._isIdentity)
|
|
437
431
|
return point;
|
|
438
|
-
const { x, y } =
|
|
432
|
+
const { x, y } = this._currentTransform.transformPoint({ x: point[0], y: point[1] });
|
|
439
433
|
return [x, y];
|
|
440
434
|
}
|
|
441
|
-
_transformPoints(points
|
|
442
|
-
if (
|
|
435
|
+
_transformPoints(points) {
|
|
436
|
+
if (this._isIdentity)
|
|
443
437
|
return points;
|
|
444
|
-
return points.map((point) => this._transformPoint(point
|
|
438
|
+
return points.map((point) => this._transformPoint(point));
|
|
445
439
|
}
|
|
446
|
-
_transformVector(vector
|
|
447
|
-
if (
|
|
440
|
+
_transformVector(vector) {
|
|
441
|
+
if (this._isIdentity)
|
|
448
442
|
return vector;
|
|
449
|
-
const [x0, y0] = this._transformPoint([0, 0]
|
|
450
|
-
const [vx, vy] = this._transformPoint(vector
|
|
443
|
+
const [x0, y0] = this._transformPoint([0, 0]);
|
|
444
|
+
const [vx, vy] = this._transformPoint(vector);
|
|
451
445
|
return [vx - x0, vy - y0];
|
|
452
446
|
}
|
|
453
|
-
_transformEllipse(cx, cy, rx, ry, rotation
|
|
454
|
-
if (
|
|
447
|
+
_transformEllipse(cx, cy, rx, ry, rotation) {
|
|
448
|
+
if (this._isIdentity)
|
|
455
449
|
return [cx, cy, rx, ry, rotation];
|
|
456
|
-
|
|
457
|
-
const [
|
|
458
|
-
const [
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
return [
|
|
463
|
-
}
|
|
464
|
-
_inversePoint(point, matrix = this._currentTransform) {
|
|
465
|
-
return this._transformPoint(point, matrix.inverse());
|
|
450
|
+
[cx, cy] = this._transformPoint([cx, cy]);
|
|
451
|
+
const [u1x, u1y] = this._transformVector([Math.cos(rotation) * rx, Math.sin(rotation) * rx]);
|
|
452
|
+
const [u2x, u2y] = this._transformVector([-Math.sin(rotation) * ry, Math.cos(rotation) * ry]);
|
|
453
|
+
rx = Math.hypot(u1x, u1y);
|
|
454
|
+
ry = Math.hypot(u2x, u2y);
|
|
455
|
+
rotation = Math.atan2(u1y, u1x);
|
|
456
|
+
return [cx, cy, rx, ry, rotation];
|
|
466
457
|
}
|
|
467
458
|
get _translateX() {
|
|
468
459
|
return this._currentTransform.e;
|
|
@@ -482,20 +473,6 @@ export default class PathContext extends Path {
|
|
|
482
473
|
const { a, b } = this._currentTransform;
|
|
483
474
|
return Math.atan2(b, a);
|
|
484
475
|
}
|
|
485
|
-
get _skewX() {
|
|
486
|
-
const { c, d } = this._currentTransform;
|
|
487
|
-
const cos = Math.cos(this._rotation);
|
|
488
|
-
const sin = Math.sin(this._rotation);
|
|
489
|
-
const m11 = c * cos + d * sin;
|
|
490
|
-
return Math.atan(m11 / this._scaleX);
|
|
491
|
-
}
|
|
492
|
-
get _skewY() {
|
|
493
|
-
const { a, b } = this._currentTransform;
|
|
494
|
-
const cos = Math.cos(this._rotation);
|
|
495
|
-
const sin = Math.sin(this._rotation);
|
|
496
|
-
const m21 = a * sin - b * cos;
|
|
497
|
-
return Math.atan(m21 / this._scaleY);
|
|
498
|
-
}
|
|
499
476
|
get _isTranslated() {
|
|
500
477
|
return Math.abs(this._translateX) > EPSILON || Math.abs(this._translateY) > EPSILON;
|
|
501
478
|
}
|
|
@@ -506,12 +483,6 @@ export default class PathContext extends Path {
|
|
|
506
483
|
const { b, c } = this._currentTransform;
|
|
507
484
|
return Math.abs(b) > EPSILON || Math.abs(c) > EPSILON;
|
|
508
485
|
}
|
|
509
|
-
get _isSkewed() {
|
|
510
|
-
const { a, b, c, d } = this._currentTransform;
|
|
511
|
-
const angleX = Math.atan2(b, a);
|
|
512
|
-
const angleY = Math.atan2(-c, d);
|
|
513
|
-
return Math.abs(angleX - angleY) > EPSILON;
|
|
514
|
-
}
|
|
515
486
|
get _isUniform() {
|
|
516
487
|
return Math.abs(this._scaleX - this._scaleY) <= EPSILON;
|
|
517
488
|
}
|