pts 0.11.6 → 0.12.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/.eslintignore +5 -0
- package/.eslintrc.js +52 -0
- package/dist/index.d.mts +1378 -0
- package/dist/index.d.ts +31 -33
- package/dist/index.js +723 -737
- package/dist/index.mjs +723 -737
- package/dist/pts.js +723 -737
- package/dist/pts.min.js +3 -3
- package/dist/pts.min.js.map +1 -1
- package/package.json +10 -5
package/dist/pts.js
CHANGED
|
@@ -98,7 +98,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
98
98
|
Mat: () => Mat,
|
|
99
99
|
Vec: () => Vec
|
|
100
100
|
});
|
|
101
|
-
var Vec = class {
|
|
101
|
+
var Vec = class _Vec {
|
|
102
102
|
/**
|
|
103
103
|
* Add `b` to vector `a`.
|
|
104
104
|
* @returns vector `a`
|
|
@@ -191,44 +191,44 @@ See https://github.com/williamngan/pts for details. */
|
|
|
191
191
|
* Magnitude of `a`.
|
|
192
192
|
*/
|
|
193
193
|
static magnitude(a) {
|
|
194
|
-
return Math.sqrt(
|
|
194
|
+
return Math.sqrt(_Vec.dot(a, a));
|
|
195
195
|
}
|
|
196
196
|
/**
|
|
197
197
|
* Unit vector of `a`. If magnitude of `a` is already known, pass it in the second paramter to optimize calculation.
|
|
198
198
|
*/
|
|
199
199
|
static unit(a, magnitude = void 0) {
|
|
200
|
-
|
|
200
|
+
const m = magnitude === void 0 ? _Vec.magnitude(a) : magnitude;
|
|
201
201
|
if (m === 0)
|
|
202
202
|
return Pt.make(a.length);
|
|
203
|
-
return
|
|
203
|
+
return _Vec.divide(a, m);
|
|
204
204
|
}
|
|
205
205
|
/**
|
|
206
206
|
* Set `a` to its absolute value in each dimension.
|
|
207
207
|
* @returns vector `a`
|
|
208
208
|
*/
|
|
209
209
|
static abs(a) {
|
|
210
|
-
return
|
|
210
|
+
return _Vec.map(a, Math.abs);
|
|
211
211
|
}
|
|
212
212
|
/**
|
|
213
213
|
* Set `a` to its floor value in each dimension.
|
|
214
214
|
* @returns vector `a`
|
|
215
215
|
*/
|
|
216
216
|
static floor(a) {
|
|
217
|
-
return
|
|
217
|
+
return _Vec.map(a, Math.floor);
|
|
218
218
|
}
|
|
219
219
|
/**
|
|
220
220
|
* Set `a` to its ceiling value in each dimension.
|
|
221
221
|
* @returns vector `a`
|
|
222
222
|
*/
|
|
223
223
|
static ceil(a) {
|
|
224
|
-
return
|
|
224
|
+
return _Vec.map(a, Math.ceil);
|
|
225
225
|
}
|
|
226
226
|
/**
|
|
227
227
|
* Set `a` to its rounded value in each dimension.
|
|
228
228
|
* @returns vector `a`
|
|
229
229
|
*/
|
|
230
230
|
static round(a) {
|
|
231
|
-
return
|
|
231
|
+
return _Vec.map(a, Math.round);
|
|
232
232
|
}
|
|
233
233
|
/**
|
|
234
234
|
* Find the max value within a vector's dimensions.
|
|
@@ -278,7 +278,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
278
278
|
return a;
|
|
279
279
|
}
|
|
280
280
|
};
|
|
281
|
-
var Mat = class {
|
|
281
|
+
var Mat = class _Mat {
|
|
282
282
|
constructor() {
|
|
283
283
|
this.reset();
|
|
284
284
|
}
|
|
@@ -292,13 +292,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
292
292
|
* Convert the value of its stored 3x3 matrix to a 2D [`DOMMatrix`](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix) instance
|
|
293
293
|
*/
|
|
294
294
|
get domMatrix() {
|
|
295
|
-
return new DOMMatrix(
|
|
295
|
+
return new DOMMatrix(_Mat.toDOMMatrix(this._33));
|
|
296
296
|
}
|
|
297
297
|
/**
|
|
298
298
|
* Reset the internal 3x3 matrix to its identity
|
|
299
299
|
*/
|
|
300
300
|
reset() {
|
|
301
|
-
this._33 =
|
|
301
|
+
this._33 = _Mat.scale2DMatrix(1, 1);
|
|
302
302
|
}
|
|
303
303
|
/**
|
|
304
304
|
* Scale the internal 3x3 matrix. You can chain this function with other related functions.
|
|
@@ -306,8 +306,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
306
306
|
* @param at Optional origin location to scale from.
|
|
307
307
|
*/
|
|
308
308
|
scale2D(val, at = [0, 0]) {
|
|
309
|
-
const m =
|
|
310
|
-
this._33 =
|
|
309
|
+
const m = _Mat.scaleAt2DMatrix(val[0] || 1, val[1] || 1, at);
|
|
310
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
311
311
|
return this;
|
|
312
312
|
}
|
|
313
313
|
/**
|
|
@@ -316,8 +316,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
316
316
|
* @param at Optional origin location to rotate from.
|
|
317
317
|
*/
|
|
318
318
|
rotate2D(ang, at = [0, 0]) {
|
|
319
|
-
const m =
|
|
320
|
-
this._33 =
|
|
319
|
+
const m = _Mat.rotateAt2DMatrix(Math.cos(ang), Math.sin(ang), at);
|
|
320
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
321
321
|
return this;
|
|
322
322
|
}
|
|
323
323
|
/**
|
|
@@ -325,8 +325,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
325
325
|
* @param val [x, y] offset values
|
|
326
326
|
*/
|
|
327
327
|
translate2D(val) {
|
|
328
|
-
const m =
|
|
329
|
-
this._33 =
|
|
328
|
+
const m = _Mat.translate2DMatrix(val[0] || 0, val[1] || 0);
|
|
329
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
330
330
|
return this;
|
|
331
331
|
}
|
|
332
332
|
/**
|
|
@@ -335,8 +335,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
335
335
|
* @param at Optional origin location to scale from.
|
|
336
336
|
*/
|
|
337
337
|
shear2D(val, at = [0, 0]) {
|
|
338
|
-
const m =
|
|
339
|
-
this._33 =
|
|
338
|
+
const m = _Mat.shearAt2DMatrix(Math.tan(val[0] || 0), Math.tan(val[1] || 1), at);
|
|
339
|
+
this._33 = _Mat.multiply(this._33, m);
|
|
340
340
|
return this;
|
|
341
341
|
}
|
|
342
342
|
/**
|
|
@@ -352,8 +352,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
352
352
|
if (a.length != b.length)
|
|
353
353
|
throw new Error("Cannot add matrix if rows' and columns' size don't match.");
|
|
354
354
|
}
|
|
355
|
-
|
|
356
|
-
|
|
355
|
+
const g = new Group();
|
|
356
|
+
const isNum = typeof b == "number";
|
|
357
357
|
for (let i = 0, len = a.length; i < len; i++) {
|
|
358
358
|
g.push(a[i].$add(isNum ? b : b[i]));
|
|
359
359
|
}
|
|
@@ -368,7 +368,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
368
368
|
* @returns If not elementwise, this will return a new group with M Pt, each with N dimensions (M-rows, N-columns).
|
|
369
369
|
*/
|
|
370
370
|
static multiply(a, b, transposed = false, elementwise = false) {
|
|
371
|
-
|
|
371
|
+
const g = new Group();
|
|
372
372
|
if (typeof b != "number") {
|
|
373
373
|
if (elementwise) {
|
|
374
374
|
if (a.length != b.length)
|
|
@@ -382,9 +382,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
382
382
|
if (transposed && a[0].length != b[0].length)
|
|
383
383
|
throw new Error("Cannot multiply matrix if transposed and the columns in both matrices don't match.");
|
|
384
384
|
if (!transposed)
|
|
385
|
-
b =
|
|
385
|
+
b = _Mat.transpose(b);
|
|
386
386
|
for (let ai = 0, alen = a.length; ai < alen; ai++) {
|
|
387
|
-
|
|
387
|
+
const p = Pt.make(b.length, 0);
|
|
388
388
|
for (let bi = 0, blen = b.length; bi < blen; bi++) {
|
|
389
389
|
p[bi] = Vec.dot(a[ai], b[bi]);
|
|
390
390
|
}
|
|
@@ -405,7 +405,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
405
405
|
* @param defaultValue a default value to fill if index out of bound. If not provided, it will throw an error instead.
|
|
406
406
|
*/
|
|
407
407
|
static zipSlice(g, index, defaultValue = false) {
|
|
408
|
-
|
|
408
|
+
const z = [];
|
|
409
409
|
for (let i = 0, len = g.length; i < len; i++) {
|
|
410
410
|
if (g[i].length - 1 < index && defaultValue === false)
|
|
411
411
|
throw `Index ${index} is out of bounds`;
|
|
@@ -420,10 +420,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
420
420
|
* @param useLongest If true, find the longest list of values in a Pt and use its length for zipping. Default is false, which uses the first item's length for zipping.
|
|
421
421
|
*/
|
|
422
422
|
static zip(g, defaultValue = false, useLongest = false) {
|
|
423
|
-
|
|
424
|
-
|
|
423
|
+
const ps = new Group();
|
|
424
|
+
const len = useLongest ? g.reduce((a, b) => Math.max(a, b.length), 0) : g[0].length;
|
|
425
425
|
for (let i = 0; i < len; i++) {
|
|
426
|
-
ps.push(
|
|
426
|
+
ps.push(_Mat.zipSlice(g, i, defaultValue));
|
|
427
427
|
}
|
|
428
428
|
return ps;
|
|
429
429
|
}
|
|
@@ -431,7 +431,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
431
431
|
* Same as `zip` function.
|
|
432
432
|
*/
|
|
433
433
|
static transpose(g, defaultValue = false, useLongest = false) {
|
|
434
|
-
return
|
|
434
|
+
return _Mat.zip(g, defaultValue, useLongest);
|
|
435
435
|
}
|
|
436
436
|
static toDOMMatrix(m) {
|
|
437
437
|
return [m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1]];
|
|
@@ -443,8 +443,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
443
443
|
* @returns a new transformed Pt
|
|
444
444
|
*/
|
|
445
445
|
static transform2D(pt, m) {
|
|
446
|
-
|
|
447
|
-
|
|
446
|
+
const x = pt[0] * m[0][0] + pt[1] * m[1][0] + m[2][0];
|
|
447
|
+
const y = pt[0] * m[0][1] + pt[1] * m[1][1] + m[2][1];
|
|
448
448
|
return new Pt(x, y);
|
|
449
449
|
}
|
|
450
450
|
/**
|
|
@@ -491,7 +491,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
491
491
|
* Get a matrix to scale a point from an origin point. For use in `transform2D`.
|
|
492
492
|
*/
|
|
493
493
|
static scaleAt2DMatrix(sx, sy, at) {
|
|
494
|
-
|
|
494
|
+
const m = _Mat.scale2DMatrix(sx, sy);
|
|
495
495
|
m[2][0] = -at[0] * sx + at[0];
|
|
496
496
|
m[2][1] = -at[1] * sy + at[1];
|
|
497
497
|
return m;
|
|
@@ -500,7 +500,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
500
500
|
* Get a matrix to rotate a point from an origin point. For use in `transform2D`.
|
|
501
501
|
*/
|
|
502
502
|
static rotateAt2DMatrix(cosA, sinA, at) {
|
|
503
|
-
|
|
503
|
+
const m = _Mat.rotate2DMatrix(cosA, sinA);
|
|
504
504
|
m[2][0] = at[0] * (1 - cosA) + at[1] * sinA;
|
|
505
505
|
m[2][1] = at[1] * (1 - cosA) - at[0] * sinA;
|
|
506
506
|
return m;
|
|
@@ -509,7 +509,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
509
509
|
* Get a matrix to shear a point from an origin point. For use in `transform2D`.
|
|
510
510
|
*/
|
|
511
511
|
static shearAt2DMatrix(tanX, tanY, at) {
|
|
512
|
-
|
|
512
|
+
const m = _Mat.shear2DMatrix(tanX, tanY);
|
|
513
513
|
m[2][0] = -at[1] * tanY;
|
|
514
514
|
m[2][1] = -at[0] * tanX;
|
|
515
515
|
return m;
|
|
@@ -520,7 +520,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
520
520
|
* @param p1 second end point to define the reflection line
|
|
521
521
|
*/
|
|
522
522
|
static reflectAt2DMatrix(p1, p2) {
|
|
523
|
-
|
|
523
|
+
const intercept = Line.intercept(p1, p2);
|
|
524
524
|
if (intercept == void 0) {
|
|
525
525
|
return [
|
|
526
526
|
new Pt([-1, 0, 0]),
|
|
@@ -528,10 +528,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
528
528
|
new Pt([p1[0] + p2[0], 0, 1])
|
|
529
529
|
];
|
|
530
530
|
} else {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
531
|
+
const yi = intercept.yi;
|
|
532
|
+
const ang2 = Math.atan(intercept.slope) * 2;
|
|
533
|
+
const cosA = Math.cos(ang2);
|
|
534
|
+
const sinA = Math.sin(ang2);
|
|
535
535
|
return [
|
|
536
536
|
new Pt([cosA, sinA, 0]),
|
|
537
537
|
new Pt([sinA, -cosA, 0]),
|
|
@@ -544,7 +544,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
544
544
|
// src/Op.ts
|
|
545
545
|
var _errorLength = (obj, param = "expected") => Util.warn("Group's length is less than " + param, obj);
|
|
546
546
|
var _errorOutofBound = (obj, param = "") => Util.warn(`Index ${param} is out of bound in Group`, obj);
|
|
547
|
-
var Line = class {
|
|
547
|
+
var Line = class _Line {
|
|
548
548
|
/**
|
|
549
549
|
* Create a line that originates from an anchor point, given an angle and a magnitude.
|
|
550
550
|
* @param anchor an anchor Pt
|
|
@@ -642,7 +642,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
642
642
|
*/
|
|
643
643
|
static distanceFromPt(line, pt) {
|
|
644
644
|
let _line = Util.iterToArray(line);
|
|
645
|
-
let projectionVector =
|
|
645
|
+
let projectionVector = _Line.perpendicularFromPt(_line, pt, true);
|
|
646
646
|
if (projectionVector) {
|
|
647
647
|
return projectionVector.magnitude();
|
|
648
648
|
} else {
|
|
@@ -658,8 +658,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
658
658
|
static intersectRay2D(la, lb) {
|
|
659
659
|
let _la = Util.iterToArray(la);
|
|
660
660
|
let _lb = Util.iterToArray(lb);
|
|
661
|
-
let a =
|
|
662
|
-
let b =
|
|
661
|
+
let a = _Line.intercept(_la[0], _la[1]);
|
|
662
|
+
let b = _Line.intercept(_lb[0], _lb[1]);
|
|
663
663
|
let pa = _la[0];
|
|
664
664
|
let pb = _lb[0];
|
|
665
665
|
if (a == void 0) {
|
|
@@ -693,7 +693,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
693
693
|
static intersectLine2D(la, lb) {
|
|
694
694
|
let _la = Util.iterToArray(la);
|
|
695
695
|
let _lb = Util.iterToArray(lb);
|
|
696
|
-
let pt =
|
|
696
|
+
let pt = _Line.intersectRay2D(_la, _lb);
|
|
697
697
|
return pt && Geom.withinBound(pt, _la[0], _la[1]) && Geom.withinBound(pt, _lb[0], _lb[1]) ? pt : void 0;
|
|
698
698
|
}
|
|
699
699
|
/**
|
|
@@ -705,7 +705,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
705
705
|
static intersectLineWithRay2D(line, ray) {
|
|
706
706
|
let _line = Util.iterToArray(line);
|
|
707
707
|
let _ray = Util.iterToArray(ray);
|
|
708
|
-
let pt =
|
|
708
|
+
let pt = _Line.intersectRay2D(_line, _ray);
|
|
709
709
|
return pt && Geom.withinBound(pt, _line[0], _line[1]) ? pt : void 0;
|
|
710
710
|
}
|
|
711
711
|
/**
|
|
@@ -717,7 +717,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
717
717
|
static intersectPolygon2D(lineOrRay, poly, sourceIsRay = false) {
|
|
718
718
|
let _lineOrRay = Util.iterToArray(lineOrRay);
|
|
719
719
|
let _poly = Util.iterToArray(poly);
|
|
720
|
-
let fn = sourceIsRay ?
|
|
720
|
+
let fn = sourceIsRay ? _Line.intersectLineWithRay2D : _Line.intersectLine2D;
|
|
721
721
|
let pts = new Group();
|
|
722
722
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
723
723
|
let next = i === len - 1 ? 0 : i + 1;
|
|
@@ -735,7 +735,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
735
735
|
*/
|
|
736
736
|
static intersectLines2D(lines1, lines2, isRay = false) {
|
|
737
737
|
let group = new Group();
|
|
738
|
-
let fn = isRay ?
|
|
738
|
+
let fn = isRay ? _Line.intersectLineWithRay2D : _Line.intersectLine2D;
|
|
739
739
|
for (let l1 of lines1) {
|
|
740
740
|
for (let l2 of lines2) {
|
|
741
741
|
let _ip = fn(l1, l2);
|
|
@@ -753,7 +753,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
753
753
|
*/
|
|
754
754
|
static intersectGridWithRay2D(ray, gridPt) {
|
|
755
755
|
let _ray = Util.iterToArray(ray);
|
|
756
|
-
let t =
|
|
756
|
+
let t = _Line.intercept(new Pt(_ray[0]).subtract(gridPt), new Pt(_ray[1]).subtract(gridPt));
|
|
757
757
|
let g = new Group();
|
|
758
758
|
if (t && t.xi)
|
|
759
759
|
g.push(new Pt(gridPt[0] + t.xi, gridPt[1]));
|
|
@@ -769,7 +769,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
769
769
|
*/
|
|
770
770
|
static intersectGridWithLine2D(line, gridPt) {
|
|
771
771
|
let _line = Util.iterToArray(line);
|
|
772
|
-
let g =
|
|
772
|
+
let g = _Line.intersectGridWithRay2D(_line, gridPt);
|
|
773
773
|
let gg = new Group();
|
|
774
774
|
for (let i = 0, len = g.length; i < len; i++) {
|
|
775
775
|
if (Geom.withinBound(g[i], _line[0], _line[1]))
|
|
@@ -789,7 +789,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
789
789
|
let box = Geom.boundingBox(Group.fromPtArray(_line));
|
|
790
790
|
if (!Rectangle.hasIntersectRect2D(box, _rect))
|
|
791
791
|
return new Group();
|
|
792
|
-
return
|
|
792
|
+
return _Line.intersectLines2D([_line], Rectangle.sides(_rect));
|
|
793
793
|
}
|
|
794
794
|
/**
|
|
795
795
|
* Get evenly distributed points on a line. Similar to [`Create.distributeLinear`](#link) but excluding end points.
|
|
@@ -830,7 +830,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
830
830
|
} else {
|
|
831
831
|
sideIdx = ls[0] < 0 ? 3 : 1;
|
|
832
832
|
}
|
|
833
|
-
return
|
|
833
|
+
return _Line.intersectRay2D(sides[sideIdx], _line);
|
|
834
834
|
}
|
|
835
835
|
}
|
|
836
836
|
/**
|
|
@@ -866,7 +866,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
866
866
|
return new Group(_line[0].$min(_line[1]), _line[0].$max(_line[1]));
|
|
867
867
|
}
|
|
868
868
|
};
|
|
869
|
-
var Rectangle = class {
|
|
869
|
+
var Rectangle = class _Rectangle {
|
|
870
870
|
/**
|
|
871
871
|
* Create a rectangle from top-left anchor point. Same as [`Rectangle.fromTopLeft`](#link).
|
|
872
872
|
* @param topLeft top-left point
|
|
@@ -875,7 +875,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
875
875
|
* @returns a Group of 2 Pts representing a rectangle
|
|
876
876
|
*/
|
|
877
877
|
static from(topLeft, widthOrSize, height) {
|
|
878
|
-
return
|
|
878
|
+
return _Rectangle.fromTopLeft(topLeft, widthOrSize, height);
|
|
879
879
|
}
|
|
880
880
|
/**
|
|
881
881
|
* Create a rectangle given a top-left position and a size.
|
|
@@ -916,9 +916,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
916
916
|
*/
|
|
917
917
|
static toSquare(pts, enclose = false) {
|
|
918
918
|
let _pts = Util.iterToArray(pts);
|
|
919
|
-
let s =
|
|
919
|
+
let s = _Rectangle.size(_pts);
|
|
920
920
|
let m = enclose ? s.maxValue().value : s.minValue().value;
|
|
921
|
-
return
|
|
921
|
+
return _Rectangle.fromCenter(_Rectangle.center(_pts), m, m);
|
|
922
922
|
}
|
|
923
923
|
/**
|
|
924
924
|
* Get the size of this rectangle as a Pt.
|
|
@@ -954,7 +954,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
954
954
|
* @returns an array of 4 Groups, each of which represents a line segment
|
|
955
955
|
*/
|
|
956
956
|
static sides(rect) {
|
|
957
|
-
let [p0, p1, p2, p3] =
|
|
957
|
+
let [p0, p1, p2, p3] = _Rectangle.corners(rect);
|
|
958
958
|
return [
|
|
959
959
|
new Group(p0, p1),
|
|
960
960
|
new Group(p1, p2),
|
|
@@ -988,7 +988,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
988
988
|
* @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle
|
|
989
989
|
*/
|
|
990
990
|
static polygon(rect) {
|
|
991
|
-
return
|
|
991
|
+
return _Rectangle.corners(rect);
|
|
992
992
|
}
|
|
993
993
|
/**
|
|
994
994
|
* Subdivide a rectangle into 4 rectangles, one for each quadrant.
|
|
@@ -997,8 +997,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
997
997
|
*/
|
|
998
998
|
static quadrants(rect, center) {
|
|
999
999
|
let _rect = Util.iterToArray(rect);
|
|
1000
|
-
let corners =
|
|
1001
|
-
let _center = center != void 0 ? new Pt(center) :
|
|
1000
|
+
let corners = _Rectangle.corners(_rect);
|
|
1001
|
+
let _center = center != void 0 ? new Pt(center) : _Rectangle.center(_rect);
|
|
1002
1002
|
return corners.map((c) => new Group(c, _center).boundingBox());
|
|
1003
1003
|
}
|
|
1004
1004
|
/**
|
|
@@ -1051,12 +1051,12 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1051
1051
|
static intersectRect2D(rect1, rect2) {
|
|
1052
1052
|
let _rect1 = Util.iterToArray(rect1);
|
|
1053
1053
|
let _rect2 = Util.iterToArray(rect2);
|
|
1054
|
-
if (!
|
|
1054
|
+
if (!_Rectangle.hasIntersectRect2D(_rect1, _rect2))
|
|
1055
1055
|
return new Group();
|
|
1056
|
-
return Line.intersectLines2D(
|
|
1056
|
+
return Line.intersectLines2D(_Rectangle.sides(_rect1), _Rectangle.sides(_rect2));
|
|
1057
1057
|
}
|
|
1058
1058
|
};
|
|
1059
|
-
var Circle = class {
|
|
1059
|
+
var Circle = class _Circle {
|
|
1060
1060
|
/**
|
|
1061
1061
|
* Create a circle that either fits within, or encloses, a rectangle.
|
|
1062
1062
|
* @param pts a Group or an Iterable<PtLike> with 2 Pt representing a rectangle
|
|
@@ -1147,7 +1147,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1147
1147
|
static intersectLine2D(circle, line) {
|
|
1148
1148
|
let _pts = Util.iterToArray(circle);
|
|
1149
1149
|
let _line = Util.iterToArray(line);
|
|
1150
|
-
let ps =
|
|
1150
|
+
let ps = _Circle.intersectRay2D(_pts, _line);
|
|
1151
1151
|
let g = new Group();
|
|
1152
1152
|
if (ps.length > 0) {
|
|
1153
1153
|
for (let i = 0, len = ps.length; i < len; i++) {
|
|
@@ -1200,7 +1200,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1200
1200
|
let sides = Rectangle.sides(_rect);
|
|
1201
1201
|
let g = [];
|
|
1202
1202
|
for (let i = 0, len = sides.length; i < len; i++) {
|
|
1203
|
-
let ps =
|
|
1203
|
+
let ps = _Circle.intersectLine2D(_pts, sides[i]);
|
|
1204
1204
|
if (ps.length > 0)
|
|
1205
1205
|
g.push(ps);
|
|
1206
1206
|
}
|
|
@@ -1243,7 +1243,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1243
1243
|
}
|
|
1244
1244
|
}
|
|
1245
1245
|
};
|
|
1246
|
-
var Triangle = class {
|
|
1246
|
+
var Triangle = class _Triangle {
|
|
1247
1247
|
/**
|
|
1248
1248
|
* Create a triangle from a rectangle. The triangle will be isosceles, with the bottom of the rectangle as its base.
|
|
1249
1249
|
* @param rect a Group or an Iterable<Pt> with 2 Pt representing a rectangle
|
|
@@ -1269,7 +1269,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1269
1269
|
* @param size size is the magnitude of lines from center to the triangle's vertices, like a "radius".
|
|
1270
1270
|
*/
|
|
1271
1271
|
static fromCenter(pt, size) {
|
|
1272
|
-
return
|
|
1272
|
+
return _Triangle.fromCircle(Circle.fromCenter(pt, size));
|
|
1273
1273
|
}
|
|
1274
1274
|
/**
|
|
1275
1275
|
* Get the medial, which is an inner triangle formed by connecting the midpoints of this triangle's sides.
|
|
@@ -1308,7 +1308,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1308
1308
|
*/
|
|
1309
1309
|
static altitude(tri, index) {
|
|
1310
1310
|
let _pts = Util.iterToArray(tri);
|
|
1311
|
-
let opp =
|
|
1311
|
+
let opp = _Triangle.oppositeSide(_pts, index);
|
|
1312
1312
|
if (opp.length > 1) {
|
|
1313
1313
|
return new Group(_pts[index], Line.perpendicularFromPt(opp, _pts[index]));
|
|
1314
1314
|
} else {
|
|
@@ -1324,8 +1324,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1324
1324
|
let _pts = Util.iterToArray(tri);
|
|
1325
1325
|
if (_pts.length < 3)
|
|
1326
1326
|
return _errorLength(void 0, 3);
|
|
1327
|
-
let a =
|
|
1328
|
-
let b =
|
|
1327
|
+
let a = _Triangle.altitude(_pts, 0);
|
|
1328
|
+
let b = _Triangle.altitude(_pts, 1);
|
|
1329
1329
|
return Line.intersectRay2D(a, b);
|
|
1330
1330
|
}
|
|
1331
1331
|
/**
|
|
@@ -1348,7 +1348,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1348
1348
|
*/
|
|
1349
1349
|
static incircle(tri, center) {
|
|
1350
1350
|
let _pts = Util.iterToArray(tri);
|
|
1351
|
-
let c = center ? center :
|
|
1351
|
+
let c = center ? center : _Triangle.incenter(_pts);
|
|
1352
1352
|
let area = Polygon.area(_pts);
|
|
1353
1353
|
let perim = Polygon.perimeter(_pts, true);
|
|
1354
1354
|
let r = 2 * area / perim.total;
|
|
@@ -1361,7 +1361,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1361
1361
|
*/
|
|
1362
1362
|
static circumcenter(tri) {
|
|
1363
1363
|
let _pts = Util.iterToArray(tri);
|
|
1364
|
-
let md =
|
|
1364
|
+
let md = _Triangle.medial(_pts);
|
|
1365
1365
|
let a = [md[0], Geom.perpendicular(_pts[0].$subtract(md[0])).p1.$add(md[0])];
|
|
1366
1366
|
let b = [md[1], Geom.perpendicular(_pts[1].$subtract(md[1])).p1.$add(md[1])];
|
|
1367
1367
|
return Line.intersectRay2D(a, b);
|
|
@@ -1373,12 +1373,12 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1373
1373
|
*/
|
|
1374
1374
|
static circumcircle(tri, center) {
|
|
1375
1375
|
let _pts = Util.iterToArray(tri);
|
|
1376
|
-
let c = center ? center :
|
|
1376
|
+
let c = center ? center : _Triangle.circumcenter(_pts);
|
|
1377
1377
|
let r = _pts[0].$subtract(c).magnitude();
|
|
1378
1378
|
return Circle.fromCenter(c, r);
|
|
1379
1379
|
}
|
|
1380
1380
|
};
|
|
1381
|
-
var Polygon = class {
|
|
1381
|
+
var Polygon = class _Polygon {
|
|
1382
1382
|
/**
|
|
1383
1383
|
* Get the centroid of a polygon, which is the average of all its points.
|
|
1384
1384
|
* @param pts a Group or an Iterable<PtLike> representing a polygon
|
|
@@ -1442,7 +1442,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1442
1442
|
* @param t a value between 0 to 1 for interpolation. Default to 0.5 which will get the middle point.
|
|
1443
1443
|
*/
|
|
1444
1444
|
static midpoints(poly, closePath = false, t = 0.5) {
|
|
1445
|
-
let sides =
|
|
1445
|
+
let sides = _Polygon.lines(poly, closePath);
|
|
1446
1446
|
let mids = sides.map((s) => Geom.interpolate(s[0], s[1], t));
|
|
1447
1447
|
return mids;
|
|
1448
1448
|
}
|
|
@@ -1479,7 +1479,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1479
1479
|
* @returns a bisector Pt that's a normalized unit vector
|
|
1480
1480
|
*/
|
|
1481
1481
|
static bisector(poly, index) {
|
|
1482
|
-
let sides =
|
|
1482
|
+
let sides = _Polygon.adjacentSides(poly, index, true);
|
|
1483
1483
|
if (sides.length >= 2) {
|
|
1484
1484
|
let a = sides[0][1].$subtract(sides[0][0]).unit();
|
|
1485
1485
|
let b = sides[1][1].$subtract(sides[1][0]).unit();
|
|
@@ -1495,7 +1495,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1495
1495
|
* @returns an object with `total` length, and `segments` which is a Pt that stores each segment's length
|
|
1496
1496
|
*/
|
|
1497
1497
|
static perimeter(poly, closePath = false) {
|
|
1498
|
-
let lines =
|
|
1498
|
+
let lines = _Polygon.lines(poly, closePath);
|
|
1499
1499
|
let mag = 0;
|
|
1500
1500
|
let p = Pt.make(lines.length, 0);
|
|
1501
1501
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
@@ -1635,8 +1635,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1635
1635
|
* @param unitAxis unit axis
|
|
1636
1636
|
*/
|
|
1637
1637
|
static _axisOverlap(poly1, poly2, unitAxis) {
|
|
1638
|
-
let pa =
|
|
1639
|
-
let pb =
|
|
1638
|
+
let pa = _Polygon.projectAxis(poly1, unitAxis);
|
|
1639
|
+
let pb = _Polygon.projectAxis(poly2, unitAxis);
|
|
1640
1640
|
return pa[0] < pb[0] ? pb[0] - pa[1] : pa[0] - pb[1];
|
|
1641
1641
|
}
|
|
1642
1642
|
/**
|
|
@@ -1648,7 +1648,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1648
1648
|
let _poly = Util.iterToArray(poly);
|
|
1649
1649
|
let c = false;
|
|
1650
1650
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
1651
|
-
let ln =
|
|
1651
|
+
let ln = _Polygon.lineAt(_poly, i);
|
|
1652
1652
|
if (ln[0][1] > pt[1] != ln[1][1] > pt[1] && pt[0] < (ln[1][0] - ln[0][0]) * (pt[1] - ln[0][1]) / (ln[1][1] - ln[0][1]) + ln[0][0]) {
|
|
1653
1653
|
c = !c;
|
|
1654
1654
|
}
|
|
@@ -1679,10 +1679,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1679
1679
|
let r = _circle[1][0];
|
|
1680
1680
|
let minDist = Number.MAX_SAFE_INTEGER;
|
|
1681
1681
|
for (let i = 0, len = _poly.length; i < len; i++) {
|
|
1682
|
-
let edge =
|
|
1682
|
+
let edge = _Polygon.lineAt(_poly, i);
|
|
1683
1683
|
let axis = new Pt(edge[0].y - edge[1].y, edge[1].x - edge[0].x).unit();
|
|
1684
1684
|
let poly2 = new Group(c.$add(axis.$multiply(r)), c.$subtract(axis.$multiply(r)));
|
|
1685
|
-
let dist =
|
|
1685
|
+
let dist = _Polygon._axisOverlap(_poly, poly2, axis);
|
|
1686
1686
|
if (dist > 0) {
|
|
1687
1687
|
return null;
|
|
1688
1688
|
} else if (Math.abs(dist) < minDist) {
|
|
@@ -1697,7 +1697,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1697
1697
|
}
|
|
1698
1698
|
if (!info.edge)
|
|
1699
1699
|
return null;
|
|
1700
|
-
let dir = c.$subtract(
|
|
1700
|
+
let dir = c.$subtract(_Polygon.centroid(_poly)).dot(info.normal);
|
|
1701
1701
|
if (dir < 0)
|
|
1702
1702
|
info.normal.multiply(-1);
|
|
1703
1703
|
info.dist = minDist;
|
|
@@ -1726,9 +1726,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1726
1726
|
};
|
|
1727
1727
|
let minDist = Number.MAX_SAFE_INTEGER;
|
|
1728
1728
|
for (let i = 0, plen = _poly1.length + _poly2.length; i < plen; i++) {
|
|
1729
|
-
let edge = i < _poly1.length ?
|
|
1729
|
+
let edge = i < _poly1.length ? _Polygon.lineAt(_poly1, i) : _Polygon.lineAt(_poly2, i - _poly1.length);
|
|
1730
1730
|
let axis = new Pt(edge[0].y - edge[1].y, edge[1].x - edge[0].x).unit();
|
|
1731
|
-
let dist =
|
|
1731
|
+
let dist = _Polygon._axisOverlap(_poly1, _poly2, axis);
|
|
1732
1732
|
if (dist > 0) {
|
|
1733
1733
|
return null;
|
|
1734
1734
|
} else if (Math.abs(dist) < minDist) {
|
|
@@ -1741,8 +1741,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1741
1741
|
info.dist = minDist;
|
|
1742
1742
|
let b1 = info.which === 0 ? _poly2 : _poly1;
|
|
1743
1743
|
let b2 = info.which === 0 ? _poly1 : _poly2;
|
|
1744
|
-
let c1 =
|
|
1745
|
-
let c2 =
|
|
1744
|
+
let c1 = _Polygon.centroid(b1);
|
|
1745
|
+
let c2 = _Polygon.centroid(b2);
|
|
1746
1746
|
let dir = c1.$subtract(c2).dot(info.normal);
|
|
1747
1747
|
if (dir < 0)
|
|
1748
1748
|
info.normal.multiply(-1);
|
|
@@ -1764,7 +1764,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1764
1764
|
static intersectPolygon2D(poly1, poly2) {
|
|
1765
1765
|
let _poly1 = Util.iterToArray(poly1);
|
|
1766
1766
|
let _poly2 = Util.iterToArray(poly2);
|
|
1767
|
-
let lp =
|
|
1767
|
+
let lp = _Polygon.lines(_poly1);
|
|
1768
1768
|
let g = [];
|
|
1769
1769
|
for (let i = 0, len = lp.length; i < len; i++) {
|
|
1770
1770
|
let ins = Line.intersectPolygon2D(lp[i], _poly2, false);
|
|
@@ -1787,7 +1787,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1787
1787
|
return boxes;
|
|
1788
1788
|
}
|
|
1789
1789
|
};
|
|
1790
|
-
var Curve = class {
|
|
1790
|
+
var Curve = class _Curve {
|
|
1791
1791
|
/**
|
|
1792
1792
|
* Get a precalculated coefficients per step.
|
|
1793
1793
|
* @param steps number of steps
|
|
@@ -1846,17 +1846,17 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1846
1846
|
if (_pts.length < 2)
|
|
1847
1847
|
return new Group();
|
|
1848
1848
|
let ps = new Group();
|
|
1849
|
-
let ts =
|
|
1850
|
-
let c =
|
|
1849
|
+
let ts = _Curve.getSteps(steps);
|
|
1850
|
+
let c = _Curve.controlPoints(_pts, 0, true);
|
|
1851
1851
|
for (let i = 0; i <= steps; i++) {
|
|
1852
|
-
ps.push(
|
|
1852
|
+
ps.push(_Curve.catmullRomStep(ts[i], c));
|
|
1853
1853
|
}
|
|
1854
1854
|
let k = 0;
|
|
1855
1855
|
while (k < _pts.length - 2) {
|
|
1856
|
-
let cp =
|
|
1856
|
+
let cp = _Curve.controlPoints(_pts, k);
|
|
1857
1857
|
if (cp.length > 0) {
|
|
1858
1858
|
for (let i = 0; i <= steps; i++) {
|
|
1859
|
-
ps.push(
|
|
1859
|
+
ps.push(_Curve.catmullRomStep(ts[i], cp));
|
|
1860
1860
|
}
|
|
1861
1861
|
k++;
|
|
1862
1862
|
}
|
|
@@ -1876,7 +1876,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1876
1876
|
new Pt(-1.5, 2, 0.5, 0),
|
|
1877
1877
|
new Pt(0.5, -0.5, 0, 0)
|
|
1878
1878
|
);
|
|
1879
|
-
return
|
|
1879
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
1880
1880
|
}
|
|
1881
1881
|
/**
|
|
1882
1882
|
* Create a Cardinal curve.
|
|
@@ -1890,17 +1890,17 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1890
1890
|
if (_pts.length < 2)
|
|
1891
1891
|
return new Group();
|
|
1892
1892
|
let ps = new Group();
|
|
1893
|
-
let ts =
|
|
1894
|
-
let c =
|
|
1893
|
+
let ts = _Curve.getSteps(steps);
|
|
1894
|
+
let c = _Curve.controlPoints(_pts, 0, true);
|
|
1895
1895
|
for (let i = 0; i <= steps; i++) {
|
|
1896
|
-
ps.push(
|
|
1896
|
+
ps.push(_Curve.cardinalStep(ts[i], c, tension));
|
|
1897
1897
|
}
|
|
1898
1898
|
let k = 0;
|
|
1899
1899
|
while (k < _pts.length - 2) {
|
|
1900
|
-
let cp =
|
|
1900
|
+
let cp = _Curve.controlPoints(_pts, k);
|
|
1901
1901
|
if (cp.length > 0) {
|
|
1902
1902
|
for (let i = 0; i <= steps; i++) {
|
|
1903
|
-
ps.push(
|
|
1903
|
+
ps.push(_Curve.cardinalStep(ts[i], cp, tension));
|
|
1904
1904
|
}
|
|
1905
1905
|
k++;
|
|
1906
1906
|
}
|
|
@@ -1924,7 +1924,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1924
1924
|
let h = Mat.multiply([step], m, true)[0].multiply(tension);
|
|
1925
1925
|
let h2 = 2 * step[0] - 3 * step[1] + 1;
|
|
1926
1926
|
let h3 = -2 * step[0] + 3 * step[1];
|
|
1927
|
-
let pt =
|
|
1927
|
+
let pt = _Curve._calcPt(ctrls, h);
|
|
1928
1928
|
pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;
|
|
1929
1929
|
pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;
|
|
1930
1930
|
if (pt.length > 2)
|
|
@@ -1942,13 +1942,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1942
1942
|
if (_pts.length < 4)
|
|
1943
1943
|
return new Group();
|
|
1944
1944
|
let ps = new Group();
|
|
1945
|
-
let ts =
|
|
1945
|
+
let ts = _Curve.getSteps(steps);
|
|
1946
1946
|
let k = 0;
|
|
1947
1947
|
while (k < _pts.length - 3) {
|
|
1948
|
-
let c =
|
|
1948
|
+
let c = _Curve.controlPoints(_pts, k);
|
|
1949
1949
|
if (c.length > 0) {
|
|
1950
1950
|
for (let i = 0; i <= steps; i++) {
|
|
1951
|
-
ps.push(
|
|
1951
|
+
ps.push(_Curve.bezierStep(ts[i], c));
|
|
1952
1952
|
}
|
|
1953
1953
|
k += 3;
|
|
1954
1954
|
}
|
|
@@ -1968,7 +1968,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1968
1968
|
new Pt(-3, 3, 0, 0),
|
|
1969
1969
|
new Pt(1, 0, 0, 0)
|
|
1970
1970
|
);
|
|
1971
|
-
return
|
|
1971
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
1972
1972
|
}
|
|
1973
1973
|
/**
|
|
1974
1974
|
* Create a basis spline (NURBS) curve.
|
|
@@ -1982,18 +1982,18 @@ See https://github.com/williamngan/pts for details. */
|
|
|
1982
1982
|
if (_pts.length < 2)
|
|
1983
1983
|
return new Group();
|
|
1984
1984
|
let ps = new Group();
|
|
1985
|
-
let ts =
|
|
1985
|
+
let ts = _Curve.getSteps(steps);
|
|
1986
1986
|
let k = 0;
|
|
1987
1987
|
while (k < _pts.length - 3) {
|
|
1988
|
-
let c =
|
|
1988
|
+
let c = _Curve.controlPoints(_pts, k);
|
|
1989
1989
|
if (c.length > 0) {
|
|
1990
1990
|
if (tension !== 1) {
|
|
1991
1991
|
for (let i = 0; i <= steps; i++) {
|
|
1992
|
-
ps.push(
|
|
1992
|
+
ps.push(_Curve.bsplineTensionStep(ts[i], c, tension));
|
|
1993
1993
|
}
|
|
1994
1994
|
} else {
|
|
1995
1995
|
for (let i = 0; i <= steps; i++) {
|
|
1996
|
-
ps.push(
|
|
1996
|
+
ps.push(_Curve.bsplineStep(ts[i], c));
|
|
1997
1997
|
}
|
|
1998
1998
|
}
|
|
1999
1999
|
k++;
|
|
@@ -2014,7 +2014,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2014
2014
|
new Pt(-0.5, 0.5, 0.5, 0.16666666666666666),
|
|
2015
2015
|
new Pt(0.16666666666666666, 0, 0, 0)
|
|
2016
2016
|
);
|
|
2017
|
-
return
|
|
2017
|
+
return _Curve._calcPt(ctrls, Mat.multiply([step], m, true)[0]);
|
|
2018
2018
|
}
|
|
2019
2019
|
/**
|
|
2020
2020
|
* Interpolate to get a point on a basis spline curve with tension.
|
|
@@ -2033,7 +2033,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2033
2033
|
let h = Mat.multiply([step], m, true)[0].multiply(tension);
|
|
2034
2034
|
let h2 = 2 * step[0] - 3 * step[1] + 1;
|
|
2035
2035
|
let h3 = -2 * step[0] + 3 * step[1];
|
|
2036
|
-
let pt =
|
|
2036
|
+
let pt = _Curve._calcPt(ctrls, h);
|
|
2037
2037
|
pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;
|
|
2038
2038
|
pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;
|
|
2039
2039
|
if (pt.length > 2)
|
|
@@ -2044,13 +2044,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2044
2044
|
|
|
2045
2045
|
// src/uheprng.ts
|
|
2046
2046
|
function Mash() {
|
|
2047
|
-
|
|
2048
|
-
|
|
2047
|
+
let n = 4022871197;
|
|
2048
|
+
let mash = function(data) {
|
|
2049
2049
|
if (data) {
|
|
2050
2050
|
data = data.toString();
|
|
2051
|
-
for (
|
|
2051
|
+
for (let i = 0; i < data.length; i++) {
|
|
2052
2052
|
n += data.charCodeAt(i);
|
|
2053
|
-
|
|
2053
|
+
let h = 0.02519603282416938 * n;
|
|
2054
2054
|
n = h >>> 0;
|
|
2055
2055
|
h -= n;
|
|
2056
2056
|
h *= n;
|
|
@@ -2065,12 +2065,12 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2065
2065
|
return mash;
|
|
2066
2066
|
}
|
|
2067
2067
|
function uheprng_default(seed) {
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2068
|
+
let o = 48;
|
|
2069
|
+
let c = 1;
|
|
2070
|
+
let p = o;
|
|
2071
|
+
let s = new Array(o);
|
|
2072
|
+
let i, j, k = 0;
|
|
2073
|
+
let mash = Mash();
|
|
2074
2074
|
for (i = 0; i < o; i++)
|
|
2075
2075
|
s[i] = mash(Math.random().toString());
|
|
2076
2076
|
function initState() {
|
|
@@ -2102,24 +2102,24 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2102
2102
|
hashString(seed);
|
|
2103
2103
|
return {
|
|
2104
2104
|
/**
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2105
|
+
* this (not anymore) PRIVATE (internal access only) function is the heart of the multiply-with-carry
|
|
2106
|
+
* (MWC) PRNG algorithm. When called it returns a pseudo-random number in the form of a
|
|
2107
|
+
* 32-bit JavaScript fraction (0.0 to <1.0) it is a PRIVATE function used by the default
|
|
2108
|
+
* [0-1] return function, and by the random 'string(n)' function which returns 'n'
|
|
2109
|
+
* characters from 33 to 126.
|
|
2110
|
+
* @returns a number between 0.0 and 1.0
|
|
2111
|
+
*/
|
|
2112
2112
|
random() {
|
|
2113
2113
|
if (++p >= o)
|
|
2114
2114
|
p = 0;
|
|
2115
|
-
|
|
2115
|
+
let t = 1768863 * s[p] + c * 23283064365386963e-26;
|
|
2116
2116
|
return s[p] = t - (c = t | 0);
|
|
2117
2117
|
}
|
|
2118
2118
|
};
|
|
2119
2119
|
}
|
|
2120
2120
|
|
|
2121
2121
|
// src/Num.ts
|
|
2122
|
-
var Num = class {
|
|
2122
|
+
var Num = class _Num {
|
|
2123
2123
|
/**
|
|
2124
2124
|
* Check if two numbers are equal or almost equal within a threshold.
|
|
2125
2125
|
* @param a number a
|
|
@@ -2155,7 +2155,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2155
2155
|
* @example `boundValue(361, 0, 360)` will return 1
|
|
2156
2156
|
*/
|
|
2157
2157
|
static boundValue(val, min, max) {
|
|
2158
|
-
|
|
2158
|
+
const len = Math.abs(max - min);
|
|
2159
2159
|
let a = val % len;
|
|
2160
2160
|
if (a > max)
|
|
2161
2161
|
a -= len;
|
|
@@ -2178,8 +2178,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2178
2178
|
* @param b range value 2
|
|
2179
2179
|
*/
|
|
2180
2180
|
static randomRange(a, b = 0) {
|
|
2181
|
-
|
|
2182
|
-
return a +
|
|
2181
|
+
const r = a > b ? a - b : b - a;
|
|
2182
|
+
return a + _Num.random() * r;
|
|
2183
2183
|
}
|
|
2184
2184
|
/**
|
|
2185
2185
|
* Get a random Pt within the range defined by either 1 or 2 Pt
|
|
@@ -2187,11 +2187,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2187
2187
|
* @param b optional Pt to define the end of the range
|
|
2188
2188
|
*/
|
|
2189
2189
|
static randomPt(a, b) {
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2190
|
+
const p = new Pt(a.length);
|
|
2191
|
+
const range = b ? Vec.subtract(b.slice(), a) : a;
|
|
2192
|
+
const start = b ? a : new Pt(a.length).fill(0);
|
|
2193
2193
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
2194
|
-
p[i] =
|
|
2194
|
+
p[i] = _Num.random() * range[i] + start[i];
|
|
2195
2195
|
}
|
|
2196
2196
|
return p;
|
|
2197
2197
|
}
|
|
@@ -2202,8 +2202,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2202
2202
|
* @param b range value 1
|
|
2203
2203
|
*/
|
|
2204
2204
|
static normalizeValue(n, a, b) {
|
|
2205
|
-
|
|
2206
|
-
|
|
2205
|
+
const min = Math.min(a, b);
|
|
2206
|
+
const max = Math.max(a, b);
|
|
2207
2207
|
return (n - min) / (max - min);
|
|
2208
2208
|
}
|
|
2209
2209
|
/**
|
|
@@ -2212,8 +2212,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2212
2212
|
* @returns a Pt of the dimensional sums
|
|
2213
2213
|
*/
|
|
2214
2214
|
static sum(pts) {
|
|
2215
|
-
|
|
2216
|
-
|
|
2215
|
+
const _pts = Util.iterToArray(pts);
|
|
2216
|
+
const c = new Pt(_pts[0]);
|
|
2217
2217
|
for (let i = 1, len = _pts.length; i < len; i++) {
|
|
2218
2218
|
Vec.add(c, _pts[i]);
|
|
2219
2219
|
}
|
|
@@ -2225,8 +2225,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2225
2225
|
* @returns a Pt of averages
|
|
2226
2226
|
*/
|
|
2227
2227
|
static average(pts) {
|
|
2228
|
-
|
|
2229
|
-
return
|
|
2228
|
+
const _pts = Util.iterToArray(pts);
|
|
2229
|
+
return _Num.sum(_pts).divide(_pts.length);
|
|
2230
2230
|
}
|
|
2231
2231
|
/**
|
|
2232
2232
|
* Given a value between 0 to 1, returns a value that cycles between 0 -> 1 -> 0 using the provided shaping method.
|
|
@@ -2249,9 +2249,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2249
2249
|
static mapToRange(n, currA, currB, targetA, targetB) {
|
|
2250
2250
|
if (currA == currB)
|
|
2251
2251
|
throw new Error("[currMin, currMax] must define a range that is not zero");
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
return
|
|
2252
|
+
const min = Math.min(targetA, targetB);
|
|
2253
|
+
const max = Math.max(targetA, targetB);
|
|
2254
|
+
return _Num.normalizeValue(n, currA, currB) * (max - min) + min;
|
|
2255
2255
|
}
|
|
2256
2256
|
/**
|
|
2257
2257
|
* Seed the pseudorandom generator.
|
|
@@ -2269,7 +2269,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2269
2269
|
return this.generator ? this.generator.random() : Math.random();
|
|
2270
2270
|
}
|
|
2271
2271
|
};
|
|
2272
|
-
var Geom = class {
|
|
2272
|
+
var Geom = class _Geom {
|
|
2273
2273
|
/**
|
|
2274
2274
|
* Bound an angle between 0 to 360 degrees.
|
|
2275
2275
|
* @param angle angle value
|
|
@@ -2305,7 +2305,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2305
2305
|
*/
|
|
2306
2306
|
static boundingBox(pts) {
|
|
2307
2307
|
let minPt, maxPt;
|
|
2308
|
-
for (
|
|
2308
|
+
for (const p of pts) {
|
|
2309
2309
|
if (minPt == void 0) {
|
|
2310
2310
|
minPt = p.clone();
|
|
2311
2311
|
maxPt = p.clone();
|
|
@@ -2331,9 +2331,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2331
2331
|
* @param direction a string either "to" (subtract all Pt with this anchor base), or "from" (add all Pt from this anchor base)
|
|
2332
2332
|
*/
|
|
2333
2333
|
static anchor(pts, ptOrIndex = 0, direction = "to") {
|
|
2334
|
-
|
|
2334
|
+
const method = direction == "to" ? "subtract" : "add";
|
|
2335
2335
|
let i = 0;
|
|
2336
|
-
for (
|
|
2336
|
+
for (const p of pts) {
|
|
2337
2337
|
if (typeof ptOrIndex == "number") {
|
|
2338
2338
|
if (ptOrIndex !== i)
|
|
2339
2339
|
p[method](pts[ptOrIndex]);
|
|
@@ -2351,8 +2351,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2351
2351
|
* @returns interpolated point as a new Pt
|
|
2352
2352
|
*/
|
|
2353
2353
|
static interpolate(a, b, t = 0.5) {
|
|
2354
|
-
|
|
2355
|
-
|
|
2354
|
+
const len = Math.min(a.length, b.length);
|
|
2355
|
+
const d = Pt.make(len);
|
|
2356
2356
|
for (let i = 0; i < len; i++) {
|
|
2357
2357
|
d[i] = a[i] * (1 - t) + b[i] * t;
|
|
2358
2358
|
}
|
|
@@ -2364,13 +2364,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2364
2364
|
* @returns an array of two Pt that are perpendicular to this Pt
|
|
2365
2365
|
*/
|
|
2366
2366
|
static perpendicular(pt, axis = Const.xy) {
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2367
|
+
const y = axis[1];
|
|
2368
|
+
const x = axis[0];
|
|
2369
|
+
const p = new Pt(pt);
|
|
2370
|
+
const pa = new Pt(p);
|
|
2371
2371
|
pa[x] = -p[y];
|
|
2372
2372
|
pa[y] = p[x];
|
|
2373
|
-
|
|
2373
|
+
const pb = new Pt(p);
|
|
2374
2374
|
pb[x] = p[y];
|
|
2375
2375
|
pb[y] = -p[x];
|
|
2376
2376
|
return new Group(pa, pb);
|
|
@@ -2399,14 +2399,14 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2399
2399
|
* @param pts a Group or an Iterable<Pt>
|
|
2400
2400
|
*/
|
|
2401
2401
|
static sortEdges(pts) {
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2402
|
+
const _pts = Util.iterToArray(pts);
|
|
2403
|
+
const bounds = _Geom.boundingBox(_pts);
|
|
2404
|
+
const center = bounds[1].add(bounds[0]).divide(2);
|
|
2405
|
+
const fn = (a, b) => {
|
|
2406
2406
|
if (a.length < 2 || b.length < 2)
|
|
2407
2407
|
throw new Error("Pt dimension cannot be less than 2");
|
|
2408
|
-
|
|
2409
|
-
|
|
2408
|
+
const da = a.$subtract(center);
|
|
2409
|
+
const db = b.$subtract(center);
|
|
2410
2410
|
if (da[0] >= 0 && db[0] < 0)
|
|
2411
2411
|
return 1;
|
|
2412
2412
|
if (da[0] < 0 && db[0] >= 0)
|
|
@@ -2416,7 +2416,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2416
2416
|
return da[1] > db[1] ? 1 : -1;
|
|
2417
2417
|
return db[1] > da[1] ? 1 : -1;
|
|
2418
2418
|
}
|
|
2419
|
-
|
|
2419
|
+
const det = da.$cross2D(db);
|
|
2420
2420
|
if (det < 0)
|
|
2421
2421
|
return 1;
|
|
2422
2422
|
if (det > 0)
|
|
@@ -2432,17 +2432,17 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2432
2432
|
* @param anchor optional anchor point to scale from
|
|
2433
2433
|
*/
|
|
2434
2434
|
static scale(ps, scale, anchor) {
|
|
2435
|
-
|
|
2436
|
-
|
|
2435
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2436
|
+
const scs = typeof scale == "number" ? Pt.make(pts[0].length, scale) : scale;
|
|
2437
2437
|
if (!anchor)
|
|
2438
2438
|
anchor = Pt.make(pts[0].length, 0);
|
|
2439
2439
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2440
|
-
|
|
2440
|
+
const p = pts[i];
|
|
2441
2441
|
for (let k = 0, lenP = p.length; k < lenP; k++) {
|
|
2442
2442
|
p[k] = anchor && anchor[k] ? anchor[k] + (p[k] - anchor[k]) * scs[k] : p[k] * scs[k];
|
|
2443
2443
|
}
|
|
2444
2444
|
}
|
|
2445
|
-
return
|
|
2445
|
+
return _Geom;
|
|
2446
2446
|
}
|
|
2447
2447
|
/**
|
|
2448
2448
|
* Rotate a Pt or a Group of Pts in 2D space. You may also use [`Pt.rotate2D`](#link) instance method.
|
|
@@ -2452,14 +2452,14 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2452
2452
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2453
2453
|
*/
|
|
2454
2454
|
static rotate2D(ps, angle, anchor, axis) {
|
|
2455
|
-
|
|
2456
|
-
|
|
2455
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2456
|
+
const fn = anchor ? Mat.rotateAt2DMatrix : Mat.rotate2DMatrix;
|
|
2457
2457
|
if (!anchor)
|
|
2458
2458
|
anchor = Pt.make(pts[0].length, 0);
|
|
2459
|
-
|
|
2460
|
-
|
|
2459
|
+
const cos = Math.cos(angle);
|
|
2460
|
+
const sin = Math.sin(angle);
|
|
2461
2461
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2462
|
-
|
|
2462
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2463
2463
|
p.to(Mat.transform2D(p, fn(cos, sin, anchor)));
|
|
2464
2464
|
if (axis) {
|
|
2465
2465
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2467,7 +2467,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2467
2467
|
}
|
|
2468
2468
|
}
|
|
2469
2469
|
}
|
|
2470
|
-
return
|
|
2470
|
+
return _Geom;
|
|
2471
2471
|
}
|
|
2472
2472
|
/**
|
|
2473
2473
|
* Shear a Pt or a Group of Pts in 2D space. You may also use [`Pt.shear2D`](#link) instance method.
|
|
@@ -2477,15 +2477,15 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2477
2477
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2478
2478
|
*/
|
|
2479
2479
|
static shear2D(ps, scale, anchor, axis) {
|
|
2480
|
-
|
|
2481
|
-
|
|
2480
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2481
|
+
const s = typeof scale == "number" ? [scale, scale] : scale;
|
|
2482
2482
|
if (!anchor)
|
|
2483
2483
|
anchor = Pt.make(pts[0].length, 0);
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2484
|
+
const fn = anchor ? Mat.shearAt2DMatrix : Mat.shear2DMatrix;
|
|
2485
|
+
const tanx = Math.tan(s[0]);
|
|
2486
|
+
const tany = Math.tan(s[1]);
|
|
2487
2487
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2488
|
-
|
|
2488
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2489
2489
|
p.to(Mat.transform2D(p, fn(tanx, tany, anchor)));
|
|
2490
2490
|
if (axis) {
|
|
2491
2491
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2493,7 +2493,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2493
2493
|
}
|
|
2494
2494
|
}
|
|
2495
2495
|
}
|
|
2496
|
-
return
|
|
2496
|
+
return _Geom;
|
|
2497
2497
|
}
|
|
2498
2498
|
/**
|
|
2499
2499
|
* Reflect a Pt or a Group of Pts along a 2D line. You may also use [`Pt.reflect2D`](#link) instance method.
|
|
@@ -2502,11 +2502,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2502
2502
|
* @param axis optional axis such as "xy" (use Const.xy) to define a 2D plane, or a number array to specify indices
|
|
2503
2503
|
*/
|
|
2504
2504
|
static reflect2D(ps, line, axis) {
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2505
|
+
const pts = Util.iterToArray(ps[0] !== void 0 && typeof ps[0] == "number" ? [ps] : ps);
|
|
2506
|
+
const _line = Util.iterToArray(line);
|
|
2507
|
+
const mat = Mat.reflectAt2DMatrix(_line[0], _line[1]);
|
|
2508
2508
|
for (let i = 0, len = pts.length; i < len; i++) {
|
|
2509
|
-
|
|
2509
|
+
const p = axis ? pts[i].$take(axis) : pts[i];
|
|
2510
2510
|
p.to(Mat.transform2D(p, mat));
|
|
2511
2511
|
if (axis) {
|
|
2512
2512
|
for (let k = 0; k < axis.length; k++) {
|
|
@@ -2514,17 +2514,17 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2514
2514
|
}
|
|
2515
2515
|
}
|
|
2516
2516
|
}
|
|
2517
|
-
return
|
|
2517
|
+
return _Geom;
|
|
2518
2518
|
}
|
|
2519
2519
|
/**
|
|
2520
2520
|
* Generate a cosine lookup table.
|
|
2521
2521
|
* @returns an object with a cosine tables (array of 360 values) and a function to get cosine given a radian input.
|
|
2522
2522
|
*/
|
|
2523
2523
|
static cosTable() {
|
|
2524
|
-
|
|
2524
|
+
const cos = new Float64Array(360);
|
|
2525
2525
|
for (let i = 0; i < 360; i++)
|
|
2526
2526
|
cos[i] = Math.cos(i * Math.PI / 180);
|
|
2527
|
-
|
|
2527
|
+
const find = (rad) => cos[Math.floor(_Geom.boundAngle(_Geom.toDegree(rad)))];
|
|
2528
2528
|
return { table: cos, cos: find };
|
|
2529
2529
|
}
|
|
2530
2530
|
/**
|
|
@@ -2532,14 +2532,14 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2532
2532
|
* @returns an object with a sine tables (array of 360 values) and a function to get sine value given a radian input.
|
|
2533
2533
|
*/
|
|
2534
2534
|
static sinTable() {
|
|
2535
|
-
|
|
2535
|
+
const sin = new Float64Array(360);
|
|
2536
2536
|
for (let i = 0; i < 360; i++)
|
|
2537
2537
|
sin[i] = Math.sin(i * Math.PI / 180);
|
|
2538
|
-
|
|
2538
|
+
const find = (rad) => sin[Math.floor(_Geom.boundAngle(_Geom.toDegree(rad)))];
|
|
2539
2539
|
return { table: sin, sin: find };
|
|
2540
2540
|
}
|
|
2541
2541
|
};
|
|
2542
|
-
var Shaping = class {
|
|
2542
|
+
var Shaping = class _Shaping {
|
|
2543
2543
|
/**
|
|
2544
2544
|
* Linear mapping.
|
|
2545
2545
|
* @param t a value between 0 to 1
|
|
@@ -2570,7 +2570,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2570
2570
|
* @param c the value to shape, default is 1
|
|
2571
2571
|
*/
|
|
2572
2572
|
static quadraticInOut(t, c = 1) {
|
|
2573
|
-
|
|
2573
|
+
const dt = t * 2;
|
|
2574
2574
|
return t < 0.5 ? c / 2 * t * t * 4 : -c / 2 * ((dt - 1) * (dt - 3) - 1);
|
|
2575
2575
|
}
|
|
2576
2576
|
/**
|
|
@@ -2587,7 +2587,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2587
2587
|
* @param c the value to shape, default is 1
|
|
2588
2588
|
*/
|
|
2589
2589
|
static cubicOut(t, c = 1) {
|
|
2590
|
-
|
|
2590
|
+
const dt = t - 1;
|
|
2591
2591
|
return c * (dt * dt * dt + 1);
|
|
2592
2592
|
}
|
|
2593
2593
|
/**
|
|
@@ -2596,7 +2596,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2596
2596
|
* @param c the value to shape, default is 1
|
|
2597
2597
|
*/
|
|
2598
2598
|
static cubicInOut(t, c = 1) {
|
|
2599
|
-
|
|
2599
|
+
const dt = t * 2;
|
|
2600
2600
|
return t < 0.5 ? c / 2 * dt * dt * dt : c / 2 * ((dt - 2) * (dt - 2) * (dt - 2) + 2);
|
|
2601
2601
|
}
|
|
2602
2602
|
/**
|
|
@@ -2647,9 +2647,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2647
2647
|
* @param c the value to shape, default is 1
|
|
2648
2648
|
*/
|
|
2649
2649
|
static cosineApprox(t, c = 1) {
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2650
|
+
const t2 = t * t;
|
|
2651
|
+
const t4 = t2 * t2;
|
|
2652
|
+
const t6 = t4 * t2;
|
|
2653
2653
|
return c * (4 * t6 / 9 - 17 * t4 / 9 + 22 * t2 / 9);
|
|
2654
2654
|
}
|
|
2655
2655
|
/**
|
|
@@ -2666,7 +2666,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2666
2666
|
* @param c the value to shape, default is 1
|
|
2667
2667
|
*/
|
|
2668
2668
|
static circularOut(t, c = 1) {
|
|
2669
|
-
|
|
2669
|
+
const dt = t - 1;
|
|
2670
2670
|
return c * Math.sqrt(1 - dt * dt);
|
|
2671
2671
|
}
|
|
2672
2672
|
/**
|
|
@@ -2675,7 +2675,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2675
2675
|
* @param c the value to shape, default is 1
|
|
2676
2676
|
*/
|
|
2677
2677
|
static circularInOut(t, c = 1) {
|
|
2678
|
-
|
|
2678
|
+
const dt = t * 2;
|
|
2679
2679
|
return t < 0.5 ? -c / 2 * (Math.sqrt(1 - dt * dt) - 1) : c / 2 * (Math.sqrt(1 - (dt - 2) * (dt - 2)) + 1);
|
|
2680
2680
|
}
|
|
2681
2681
|
/**
|
|
@@ -2685,8 +2685,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2685
2685
|
* @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.
|
|
2686
2686
|
*/
|
|
2687
2687
|
static elasticIn(t, c = 1, p = 0.7) {
|
|
2688
|
-
|
|
2689
|
-
|
|
2688
|
+
const dt = t - 1;
|
|
2689
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2690
2690
|
return c * (-Math.pow(2, 10 * dt) * Math.sin((dt - s) * Const.two_pi / p));
|
|
2691
2691
|
}
|
|
2692
2692
|
/**
|
|
@@ -2696,7 +2696,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2696
2696
|
* @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.
|
|
2697
2697
|
*/
|
|
2698
2698
|
static elasticOut(t, c = 1, p = 0.7) {
|
|
2699
|
-
|
|
2699
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2700
2700
|
return c * (Math.pow(2, -10 * t) * Math.sin((t - s) * Const.two_pi / p)) + c;
|
|
2701
2701
|
}
|
|
2702
2702
|
/**
|
|
@@ -2707,7 +2707,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2707
2707
|
*/
|
|
2708
2708
|
static elasticInOut(t, c = 1, p = 0.6) {
|
|
2709
2709
|
let dt = t * 2;
|
|
2710
|
-
|
|
2710
|
+
const s = p / Const.two_pi * 1.5707963267948966;
|
|
2711
2711
|
if (t < 0.5) {
|
|
2712
2712
|
dt -= 1;
|
|
2713
2713
|
return c * (-0.5 * (Math.pow(2, 10 * dt) * Math.sin((dt - s) * Const.two_pi / p)));
|
|
@@ -2722,7 +2722,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2722
2722
|
* @param c the value to shape, default is 1
|
|
2723
2723
|
*/
|
|
2724
2724
|
static bounceIn(t, c = 1) {
|
|
2725
|
-
return c -
|
|
2725
|
+
return c - _Shaping.bounceOut(1 - t, c);
|
|
2726
2726
|
}
|
|
2727
2727
|
/**
|
|
2728
2728
|
* Bounce out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).
|
|
@@ -2749,7 +2749,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2749
2749
|
* @param c the value to shape, default is 1
|
|
2750
2750
|
*/
|
|
2751
2751
|
static bounceInOut(t, c = 1) {
|
|
2752
|
-
return t < 0.5 ?
|
|
2752
|
+
return t < 0.5 ? _Shaping.bounceIn(t * 2, c) / 2 : _Shaping.bounceOut(t * 2 - 1, c) / 2 + c / 2;
|
|
2753
2753
|
}
|
|
2754
2754
|
/**
|
|
2755
2755
|
* Sigmoid curve changes its shape adapted from the input value, but always returns a value between 0 to 1.
|
|
@@ -2758,7 +2758,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2758
2758
|
* @param p the larger the value, the "steeper" the curve will be. Default is 10.
|
|
2759
2759
|
*/
|
|
2760
2760
|
static sigmoid(t, c = 1, p = 10) {
|
|
2761
|
-
|
|
2761
|
+
const d = p * (t - 0.5);
|
|
2762
2762
|
return c / (1 + Math.exp(-d));
|
|
2763
2763
|
}
|
|
2764
2764
|
/**
|
|
@@ -2770,9 +2770,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2770
2770
|
static logSigmoid(t, c = 1, p = 0.7) {
|
|
2771
2771
|
p = Math.max(Const.epsilon, Math.min(1 - Const.epsilon, p));
|
|
2772
2772
|
p = 1 / (1 - p);
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2773
|
+
const A = 1 / (1 + Math.exp((t - 0.5) * p * -2));
|
|
2774
|
+
const B = 1 / (1 + Math.exp(p));
|
|
2775
|
+
const C = 1 / (1 + Math.exp(-p));
|
|
2776
2776
|
return c * (A - B) / (C - B);
|
|
2777
2777
|
}
|
|
2778
2778
|
/**
|
|
@@ -2795,13 +2795,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2795
2795
|
* @param p1 a Pt object specifying the first control Pt, or a value specifying the control Pt's x position (its y position will default to 0.5). Default is `Pt(0.95, 0.95)
|
|
2796
2796
|
*/
|
|
2797
2797
|
static quadraticBezier(t, c = 1, p = [0.05, 0.95]) {
|
|
2798
|
-
|
|
2799
|
-
|
|
2798
|
+
const a = typeof p != "number" ? p[0] : p;
|
|
2799
|
+
const b = typeof p != "number" ? p[1] : 0.5;
|
|
2800
2800
|
let om2a = 1 - 2 * a;
|
|
2801
2801
|
if (om2a === 0) {
|
|
2802
2802
|
om2a = Const.epsilon;
|
|
2803
2803
|
}
|
|
2804
|
-
|
|
2804
|
+
const d = (Math.sqrt(a * a + om2a * t) - a) / om2a;
|
|
2805
2805
|
return c * ((1 - 2 * b) * (d * d) + 2 * b * d);
|
|
2806
2806
|
}
|
|
2807
2807
|
/**
|
|
@@ -2812,7 +2812,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2812
2812
|
* @param p2` a Pt object specifying the second control Pt. Default is `Pt(0.9, 0.2).
|
|
2813
2813
|
*/
|
|
2814
2814
|
static cubicBezier(t, c = 1, p1 = [0.1, 0.7], p2 = [0.9, 0.2]) {
|
|
2815
|
-
|
|
2815
|
+
const curve = new Group(new Pt(0, 0), new Pt(p1), new Pt(p2), new Pt(1, 1));
|
|
2816
2816
|
return c * Curve.bezierStep(new Pt(t * t * t, t * t, t, 1), Curve.controlPoints(curve)).y;
|
|
2817
2817
|
}
|
|
2818
2818
|
/**
|
|
@@ -2822,11 +2822,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2822
2822
|
* @param p1` a Pt object specifying the Pt to pass through. Default is `Pt(0.2, 0.35)
|
|
2823
2823
|
*/
|
|
2824
2824
|
static quadraticTarget(t, c = 1, p1 = [0.2, 0.35]) {
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2825
|
+
const a = Math.min(1 - Const.epsilon, Math.max(Const.epsilon, p1[0]));
|
|
2826
|
+
const b = Math.min(1, Math.max(0, p1[1]));
|
|
2827
|
+
const A = (1 - b) / (1 - a) - b / a;
|
|
2828
|
+
const B = (A * (a * a) - b) / a;
|
|
2829
|
+
const y = A * (t * t) - B * t;
|
|
2830
2830
|
return c * Math.min(1, Math.max(0, y));
|
|
2831
2831
|
}
|
|
2832
2832
|
/**
|
|
@@ -2847,8 +2847,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2847
2847
|
* @param args optional paramters to pass to original function
|
|
2848
2848
|
*/
|
|
2849
2849
|
static step(fn, steps, t, c, ...args) {
|
|
2850
|
-
|
|
2851
|
-
|
|
2850
|
+
const s = 1 / steps;
|
|
2851
|
+
const tt = Math.floor(t / s) * s;
|
|
2852
2852
|
return fn(tt, c, ...args);
|
|
2853
2853
|
}
|
|
2854
2854
|
};
|
|
@@ -2886,16 +2886,16 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2886
2886
|
calc() {
|
|
2887
2887
|
if (!this._source)
|
|
2888
2888
|
return;
|
|
2889
|
-
|
|
2889
|
+
const dims = this._source[0].length;
|
|
2890
2890
|
this._dims = dims;
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2891
|
+
const max = new Pt(dims);
|
|
2892
|
+
const min = new Pt(dims);
|
|
2893
|
+
const mag = new Pt(dims);
|
|
2894
2894
|
for (let i = 0; i < dims; i++) {
|
|
2895
2895
|
max[i] = Const.min;
|
|
2896
2896
|
min[i] = Const.max;
|
|
2897
2897
|
mag[i] = 0;
|
|
2898
|
-
|
|
2898
|
+
const s = this._source.zipSlice(i);
|
|
2899
2899
|
for (let k = 0, len = s.length; k < len; k++) {
|
|
2900
2900
|
max[i] = Math.max(max[i], s[k]);
|
|
2901
2901
|
min[i] = Math.min(min[i], s[k]);
|
|
@@ -2914,10 +2914,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2914
2914
|
* @param exclude Optional boolean array where `true` means excluding the conversion in that specific dimension.
|
|
2915
2915
|
*/
|
|
2916
2916
|
mapTo(min, max, exclude) {
|
|
2917
|
-
|
|
2917
|
+
const target = new Group();
|
|
2918
2918
|
for (let i = 0, len = this._source.length; i < len; i++) {
|
|
2919
|
-
|
|
2920
|
-
|
|
2919
|
+
const g = this._source[i];
|
|
2920
|
+
const n = new Pt(this._dims);
|
|
2921
2921
|
for (let k = 0; k < this._dims; k++) {
|
|
2922
2922
|
n[k] = exclude && exclude[k] ? g[k] : Num.mapToRange(g[k], this._min[k], this._max[k], min, max);
|
|
2923
2923
|
}
|
|
@@ -2931,7 +2931,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2931
2931
|
* @param update Optional. Set the parameter to `false` if you want to append without immediately updating this Range's min and max values. Default is `true`.
|
|
2932
2932
|
*/
|
|
2933
2933
|
append(pts, update = true) {
|
|
2934
|
-
|
|
2934
|
+
const _pts = Util.iterToArray(pts);
|
|
2935
2935
|
if (_pts[0].length !== this._dims)
|
|
2936
2936
|
throw new Error(`Dimensions don't match. ${this._dims} dimensions in Range and ${_pts[0].length} provided in parameter. `);
|
|
2937
2937
|
this._source = this._source.concat(_pts);
|
|
@@ -2944,9 +2944,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
2944
2944
|
* @param count number of subdivision. For example, 10 subdivision will return 11 tick values, which include first(min) and last(max) values.
|
|
2945
2945
|
*/
|
|
2946
2946
|
ticks(count) {
|
|
2947
|
-
|
|
2947
|
+
const g = new Group();
|
|
2948
2948
|
for (let i = 0; i <= count; i++) {
|
|
2949
|
-
|
|
2949
|
+
const p = new Pt(this._dims);
|
|
2950
2950
|
for (let k = 0, len = this._max.length; k < len; k++) {
|
|
2951
2951
|
p[k] = Num.lerp(this._min[k], this._max[k], i / count);
|
|
2952
2952
|
}
|
|
@@ -3015,7 +3015,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3015
3015
|
/** Gaussian constant (1 / Math.sqrt(2 * Math.PI)) */
|
|
3016
3016
|
gaussian: 0.3989422804014327
|
|
3017
3017
|
};
|
|
3018
|
-
var _Util = class {
|
|
3018
|
+
var _Util = class _Util {
|
|
3019
3019
|
/**
|
|
3020
3020
|
* Set a global warning level setting. If no parameter is passed, this will return the current warn-level. See [`Util.warn`](#link).
|
|
3021
3021
|
* @param lv a [`WarningType`](#link) option, where "error" will throw an error, "warn" will log in console, and "mute" will ignore the error.
|
|
@@ -3110,7 +3110,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3110
3110
|
* @param flattenAsGroup a boolean to specify whether the return type should be a Group or Array. Default is `true` which returns a Group.
|
|
3111
3111
|
*/
|
|
3112
3112
|
static flatten(pts, flattenAsGroup = true) {
|
|
3113
|
-
let arr = flattenAsGroup ? new Group() :
|
|
3113
|
+
let arr = flattenAsGroup ? new Group() : [];
|
|
3114
3114
|
return arr.concat.apply(arr, pts);
|
|
3115
3115
|
}
|
|
3116
3116
|
/**
|
|
@@ -3183,7 +3183,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3183
3183
|
* @param callback a function to capture the data. It receives two parameters: a `response` as string, and a `success` status as boolean.
|
|
3184
3184
|
*/
|
|
3185
3185
|
static load(url, callback) {
|
|
3186
|
-
|
|
3186
|
+
let request = new XMLHttpRequest();
|
|
3187
3187
|
request.open("GET", url, true);
|
|
3188
3188
|
request.onload = function() {
|
|
3189
3189
|
if (request.status >= 200 && request.status < 400) {
|
|
@@ -3261,11 +3261,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3261
3261
|
return /iPhone|iPad|Android/i.test(navigator.userAgent);
|
|
3262
3262
|
}
|
|
3263
3263
|
};
|
|
3264
|
+
_Util._warnLevel = "mute";
|
|
3264
3265
|
var Util = _Util;
|
|
3265
|
-
Util._warnLevel = "mute";
|
|
3266
3266
|
|
|
3267
3267
|
// src/Pt.ts
|
|
3268
|
-
var Pt = class extends Float32Array {
|
|
3268
|
+
var Pt = class _Pt extends Float32Array {
|
|
3269
3269
|
/**
|
|
3270
3270
|
* Create a Pt. If no parameter is provided, this will instantiate a Pt with 2 dimensions [0, 0].
|
|
3271
3271
|
* Note that `new Pt(3)` will only instantiate Pt with length of 3 (ie, same as `new Float32Array(3)` ). If you need a Pt with 1 dimension of value 3, use `new Pt([3])`.
|
|
@@ -3288,7 +3288,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3288
3288
|
* @param randomize if `true`, randomize the value between 0 to default value
|
|
3289
3289
|
*/
|
|
3290
3290
|
static make(dimensions, defaultValue = 0, randomize = false) {
|
|
3291
|
-
|
|
3291
|
+
const p = new Float32Array(dimensions);
|
|
3292
3292
|
if (defaultValue)
|
|
3293
3293
|
p.fill(defaultValue);
|
|
3294
3294
|
if (randomize) {
|
|
@@ -3296,7 +3296,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3296
3296
|
p[i] = p[i] * Num.random();
|
|
3297
3297
|
}
|
|
3298
3298
|
}
|
|
3299
|
-
return new
|
|
3299
|
+
return new _Pt(p);
|
|
3300
3300
|
}
|
|
3301
3301
|
/**
|
|
3302
3302
|
* ID string of this Pt
|
|
@@ -3347,7 +3347,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3347
3347
|
* Clone this Pt and return it as a new Pt.
|
|
3348
3348
|
*/
|
|
3349
3349
|
clone() {
|
|
3350
|
-
return new
|
|
3350
|
+
return new _Pt(this);
|
|
3351
3351
|
}
|
|
3352
3352
|
/**
|
|
3353
3353
|
* Check if another Pt is equal to this Pt, within a threshold.
|
|
@@ -3366,7 +3366,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3366
3366
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3367
3367
|
*/
|
|
3368
3368
|
to(...args) {
|
|
3369
|
-
|
|
3369
|
+
const p = Util.getArgs(args);
|
|
3370
3370
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3371
3371
|
this[i] = p[i];
|
|
3372
3372
|
}
|
|
@@ -3386,8 +3386,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3386
3386
|
* @param anchorFromPt If `true`, add it from this Pt's current position. Default is `false` which update the position from origin (0,0). See also [`Geom.rotate2D`](#link) for rotating a point from another anchor point.
|
|
3387
3387
|
*/
|
|
3388
3388
|
toAngle(radian, magnitude, anchorFromPt = false) {
|
|
3389
|
-
|
|
3390
|
-
|
|
3389
|
+
const m = magnitude != void 0 ? magnitude : this.magnitude();
|
|
3390
|
+
const change = [Math.cos(radian) * m, Math.sin(radian) * m];
|
|
3391
3391
|
return anchorFromPt ? this.add(change) : this.to(change);
|
|
3392
3392
|
}
|
|
3393
3393
|
/**
|
|
@@ -3397,7 +3397,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3397
3397
|
* @returns a resulting function that takes other parameters required in `fn`
|
|
3398
3398
|
*/
|
|
3399
3399
|
op(fn) {
|
|
3400
|
-
|
|
3400
|
+
const self = this;
|
|
3401
3401
|
return (...params) => {
|
|
3402
3402
|
return fn(self, ...params);
|
|
3403
3403
|
};
|
|
@@ -3409,7 +3409,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3409
3409
|
* @returns an array of resulting functions
|
|
3410
3410
|
*/
|
|
3411
3411
|
ops(fns) {
|
|
3412
|
-
|
|
3412
|
+
const _ops = [];
|
|
3413
3413
|
for (let i = 0, len = fns.length; i < len; i++) {
|
|
3414
3414
|
_ops.push(this.op(fns[i]));
|
|
3415
3415
|
}
|
|
@@ -3420,18 +3420,18 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3420
3420
|
* @param axis a string such as "xy" (use Const.xy) or an array to specify indices
|
|
3421
3421
|
*/
|
|
3422
3422
|
$take(axis) {
|
|
3423
|
-
|
|
3423
|
+
const p = [];
|
|
3424
3424
|
for (let i = 0, len = axis.length; i < len; i++) {
|
|
3425
3425
|
p.push(this[axis[i]] || 0);
|
|
3426
3426
|
}
|
|
3427
|
-
return new
|
|
3427
|
+
return new _Pt(p);
|
|
3428
3428
|
}
|
|
3429
3429
|
/**
|
|
3430
3430
|
* Concatenate this Pt with addition dimensional values and return as a new Pt.
|
|
3431
3431
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3432
3432
|
*/
|
|
3433
3433
|
$concat(...args) {
|
|
3434
|
-
return new
|
|
3434
|
+
return new _Pt(this.toArray().concat(Util.getArgs(args)));
|
|
3435
3435
|
}
|
|
3436
3436
|
/**
|
|
3437
3437
|
* Add scalar or vector values to this Pt.
|
|
@@ -3626,8 +3626,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3626
3626
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3627
3627
|
*/
|
|
3628
3628
|
$min(...args) {
|
|
3629
|
-
|
|
3630
|
-
|
|
3629
|
+
const p = Util.getArgs(args);
|
|
3630
|
+
const m = this.clone();
|
|
3631
3631
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3632
3632
|
m[i] = Math.min(this[i], p[i]);
|
|
3633
3633
|
}
|
|
@@ -3638,8 +3638,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3638
3638
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3639
3639
|
*/
|
|
3640
3640
|
$max(...args) {
|
|
3641
|
-
|
|
3642
|
-
|
|
3641
|
+
const p = Util.getArgs(args);
|
|
3642
|
+
const m = this.clone();
|
|
3643
3643
|
for (let i = 0, len = Math.min(this.length, p.length); i < len; i++) {
|
|
3644
3644
|
m[i] = Math.max(this[i], p[i]);
|
|
3645
3645
|
}
|
|
@@ -3666,7 +3666,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3666
3666
|
* @param anchor optional anchor point to scale from
|
|
3667
3667
|
*/
|
|
3668
3668
|
scale(scale, anchor) {
|
|
3669
|
-
Geom.scale(this, scale, anchor ||
|
|
3669
|
+
Geom.scale(this, scale, anchor || _Pt.make(this.length, 0));
|
|
3670
3670
|
return this;
|
|
3671
3671
|
}
|
|
3672
3672
|
/**
|
|
@@ -3676,7 +3676,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3676
3676
|
* @param axis optional string such as "yz" to specify a 2D plane
|
|
3677
3677
|
*/
|
|
3678
3678
|
rotate2D(angle, anchor, axis) {
|
|
3679
|
-
Geom.rotate2D(this, angle, anchor ||
|
|
3679
|
+
Geom.rotate2D(this, angle, anchor || _Pt.make(this.length, 0), axis);
|
|
3680
3680
|
return this;
|
|
3681
3681
|
}
|
|
3682
3682
|
/**
|
|
@@ -3686,7 +3686,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3686
3686
|
* @param axis optional string such as "yz" to specify a 2D plane
|
|
3687
3687
|
*/
|
|
3688
3688
|
shear2D(scale, anchor, axis) {
|
|
3689
|
-
Geom.shear2D(this, scale, anchor ||
|
|
3689
|
+
Geom.shear2D(this, scale, anchor || _Pt.make(this.length, 0), axis);
|
|
3690
3690
|
return this;
|
|
3691
3691
|
}
|
|
3692
3692
|
/**
|
|
@@ -3714,16 +3714,16 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3714
3714
|
* Convert this Pt to a Group as new Group([0,...], pt)
|
|
3715
3715
|
*/
|
|
3716
3716
|
toGroup() {
|
|
3717
|
-
return new Group(
|
|
3717
|
+
return new Group(_Pt.make(this.length), this.clone());
|
|
3718
3718
|
}
|
|
3719
3719
|
/**
|
|
3720
3720
|
* Convert this Pt to a Bound as new Group([0,...], pt)
|
|
3721
3721
|
*/
|
|
3722
3722
|
toBound() {
|
|
3723
|
-
return new Bound(
|
|
3723
|
+
return new Bound(_Pt.make(this.length), this.clone());
|
|
3724
3724
|
}
|
|
3725
3725
|
};
|
|
3726
|
-
var Group = class extends Array {
|
|
3726
|
+
var Group = class _Group extends Array {
|
|
3727
3727
|
/**
|
|
3728
3728
|
* Create a Group by passing an array of [`Pt`](#link). You may also create a Group using [`Group.fromArray`](#link) or [`Group.fromPtArray`](#link).
|
|
3729
3729
|
* @param args an array of Pts
|
|
@@ -3792,7 +3792,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3792
3792
|
* Depp clone this group and its Pts.
|
|
3793
3793
|
*/
|
|
3794
3794
|
clone() {
|
|
3795
|
-
|
|
3795
|
+
const group = new _Group();
|
|
3796
3796
|
for (let i = 0, len = this.length; i < len; i++) {
|
|
3797
3797
|
group.push(this[i].clone());
|
|
3798
3798
|
}
|
|
@@ -3804,9 +3804,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3804
3804
|
* @example `Group.fromArray( [[1,2], [3,4], [5,6]] )`
|
|
3805
3805
|
*/
|
|
3806
3806
|
static fromArray(list) {
|
|
3807
|
-
|
|
3808
|
-
for (
|
|
3809
|
-
|
|
3807
|
+
const g = new _Group();
|
|
3808
|
+
for (const li of list) {
|
|
3809
|
+
const p = li instanceof Pt ? li : new Pt(li);
|
|
3810
3810
|
g.push(p);
|
|
3811
3811
|
}
|
|
3812
3812
|
return g;
|
|
@@ -3816,7 +3816,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3816
3816
|
* @param list an Iterable<Pt>
|
|
3817
3817
|
*/
|
|
3818
3818
|
static fromPtArray(list) {
|
|
3819
|
-
return
|
|
3819
|
+
return _Group.from(list);
|
|
3820
3820
|
}
|
|
3821
3821
|
/**
|
|
3822
3822
|
* Split this Group into an array of sub-groups.
|
|
@@ -3825,7 +3825,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3825
3825
|
* @param loopBack if `true`, always go through the array till the end and loop back to the beginning to complete the segments if needed
|
|
3826
3826
|
*/
|
|
3827
3827
|
split(chunkSize, stride, loopBack = false) {
|
|
3828
|
-
|
|
3828
|
+
const sp = Util.split(this, chunkSize, stride, loopBack);
|
|
3829
3829
|
return sp;
|
|
3830
3830
|
}
|
|
3831
3831
|
/**
|
|
@@ -3834,7 +3834,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3834
3834
|
* @param index the index position to insert into
|
|
3835
3835
|
*/
|
|
3836
3836
|
insert(pts, index = 0) {
|
|
3837
|
-
|
|
3837
|
+
_Group.prototype.splice.apply(this, [index, 0, ...pts]);
|
|
3838
3838
|
return this;
|
|
3839
3839
|
}
|
|
3840
3840
|
/**
|
|
@@ -3844,8 +3844,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3844
3844
|
* @returns The items that are removed.
|
|
3845
3845
|
*/
|
|
3846
3846
|
remove(index = 0, count = 1) {
|
|
3847
|
-
|
|
3848
|
-
return
|
|
3847
|
+
const param = index < 0 ? [index * -1 - 1, count] : [index, count];
|
|
3848
|
+
return _Group.prototype.splice.apply(this, param);
|
|
3849
3849
|
}
|
|
3850
3850
|
/**
|
|
3851
3851
|
* Split this group into an array of sub-group segments.
|
|
@@ -3896,7 +3896,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3896
3896
|
* @returns a resulting function that takes other parameters required in `fn`
|
|
3897
3897
|
*/
|
|
3898
3898
|
op(fn) {
|
|
3899
|
-
|
|
3899
|
+
const self = this;
|
|
3900
3900
|
return (...params) => {
|
|
3901
3901
|
return fn(self, ...params);
|
|
3902
3902
|
};
|
|
@@ -3908,7 +3908,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3908
3908
|
* @returns an array of resulting functions
|
|
3909
3909
|
*/
|
|
3910
3910
|
ops(fns) {
|
|
3911
|
-
|
|
3911
|
+
const _ops = [];
|
|
3912
3912
|
for (let i = 0, len = fns.length; i < len; i++) {
|
|
3913
3913
|
_ops.push(this.op(fns[i]));
|
|
3914
3914
|
}
|
|
@@ -3920,9 +3920,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3920
3920
|
*/
|
|
3921
3921
|
interpolate(t) {
|
|
3922
3922
|
t = Num.clamp(t, 0, 1);
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3923
|
+
const chunk = this.length - 1;
|
|
3924
|
+
const tc = 1 / (this.length - 1);
|
|
3925
|
+
const idx = Math.floor(t / tc);
|
|
3926
3926
|
return Geom.interpolate(this[idx], this[Math.min(this.length - 1, idx + 1)], (t - idx * tc) * chunk);
|
|
3927
3927
|
}
|
|
3928
3928
|
/**
|
|
@@ -3937,7 +3937,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
3937
3937
|
* @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties
|
|
3938
3938
|
*/
|
|
3939
3939
|
moveTo(...args) {
|
|
3940
|
-
|
|
3940
|
+
const d = new Pt(Util.getArgs(args)).subtract(this[0]);
|
|
3941
3941
|
this.moveBy(d);
|
|
3942
3942
|
return this;
|
|
3943
3943
|
}
|
|
@@ -4085,7 +4085,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4085
4085
|
return "Group[ " + this.reduce((p, c) => p + c.toString() + " ", "") + " ]";
|
|
4086
4086
|
}
|
|
4087
4087
|
};
|
|
4088
|
-
var Bound = class extends Group {
|
|
4088
|
+
var Bound = class _Bound extends Group {
|
|
4089
4089
|
/**
|
|
4090
4090
|
* Create a Bound. This is similar to the Group constructor. You can also create a Bound via the static function [`Bound.fromGroup`](#link), or alternatively via the [Group.toBound](#link) function.
|
|
4091
4091
|
* @param args a list of Pt as parameters
|
|
@@ -4106,7 +4106,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4106
4106
|
* @returns a Bound object
|
|
4107
4107
|
*/
|
|
4108
4108
|
static fromBoundingRect(rect) {
|
|
4109
|
-
|
|
4109
|
+
const b = new _Bound(new Pt(rect.left || 0, rect.top || 0), new Pt(rect.right || 0, rect.bottom || 0));
|
|
4110
4110
|
if (rect.width && rect.height)
|
|
4111
4111
|
b.size = new Pt(rect.width, rect.height);
|
|
4112
4112
|
return b;
|
|
@@ -4116,10 +4116,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4116
4116
|
* @param g a Group or an Iterable<PtLike>
|
|
4117
4117
|
*/
|
|
4118
4118
|
static fromGroup(g) {
|
|
4119
|
-
|
|
4119
|
+
const _g = Util.iterToArray(g);
|
|
4120
4120
|
if (_g.length < 2)
|
|
4121
4121
|
throw new Error("Cannot create a Bound from a group that has less than 2 Pt");
|
|
4122
|
-
return new
|
|
4122
|
+
return new _Bound(_g[0], _g[_g.length - 1]);
|
|
4123
4123
|
}
|
|
4124
4124
|
/**
|
|
4125
4125
|
* Initiate the bound's properties.
|
|
@@ -4130,8 +4130,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4130
4130
|
this._inited = true;
|
|
4131
4131
|
}
|
|
4132
4132
|
if (this.p1 && this.p2) {
|
|
4133
|
-
|
|
4134
|
-
|
|
4133
|
+
const a = this.p1;
|
|
4134
|
+
const b = this.p2;
|
|
4135
4135
|
this.topLeft = a.$min(b);
|
|
4136
4136
|
this._bottomRight = a.$max(b);
|
|
4137
4137
|
this._updateSize();
|
|
@@ -4142,7 +4142,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4142
4142
|
* Clone this bound and return a new one.
|
|
4143
4143
|
*/
|
|
4144
4144
|
clone() {
|
|
4145
|
-
return new
|
|
4145
|
+
return new _Bound(this._topLeft.clone(), this._bottomRight.clone());
|
|
4146
4146
|
}
|
|
4147
4147
|
/**
|
|
4148
4148
|
* Recalculte size and center.
|
|
@@ -4175,7 +4175,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4175
4175
|
* Recalculate based on center position and size.
|
|
4176
4176
|
*/
|
|
4177
4177
|
_updatePosFromCenter() {
|
|
4178
|
-
|
|
4178
|
+
const half = this._size.$multiply(0.5);
|
|
4179
4179
|
this._topLeft = this._center.$subtract(half);
|
|
4180
4180
|
this._bottomRight = this._center.$add(half);
|
|
4181
4181
|
}
|
|
@@ -4323,7 +4323,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4323
4323
|
contextmenu: "contextmenu",
|
|
4324
4324
|
all: "all"
|
|
4325
4325
|
};
|
|
4326
|
-
var _UI = class {
|
|
4326
|
+
var _UI = class _UI {
|
|
4327
4327
|
/**
|
|
4328
4328
|
* Create an UI element. You may also create a new UI using one of the static helper like [`UI.fromRectangle`](#link) or [`UI.fromCircle`](#link).
|
|
4329
4329
|
* @param group a Group or an Iterable<PtLike> that defines the UI's appearance
|
|
@@ -4559,8 +4559,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4559
4559
|
}
|
|
4560
4560
|
}
|
|
4561
4561
|
};
|
|
4562
|
+
_UI._counter = 0;
|
|
4562
4563
|
var UI = _UI;
|
|
4563
|
-
UI._counter = 0;
|
|
4564
4564
|
var UIButton = class extends UI {
|
|
4565
4565
|
/**
|
|
4566
4566
|
* Create an UIButton. A button has 2 states, "clicks" (number) and "hover" (boolean), which you can access through [`UI.state`](#link) function. You may also create a new UIButton using one of the static helper like [`UI.fromRectangle`](#link) or [`UI.fromCircle`](#link).
|
|
@@ -4585,7 +4585,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4585
4585
|
if (hover && !this._states.hover) {
|
|
4586
4586
|
this.state("hover", true);
|
|
4587
4587
|
UI._trigger(this._actions[UA.enter], this, pt, UA.enter, evt);
|
|
4588
|
-
|
|
4588
|
+
let _capID = this.hold(UA.move);
|
|
4589
4589
|
this._hoverID = this.on(UA.move, (t, p) => {
|
|
4590
4590
|
if (!this._within(p) && !this.state("dragging")) {
|
|
4591
4591
|
this.state("hover", false);
|
|
@@ -4636,7 +4636,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4636
4636
|
* @returns id numbers that refer to enter/leave handlers, for use in [`UIButton.offHover`](#link) or [`UI.off`](#link).
|
|
4637
4637
|
*/
|
|
4638
4638
|
onHover(enter, leave) {
|
|
4639
|
-
|
|
4639
|
+
let ids = [void 0, void 0];
|
|
4640
4640
|
if (enter)
|
|
4641
4641
|
ids[0] = this.on(UIPointerActions.enter, enter);
|
|
4642
4642
|
if (leave)
|
|
@@ -4650,7 +4650,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4650
4650
|
* @returns an array of booleans indicating whether the handlers were removed successfully
|
|
4651
4651
|
*/
|
|
4652
4652
|
offHover(enterID, leaveID) {
|
|
4653
|
-
|
|
4653
|
+
let s = [false, false];
|
|
4654
4654
|
if (enterID === void 0 || enterID >= 0)
|
|
4655
4655
|
s[0] = this.off(UIPointerActions.enter, enterID);
|
|
4656
4656
|
if (leaveID === void 0 || leaveID >= 0)
|
|
@@ -4793,9 +4793,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4793
4793
|
* @param player an [`IPlayer`](#link) object with animate function, or a callback function `fn(time, ftime)`.
|
|
4794
4794
|
*/
|
|
4795
4795
|
add(p) {
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4796
|
+
const player = typeof p == "function" ? { animate: p } : p;
|
|
4797
|
+
const k = this.playerCount++;
|
|
4798
|
+
const pid = player.animateID || this.id + k;
|
|
4799
4799
|
this.players[pid] = player;
|
|
4800
4800
|
player.animateID = pid;
|
|
4801
4801
|
if (player.resize && this.bound.inited)
|
|
@@ -4862,7 +4862,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4862
4862
|
if (this._refresh)
|
|
4863
4863
|
this.clear();
|
|
4864
4864
|
if (this._isReady) {
|
|
4865
|
-
for (
|
|
4865
|
+
for (const k in this.players) {
|
|
4866
4866
|
if (this.players[k].animate)
|
|
4867
4867
|
this.players[k].animate(time, this._time.diff, this);
|
|
4868
4868
|
}
|
|
@@ -4980,7 +4980,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
4980
4980
|
* Get the mouse or touch pointer that stores the last action.
|
|
4981
4981
|
*/
|
|
4982
4982
|
get pointer() {
|
|
4983
|
-
|
|
4983
|
+
const p = this._pointer.clone();
|
|
4984
4984
|
p.id = this._pointer.id;
|
|
4985
4985
|
return p;
|
|
4986
4986
|
}
|
|
@@ -5032,27 +5032,21 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5032
5032
|
this._mouseOut = this._mouseOut.bind(this);
|
|
5033
5033
|
this._mouseMove = this._mouseMove.bind(this);
|
|
5034
5034
|
this._mouseClick = this._mouseClick.bind(this);
|
|
5035
|
-
this._pointerDown = this._pointerDown.bind(this);
|
|
5036
|
-
this._pointerUp = this._pointerUp.bind(this);
|
|
5037
5035
|
this._contextMenu = this._contextMenu.bind(this);
|
|
5038
|
-
this.bindCanvas("
|
|
5039
|
-
this.bindCanvas("
|
|
5040
|
-
this.bindCanvas("
|
|
5041
|
-
this.bindCanvas("
|
|
5042
|
-
this.bindCanvas("
|
|
5043
|
-
this.bindCanvas("mouseout", this._mouseOut, {}, customTarget);
|
|
5044
|
-
this.bindCanvas("mousemove", this._mouseMove, {}, customTarget);
|
|
5036
|
+
this.bindCanvas("pointerdown", this._mouseDown, {}, customTarget);
|
|
5037
|
+
this.bindCanvas("pointerup", this._mouseUp, {}, customTarget);
|
|
5038
|
+
this.bindCanvas("pointerover", this._mouseOver, {}, customTarget);
|
|
5039
|
+
this.bindCanvas("pointerout", this._mouseOut, {}, customTarget);
|
|
5040
|
+
this.bindCanvas("pointermove", this._mouseMove, {}, customTarget);
|
|
5045
5041
|
this.bindCanvas("click", this._mouseClick, {}, customTarget);
|
|
5046
5042
|
this.bindCanvas("contextmenu", this._contextMenu, {}, customTarget);
|
|
5047
5043
|
this._hasMouse = true;
|
|
5048
5044
|
} else {
|
|
5049
|
-
this.unbindCanvas("
|
|
5050
|
-
this.unbindCanvas("
|
|
5051
|
-
this.unbindCanvas("
|
|
5052
|
-
this.unbindCanvas("
|
|
5053
|
-
this.unbindCanvas("
|
|
5054
|
-
this.unbindCanvas("mouseout", this._mouseOut, {}, customTarget);
|
|
5055
|
-
this.unbindCanvas("mousemove", this._mouseMove, {}, customTarget);
|
|
5045
|
+
this.unbindCanvas("pointerdown", this._mouseDown, {}, customTarget);
|
|
5046
|
+
this.unbindCanvas("pointerup", this._mouseUp, {}, customTarget);
|
|
5047
|
+
this.unbindCanvas("pointerover", this._mouseOver, {}, customTarget);
|
|
5048
|
+
this.unbindCanvas("pointerout", this._mouseOut, {}, customTarget);
|
|
5049
|
+
this.unbindCanvas("pointermove", this._mouseMove, {}, customTarget);
|
|
5056
5050
|
this.unbindCanvas("click", this._mouseClick, {}, customTarget);
|
|
5057
5051
|
this.unbindCanvas("contextmenu", this._contextMenu, {}, customTarget);
|
|
5058
5052
|
this._hasMouse = false;
|
|
@@ -5107,9 +5101,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5107
5101
|
touchesToPoints(evt, which = "touches") {
|
|
5108
5102
|
if (!evt || !evt[which])
|
|
5109
5103
|
return [];
|
|
5110
|
-
|
|
5111
|
-
for (
|
|
5112
|
-
|
|
5104
|
+
const ts = [];
|
|
5105
|
+
for (let i = 0; i < evt[which].length; i++) {
|
|
5106
|
+
const t = evt[which].item(i);
|
|
5113
5107
|
ts.push(new Pt(t.pageX - this.bound.topLeft.x, t.pageY - this.bound.topLeft.y));
|
|
5114
5108
|
}
|
|
5115
5109
|
return ts;
|
|
@@ -5125,9 +5119,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5125
5119
|
return;
|
|
5126
5120
|
let px = 0, py = 0;
|
|
5127
5121
|
if (evt instanceof MouseEvent) {
|
|
5128
|
-
for (
|
|
5122
|
+
for (const k in this.players) {
|
|
5129
5123
|
if (this.players.hasOwnProperty(k)) {
|
|
5130
|
-
|
|
5124
|
+
const v = this.players[k];
|
|
5131
5125
|
px = evt.pageX - this.outerBound.x;
|
|
5132
5126
|
py = evt.pageY - this.outerBound.y;
|
|
5133
5127
|
if (v.action)
|
|
@@ -5135,11 +5129,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5135
5129
|
}
|
|
5136
5130
|
}
|
|
5137
5131
|
} else {
|
|
5138
|
-
for (
|
|
5132
|
+
for (const k in this.players) {
|
|
5139
5133
|
if (this.players.hasOwnProperty(k)) {
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5134
|
+
const v = this.players[k];
|
|
5135
|
+
const c = evt.changedTouches && evt.changedTouches.length > 0;
|
|
5136
|
+
const touch = evt.changedTouches.item(0);
|
|
5143
5137
|
px = c ? touch.pageX - this.outerBound.x : 0;
|
|
5144
5138
|
py = c ? touch.pageY - this.outerBound.y : 0;
|
|
5145
5139
|
if (v.action)
|
|
@@ -5158,11 +5152,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5158
5152
|
*/
|
|
5159
5153
|
_mouseDown(evt) {
|
|
5160
5154
|
this._mouseAction(UIPointerActions.down, evt);
|
|
5161
|
-
this._pressed = true;
|
|
5162
|
-
return false;
|
|
5163
|
-
}
|
|
5164
|
-
_pointerDown(evt) {
|
|
5165
5155
|
this._mouseAction(UIPointerActions.pointerdown, evt);
|
|
5156
|
+
this._pressed = true;
|
|
5166
5157
|
if (evt.target instanceof Element) {
|
|
5167
5158
|
evt.target.setPointerCapture(evt.pointerId);
|
|
5168
5159
|
}
|
|
@@ -5173,6 +5164,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5173
5164
|
* @param evt
|
|
5174
5165
|
*/
|
|
5175
5166
|
_mouseUp(evt) {
|
|
5167
|
+
this._mouseAction(UIPointerActions.pointerup, evt);
|
|
5176
5168
|
if (this._dragged) {
|
|
5177
5169
|
this._mouseAction(UIPointerActions.drop, evt);
|
|
5178
5170
|
} else {
|
|
@@ -5180,15 +5172,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5180
5172
|
}
|
|
5181
5173
|
this._pressed = false;
|
|
5182
5174
|
this._dragged = false;
|
|
5183
|
-
return false;
|
|
5184
|
-
}
|
|
5185
|
-
_pointerUp(evt) {
|
|
5186
|
-
this._mouseAction(UIPointerActions.pointerup, evt);
|
|
5187
5175
|
if (evt.target instanceof Element) {
|
|
5188
5176
|
evt.target.releasePointerCapture(evt.pointerId);
|
|
5189
|
-
if (this._dragged)
|
|
5190
|
-
this._mouseAction(UIPointerActions.drop, evt);
|
|
5191
|
-
this._dragged = false;
|
|
5192
5177
|
}
|
|
5193
5178
|
return false;
|
|
5194
5179
|
}
|
|
@@ -5197,10 +5182,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5197
5182
|
* @param evt
|
|
5198
5183
|
*/
|
|
5199
5184
|
_mouseMove(evt) {
|
|
5200
|
-
this._mouseAction(UIPointerActions.move, evt);
|
|
5201
5185
|
if (this._pressed) {
|
|
5202
5186
|
this._dragged = true;
|
|
5203
5187
|
this._mouseAction(UIPointerActions.drag, evt);
|
|
5188
|
+
} else {
|
|
5189
|
+
this._mouseAction(UIPointerActions.move, evt);
|
|
5204
5190
|
}
|
|
5205
5191
|
return false;
|
|
5206
5192
|
}
|
|
@@ -5246,7 +5232,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5246
5232
|
* @param evt
|
|
5247
5233
|
*/
|
|
5248
5234
|
_touchMove(evt) {
|
|
5249
|
-
this.
|
|
5235
|
+
this._mouseAction(UIPointerActions.move, evt);
|
|
5236
|
+
if (this._pressed) {
|
|
5237
|
+
this._dragged = true;
|
|
5238
|
+
this._mouseAction(UIPointerActions.drag, evt);
|
|
5239
|
+
}
|
|
5250
5240
|
evt.preventDefault();
|
|
5251
5241
|
return false;
|
|
5252
5242
|
}
|
|
@@ -5255,7 +5245,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5255
5245
|
* @param evt
|
|
5256
5246
|
*/
|
|
5257
5247
|
_touchStart(evt) {
|
|
5258
|
-
this.
|
|
5248
|
+
this._mouseAction(UIPointerActions.down, evt);
|
|
5249
|
+
this._pressed = true;
|
|
5250
|
+
return false;
|
|
5259
5251
|
evt.preventDefault();
|
|
5260
5252
|
return false;
|
|
5261
5253
|
}
|
|
@@ -5270,9 +5262,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5270
5262
|
_keyboardAction(type, evt) {
|
|
5271
5263
|
if (!this.isPlaying)
|
|
5272
5264
|
return;
|
|
5273
|
-
for (
|
|
5265
|
+
for (const k in this.players) {
|
|
5274
5266
|
if (this.players.hasOwnProperty(k)) {
|
|
5275
|
-
|
|
5267
|
+
const v = this.players[k];
|
|
5276
5268
|
if (v.action)
|
|
5277
5269
|
v.action(type, evt.shiftKey ? 1 : 0, evt.altKey ? 1 : 0, evt);
|
|
5278
5270
|
}
|
|
@@ -5535,7 +5527,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5535
5527
|
__export(Image_exports, {
|
|
5536
5528
|
Img: () => Img
|
|
5537
5529
|
});
|
|
5538
|
-
var Img = class {
|
|
5530
|
+
var Img = class _Img {
|
|
5539
5531
|
/**
|
|
5540
5532
|
* Create an Img
|
|
5541
5533
|
* @param editable Specify if you want to manipulate pixels of this image. Default is `false`.
|
|
@@ -5560,7 +5552,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5560
5552
|
* @param ready An optional ready callback function
|
|
5561
5553
|
*/
|
|
5562
5554
|
static load(src, editable = false, space, ready) {
|
|
5563
|
-
const img = new
|
|
5555
|
+
const img = new _Img(editable, space);
|
|
5564
5556
|
img.load(src).then((res) => {
|
|
5565
5557
|
if (ready)
|
|
5566
5558
|
ready(res);
|
|
@@ -5576,7 +5568,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5576
5568
|
*/
|
|
5577
5569
|
static loadAsync(src, editable = false, space) {
|
|
5578
5570
|
return __async(this, null, function* () {
|
|
5579
|
-
const img = yield new
|
|
5571
|
+
const img = yield new _Img(editable, space).load(src);
|
|
5580
5572
|
return img;
|
|
5581
5573
|
});
|
|
5582
5574
|
}
|
|
@@ -5590,7 +5582,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5590
5582
|
*/
|
|
5591
5583
|
static loadPattern(src, space, repeat = "repeat", editable = false) {
|
|
5592
5584
|
return __async(this, null, function* () {
|
|
5593
|
-
const img = yield
|
|
5585
|
+
const img = yield _Img.loadAsync(src, editable, space);
|
|
5594
5586
|
return img.pattern(repeat);
|
|
5595
5587
|
});
|
|
5596
5588
|
}
|
|
@@ -5601,7 +5593,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5601
5593
|
* @param scale Optionally set a specific pixel scale (density) of the image canvas.
|
|
5602
5594
|
*/
|
|
5603
5595
|
static blank(size, space, scale) {
|
|
5604
|
-
let img = new
|
|
5596
|
+
let img = new _Img(true, space);
|
|
5605
5597
|
const s = scale ? scale : space.pixelScale;
|
|
5606
5598
|
img.initCanvas(size[0], size[1], s);
|
|
5607
5599
|
return img;
|
|
@@ -5707,7 +5699,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5707
5699
|
*/
|
|
5708
5700
|
pixel(p, rescale = true) {
|
|
5709
5701
|
const s = typeof rescale == "number" ? rescale : rescale ? this._scale : 1;
|
|
5710
|
-
return
|
|
5702
|
+
return _Img.getPixel(this._data, [p[0] * s, p[1] * s]);
|
|
5711
5703
|
}
|
|
5712
5704
|
/**
|
|
5713
5705
|
* Given an ImaegData object and a position, return the RGBA pixel value at that position.
|
|
@@ -5772,7 +5764,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5772
5764
|
*/
|
|
5773
5765
|
static fromBlob(blob, editable = false, space) {
|
|
5774
5766
|
let url = URL.createObjectURL(blob);
|
|
5775
|
-
return new
|
|
5767
|
+
return new _Img(editable, space).load(url);
|
|
5776
5768
|
}
|
|
5777
5769
|
/**
|
|
5778
5770
|
* Convert ImageData object to a Blob, which you can then create an Img instance via [`Img.fromBlob`](#link). Note that the resulting image's dimensions will not account for pixel density.
|
|
@@ -5900,8 +5892,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5900
5892
|
this._bgcolor = "#e1e9f0";
|
|
5901
5893
|
this._offscreen = false;
|
|
5902
5894
|
this._initialResize = false;
|
|
5903
|
-
|
|
5904
|
-
|
|
5895
|
+
let _selector = null;
|
|
5896
|
+
let _existed = false;
|
|
5905
5897
|
this.id = "pt";
|
|
5906
5898
|
if (elem instanceof Element) {
|
|
5907
5899
|
_selector = elem;
|
|
@@ -5938,7 +5930,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5938
5930
|
* @param id element id attribute
|
|
5939
5931
|
*/
|
|
5940
5932
|
_createElement(elem = "div", id) {
|
|
5941
|
-
|
|
5933
|
+
const d = document.createElement(elem);
|
|
5942
5934
|
d.setAttribute("id", id);
|
|
5943
5935
|
return d;
|
|
5944
5936
|
}
|
|
@@ -5953,7 +5945,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5953
5945
|
this._resizeHandler(null);
|
|
5954
5946
|
this.clear(this._bgcolor);
|
|
5955
5947
|
this._canvas.dispatchEvent(new Event("ready"));
|
|
5956
|
-
for (
|
|
5948
|
+
for (const k in this.players) {
|
|
5957
5949
|
if (this.players.hasOwnProperty(k)) {
|
|
5958
5950
|
if (this.players[k].start)
|
|
5959
5951
|
this.players[k].start(this.bound.clone(), this);
|
|
@@ -5973,8 +5965,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
5973
5965
|
this._bgcolor = opt.bgcolor ? opt.bgcolor : "transparent";
|
|
5974
5966
|
this.autoResize = opt.resize != void 0 ? opt.resize : false;
|
|
5975
5967
|
if (opt.retina !== false) {
|
|
5976
|
-
|
|
5977
|
-
|
|
5968
|
+
const r1 = window ? window.devicePixelRatio || 1 : 1;
|
|
5969
|
+
const r2 = this._ctx.webkitBackingStorePixelRatio || this._ctx.mozBackingStorePixelRatio || this._ctx.msBackingStorePixelRatio || this._ctx.oBackingStorePixelRatio || this._ctx.backingStorePixelRatio || 1;
|
|
5978
5970
|
this._pixelScale = Math.max(1, r1 / r2);
|
|
5979
5971
|
}
|
|
5980
5972
|
if (opt.offscreen) {
|
|
@@ -6028,9 +6020,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6028
6020
|
this._offCtx.scale(this._pixelScale, this._pixelScale);
|
|
6029
6021
|
}
|
|
6030
6022
|
}
|
|
6031
|
-
for (
|
|
6023
|
+
for (const k in this.players) {
|
|
6032
6024
|
if (this.players.hasOwnProperty(k)) {
|
|
6033
|
-
|
|
6025
|
+
const p = this.players[k];
|
|
6034
6026
|
if (p.resize)
|
|
6035
6027
|
p.resize(this.bound, evt);
|
|
6036
6028
|
}
|
|
@@ -6047,9 +6039,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6047
6039
|
_resizeHandler(evt) {
|
|
6048
6040
|
if (!window)
|
|
6049
6041
|
return;
|
|
6050
|
-
|
|
6042
|
+
const b = this._autoResize || this._initialResize ? this._container.getBoundingClientRect() : this._canvas.getBoundingClientRect();
|
|
6051
6043
|
if (b) {
|
|
6052
|
-
|
|
6044
|
+
const box = Bound.fromBoundingRect(b);
|
|
6053
6045
|
box.center = box.center.add(window.pageXOffset, window.pageYOffset);
|
|
6054
6046
|
this.resize(box, evt);
|
|
6055
6047
|
}
|
|
@@ -6192,14 +6184,14 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6192
6184
|
* @example `let rec = space.recorder(true); rec.start(); setTimeout( () => rec.stop(), 5000); // record 5s of video and download the file`
|
|
6193
6185
|
*/
|
|
6194
6186
|
recorder(downloadOrCallback, filetype = "webm", bitrate = 15e6) {
|
|
6195
|
-
|
|
6187
|
+
const stream = this._canvas.captureStream();
|
|
6196
6188
|
const recorder = new MediaRecorder(stream, { mimeType: `video/${filetype}`, bitsPerSecond: bitrate });
|
|
6197
6189
|
recorder.ondataavailable = function(d) {
|
|
6198
|
-
|
|
6190
|
+
const url = URL.createObjectURL(new Blob([d.data], { type: `video/${filetype}` }));
|
|
6199
6191
|
if (typeof downloadOrCallback === "function") {
|
|
6200
6192
|
downloadOrCallback(url);
|
|
6201
6193
|
} else if (downloadOrCallback) {
|
|
6202
|
-
|
|
6194
|
+
const a = document.createElement("a");
|
|
6203
6195
|
a.href = url;
|
|
6204
6196
|
a.download = `canvas_video.${filetype}`;
|
|
6205
6197
|
a.click();
|
|
@@ -6209,7 +6201,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6209
6201
|
return recorder;
|
|
6210
6202
|
}
|
|
6211
6203
|
};
|
|
6212
|
-
var CanvasForm = class extends VisualForm {
|
|
6204
|
+
var CanvasForm = class _CanvasForm extends VisualForm {
|
|
6213
6205
|
/**
|
|
6214
6206
|
* Create a new CanvasForm. You may also use [`CanvasSpace.getForm()`](#link) to get the default form.
|
|
6215
6207
|
* @param space an instance of CanvasSpace
|
|
@@ -6286,20 +6278,20 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6286
6278
|
}
|
|
6287
6279
|
}
|
|
6288
6280
|
/**
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6281
|
+
* Set current alpha value.
|
|
6282
|
+
* @example `form.alpha(0.6)`
|
|
6283
|
+
* @param a alpha value between 0 and 1
|
|
6284
|
+
*/
|
|
6293
6285
|
alpha(a) {
|
|
6294
6286
|
this._ctx.globalAlpha = a;
|
|
6295
6287
|
this._style.globalAlpha = a;
|
|
6296
6288
|
return this;
|
|
6297
6289
|
}
|
|
6298
6290
|
/**
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6291
|
+
* Set current fill style. Provide a valid color string such as `"#FFF"` or `"rgba(255,0,100,0.5)"` or `false` to specify no fill color.
|
|
6292
|
+
* @example `form.fill("#F90")`, `form.fill("rgba(0,0,0,.5")`, `form.fill(false)`
|
|
6293
|
+
* @param c fill color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle))
|
|
6294
|
+
*/
|
|
6303
6295
|
fill(c) {
|
|
6304
6296
|
if (typeof c == "boolean") {
|
|
6305
6297
|
this.filled = c;
|
|
@@ -6311,21 +6303,21 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6311
6303
|
return this;
|
|
6312
6304
|
}
|
|
6313
6305
|
/**
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6306
|
+
* Set current fill style and remove stroke style.
|
|
6307
|
+
* @param c fill color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle))
|
|
6308
|
+
*/
|
|
6317
6309
|
fillOnly(c) {
|
|
6318
6310
|
this.stroke(false);
|
|
6319
6311
|
return this.fill(c);
|
|
6320
6312
|
}
|
|
6321
6313
|
/**
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6314
|
+
* Set current stroke style. Provide a valid color string or `false` to specify no stroke color.
|
|
6315
|
+
* @example `form.stroke("#F90")`, `form.stroke("rgba(0,0,0,.5")`, `form.stroke(false)`, `form.stroke("#000", 0.5, 'round', 'square')`
|
|
6316
|
+
* @param c stroke color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle))
|
|
6317
|
+
* @param width Optional value (can be floating point) to set line width
|
|
6318
|
+
* @param linejoin Optional string to set line joint style. Can be "miter", "bevel", or "round".
|
|
6319
|
+
* @param linecap Optional string to set line cap style. Can be "butt", "round", or "square".
|
|
6320
|
+
*/
|
|
6329
6321
|
stroke(c, width, linejoin, linecap) {
|
|
6330
6322
|
if (typeof c == "boolean") {
|
|
6331
6323
|
this.stroked = c;
|
|
@@ -6349,24 +6341,24 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6349
6341
|
return this;
|
|
6350
6342
|
}
|
|
6351
6343
|
/**
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6344
|
+
* Set stroke style and remove fill style.
|
|
6345
|
+
* @param c stroke color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle))
|
|
6346
|
+
* @param width Optional value (can be floating point) to set line width
|
|
6347
|
+
* @param linejoin Optional string to set line joint style. Can be "miter", "bevel", or "round".
|
|
6348
|
+
* @param linecap Optional string to set line cap style. Can be "butt", "round", or "square".
|
|
6349
|
+
*/
|
|
6358
6350
|
strokeOnly(c, width, linejoin, linecap) {
|
|
6359
6351
|
this.fill(false);
|
|
6360
6352
|
return this.stroke(c, width, linejoin, linecap);
|
|
6361
6353
|
}
|
|
6362
6354
|
/**
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6355
|
+
* A convenient function to apply fill and/or stroke after custom drawings using canvas context (eg, `form.ctx.ellipse(...)`).
|
|
6356
|
+
* You don't need to call this function if you're using Pts' drawing functions like `form.point` or `form.rect`
|
|
6357
|
+
* @param filled apply fill when set to `true`
|
|
6358
|
+
* @param stroked apply stroke when set to `true`
|
|
6359
|
+
* @param strokeWidth optionally set a stroke width
|
|
6360
|
+
* @example `form.ctx.beginPath(); form.ctx.ellipse(...); form.applyFillStroke();`
|
|
6361
|
+
*/
|
|
6370
6362
|
applyFillStroke(filled = true, stroked = true, strokeWidth = 1) {
|
|
6371
6363
|
if (filled) {
|
|
6372
6364
|
if (typeof filled === "string")
|
|
@@ -6381,22 +6373,22 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6381
6373
|
return this;
|
|
6382
6374
|
}
|
|
6383
6375
|
/**
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6376
|
+
* This function takes an array of gradient colors, and returns a function to define the areas of the gradient fill. See demo code in [CanvasForm.gradient](https://ptsjs.org/demo/?name=canvasform.textBox).
|
|
6377
|
+
* @param stops an array of gradient stops. This can be an array of colors `["#f00", "#0f0", ...]` for evenly distributed gradient, or an array of [stop, color] like `[[0.1, "#f00"], [0.7, "#0f0"]]`
|
|
6378
|
+
* @returns a function that takes 1 or 2 `Group` as parameters. Use a single `Group` to specify a rectangular area for linear gradient, or use 2 `Groups` to specify 2 `Circles` for radial gradient.
|
|
6379
|
+
* @example `c1 = Circle.fromCenter(...); grad = form.gradient(["#f00", "#00f"]); form.fill( grad( c1, c2 ) ).circle( c1 )`
|
|
6380
|
+
*/
|
|
6389
6381
|
gradient(stops) {
|
|
6390
|
-
|
|
6382
|
+
const vals = [];
|
|
6391
6383
|
if (stops.length < 2)
|
|
6392
6384
|
stops.push([0.99, "#000"], [1, "#000"]);
|
|
6393
6385
|
for (let i = 0, len = stops.length; i < len; i++) {
|
|
6394
|
-
|
|
6395
|
-
|
|
6386
|
+
const t = typeof stops[i] === "string" ? i * (1 / (stops.length - 1)) : stops[i][0];
|
|
6387
|
+
const v = typeof stops[i] === "string" ? stops[i] : stops[i][1];
|
|
6396
6388
|
vals.push([t, v]);
|
|
6397
6389
|
}
|
|
6398
6390
|
return (area1, area2) => {
|
|
6399
|
-
|
|
6391
|
+
const grad = area2 ? this._ctx.createRadialGradient(area1[0][0], area1[0][1], Math.abs(area1[1][0]), area2[0][0], area2[0][1], Math.abs(area2[1][0])) : this._ctx.createLinearGradient(area1[0][0], area1[0][1], area1[1][0], area1[1][1]);
|
|
6400
6392
|
for (let i = 0, len = vals.length; i < len; i++) {
|
|
6401
6393
|
grad.addColorStop(vals[i][0], vals[i][1]);
|
|
6402
6394
|
}
|
|
@@ -6404,26 +6396,26 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6404
6396
|
};
|
|
6405
6397
|
}
|
|
6406
6398
|
/**
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6399
|
+
* Set composite operation (also known as blend mode). You can also call this function without parameters to get back to default 'source-over' mode. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation) for the full list of operations you can use.
|
|
6400
|
+
* @param mode a composite operation such as 'lighten', 'multiply', 'overlay', and 'color-burn'.
|
|
6401
|
+
*/
|
|
6410
6402
|
composite(mode = "source-over") {
|
|
6411
6403
|
this._ctx.globalCompositeOperation = mode;
|
|
6412
6404
|
return this;
|
|
6413
6405
|
}
|
|
6414
6406
|
/**
|
|
6415
|
-
|
|
6416
|
-
|
|
6407
|
+
* Create a clipping mask from the current path. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip) for details.
|
|
6408
|
+
*/
|
|
6417
6409
|
clip() {
|
|
6418
6410
|
this._ctx.clip();
|
|
6419
6411
|
return this;
|
|
6420
6412
|
}
|
|
6421
6413
|
/**
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6414
|
+
* Activate dashed stroke and set dash style. You can customize the segments and offset.
|
|
6415
|
+
* @example `form.dash()`, `form.dash([5, 10])`, `form.dash([5, 5], 5)`, `form.dash(false)`
|
|
6416
|
+
* @param segments Dash segments. Defaults to `true` which corresponds to `[5, 5]`. Pass `false` to deactivate dashes. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash))
|
|
6417
|
+
* @param offset Dash offset. Defaults to 0. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)
|
|
6418
|
+
*/
|
|
6427
6419
|
dash(segments = true, offset = 0) {
|
|
6428
6420
|
if (!segments) {
|
|
6429
6421
|
this._ctx.setLineDash([]);
|
|
@@ -6438,14 +6430,14 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6438
6430
|
return this;
|
|
6439
6431
|
}
|
|
6440
6432
|
/**
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6433
|
+
* Set the current font.
|
|
6434
|
+
* @param sizeOrFont either a number to specify font-size, or a `Font` object to specify all font properties
|
|
6435
|
+
* @param weight Optional font-weight string such as "bold"
|
|
6436
|
+
* @param style Optional font-style string such as "italic"
|
|
6437
|
+
* @param lineHeight Optional line-height number suchas 1.5
|
|
6438
|
+
* @param family Optional font-family such as "Helvetica, sans-serif"
|
|
6439
|
+
* @example `form.font( myFont )`, `form.font(14, "bold")`
|
|
6440
|
+
*/
|
|
6449
6441
|
font(sizeOrFont, weight, style, lineHeight, family) {
|
|
6450
6442
|
if (typeof sizeOrFont == "number") {
|
|
6451
6443
|
this._font.size = sizeOrFont;
|
|
@@ -6466,49 +6458,49 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6466
6458
|
return this;
|
|
6467
6459
|
}
|
|
6468
6460
|
/**
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6461
|
+
* Set whether to use html canvas' [`measureText`](#link) function, or a faster but less accurate heuristic function.
|
|
6462
|
+
* @param estimate `true` to use heuristic function, or `false` to use ctx.measureText
|
|
6463
|
+
*/
|
|
6472
6464
|
fontWidthEstimate(estimate = true) {
|
|
6473
6465
|
this._estimateTextWidth = estimate ? Typography.textWidthEstimator((c) => this._ctx.measureText(c).width) : void 0;
|
|
6474
6466
|
return this;
|
|
6475
6467
|
}
|
|
6476
6468
|
/**
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6469
|
+
* Get the width of this text. It will return an actual measurement or an estimate based on [`fontWidthEstimate`](#link) setting. Default is an actual measurement using canvas context's measureText.
|
|
6470
|
+
* @param c a string of text contents
|
|
6471
|
+
*/
|
|
6480
6472
|
getTextWidth(c) {
|
|
6481
6473
|
return !this._estimateTextWidth ? this._ctx.measureText(c + " .").width : this._estimateTextWidth(c);
|
|
6482
6474
|
}
|
|
6483
6475
|
/**
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6476
|
+
* Truncate text to fit width.
|
|
6477
|
+
* @param str text to truncate
|
|
6478
|
+
* @param width width to fit
|
|
6479
|
+
* @param tail text to indicate overflow such as "...". Default is empty "".
|
|
6480
|
+
*/
|
|
6489
6481
|
_textTruncate(str, width, tail = "") {
|
|
6490
6482
|
return Typography.truncate(this.getTextWidth.bind(this), str, width, tail);
|
|
6491
6483
|
}
|
|
6492
6484
|
/**
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6485
|
+
* Align text within a rectangle box.
|
|
6486
|
+
* @param box a Group or an Iterable<PtLike> that defines a rectangular box
|
|
6487
|
+
* @param vertical a string that specifies the vertical alignment in the box: "top", "bottom", "middle", "start", "end"
|
|
6488
|
+
* @param offset Optional offset from the edge (like padding)
|
|
6489
|
+
* @param center Optional center position
|
|
6490
|
+
*/
|
|
6499
6491
|
_textAlign(box, vertical, offset, center) {
|
|
6500
|
-
|
|
6492
|
+
const _box = Util.iterToArray(box);
|
|
6501
6493
|
if (!Util.arrayCheck(_box))
|
|
6502
6494
|
return;
|
|
6503
6495
|
if (!center)
|
|
6504
6496
|
center = Rectangle.center(_box);
|
|
6505
|
-
|
|
6497
|
+
let px = _box[0][0];
|
|
6506
6498
|
if (this._ctx.textAlign == "end" || this._ctx.textAlign == "right") {
|
|
6507
6499
|
px = _box[1][0];
|
|
6508
6500
|
} else if (this._ctx.textAlign == "center" || this._ctx.textAlign == "middle") {
|
|
6509
6501
|
px = center[0];
|
|
6510
6502
|
}
|
|
6511
|
-
|
|
6503
|
+
let py = center[1];
|
|
6512
6504
|
if (vertical == "top" || vertical == "start") {
|
|
6513
6505
|
py = _box[0][1];
|
|
6514
6506
|
} else if (vertical == "end" || vertical == "bottom") {
|
|
@@ -6517,10 +6509,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6517
6509
|
return offset ? new Pt(px + offset[0], py + offset[1]) : new Pt(px, py);
|
|
6518
6510
|
}
|
|
6519
6511
|
/**
|
|
6520
|
-
|
|
6521
|
-
|
|
6512
|
+
* Reset the rendering context's common styles to this form's styles. This supports using multiple forms on the same canvas context.
|
|
6513
|
+
*/
|
|
6522
6514
|
reset() {
|
|
6523
|
-
for (
|
|
6515
|
+
for (const k in this._style) {
|
|
6524
6516
|
if (this._style.hasOwnProperty(k)) {
|
|
6525
6517
|
this._ctx[k] = this._style[k];
|
|
6526
6518
|
}
|
|
@@ -6536,38 +6528,38 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6536
6528
|
this._ctx.stroke();
|
|
6537
6529
|
}
|
|
6538
6530
|
/**
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6531
|
+
* A static function to draw a point.
|
|
6532
|
+
* @param ctx canvas rendering context
|
|
6533
|
+
* @param p a Pt object
|
|
6534
|
+
* @param radius radius of the point. Default is 5.
|
|
6535
|
+
* @param shape The shape of the point. Defaults to "square", but it can be "circle" or a custom shape function in your own implementation.
|
|
6536
|
+
* @example `form.point( p )`, `form.point( p, 10, "circle" )`
|
|
6537
|
+
*/
|
|
6546
6538
|
static point(ctx, p, radius = 5, shape = "square") {
|
|
6547
6539
|
if (!p)
|
|
6548
6540
|
return;
|
|
6549
|
-
if (!
|
|
6541
|
+
if (!_CanvasForm[shape])
|
|
6550
6542
|
throw new Error(`${shape} is not a static function of CanvasForm`);
|
|
6551
|
-
|
|
6543
|
+
_CanvasForm[shape](ctx, p, radius);
|
|
6552
6544
|
}
|
|
6553
6545
|
/**
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6546
|
+
* Draws a point.
|
|
6547
|
+
* @param p a Pt object
|
|
6548
|
+
* @param radius radius of the point. Default is 5.
|
|
6549
|
+
* @param shape The shape of the point. Defaults to "square", but it can be "circle" or a custom shape function in your own implementation.
|
|
6550
|
+
* @example `form.point( p )`, `form.point( p, 10, "circle" )`
|
|
6551
|
+
*/
|
|
6560
6552
|
point(p, radius = 5, shape = "square") {
|
|
6561
|
-
|
|
6553
|
+
_CanvasForm.point(this._ctx, p, radius, shape);
|
|
6562
6554
|
this._paint();
|
|
6563
6555
|
return this;
|
|
6564
6556
|
}
|
|
6565
6557
|
/**
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6558
|
+
* A static function to draw a circle.
|
|
6559
|
+
* @param ctx canvas rendering context
|
|
6560
|
+
* @param pt center position of the circle
|
|
6561
|
+
* @param radius radius of the circle
|
|
6562
|
+
*/
|
|
6571
6563
|
static circle(ctx, pt, radius = 10) {
|
|
6572
6564
|
if (!pt)
|
|
6573
6565
|
return;
|
|
@@ -6576,25 +6568,25 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6576
6568
|
ctx.closePath();
|
|
6577
6569
|
}
|
|
6578
6570
|
/**
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6571
|
+
* Draw a circle. See also [`Circle.fromCenter`](#link)
|
|
6572
|
+
* @param pts usually a Group or an Iterable<PtLike> with 2 Pt, but it can also take an array of two numeric arrays [ [position], [size] ]
|
|
6573
|
+
*/
|
|
6582
6574
|
circle(pts) {
|
|
6583
|
-
|
|
6584
|
-
|
|
6575
|
+
const p = Util.iterToArray(pts);
|
|
6576
|
+
_CanvasForm.circle(this._ctx, p[0], p[1][0]);
|
|
6585
6577
|
this._paint();
|
|
6586
6578
|
return this;
|
|
6587
6579
|
}
|
|
6588
6580
|
/**
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6581
|
+
* A static function to draw an ellipse.
|
|
6582
|
+
* @param ctx canvas rendering context
|
|
6583
|
+
* @param pt center position
|
|
6584
|
+
* @param radius radius [x, y] of the ellipse
|
|
6585
|
+
* @param rotation rotation of the ellipse in radian. Default is 0.
|
|
6586
|
+
* @param startAngle start angle of the ellipse. Default is 0.
|
|
6587
|
+
* @param endAngle end angle of the ellipse. Default is 2 PI.
|
|
6588
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6589
|
+
*/
|
|
6598
6590
|
static ellipse(ctx, pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6599
6591
|
if (!pt || !radius)
|
|
6600
6592
|
return;
|
|
@@ -6602,28 +6594,28 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6602
6594
|
ctx.ellipse(pt[0], pt[1], radius[0], radius[1], rotation, startAngle, endAngle, cc);
|
|
6603
6595
|
}
|
|
6604
6596
|
/**
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6597
|
+
* Draw an ellipse.
|
|
6598
|
+
* @param pt center position
|
|
6599
|
+
* @param radius radius [x, y] of the ellipse
|
|
6600
|
+
* @param rotation rotation of the ellipse in radian. Default is 0.
|
|
6601
|
+
* @param startAngle start angle of the ellipse. Default is 0.
|
|
6602
|
+
* @param endAngle end angle of the ellipse. Default is 2 PI.
|
|
6603
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6604
|
+
*/
|
|
6613
6605
|
ellipse(pt, radius, rotation = 0, startAngle = 0, endAngle = Const.two_pi, cc = false) {
|
|
6614
|
-
|
|
6606
|
+
_CanvasForm.ellipse(this._ctx, pt, radius, rotation, startAngle, endAngle, cc);
|
|
6615
6607
|
this._paint();
|
|
6616
6608
|
return this;
|
|
6617
6609
|
}
|
|
6618
6610
|
/**
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6611
|
+
* A static function to draw an arc.
|
|
6612
|
+
* @param ctx canvas rendering context
|
|
6613
|
+
* @param pt center position
|
|
6614
|
+
* @param radius radius of the arc circle
|
|
6615
|
+
* @param startAngle start angle of the arc
|
|
6616
|
+
* @param endAngle end angle of the arc
|
|
6617
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6618
|
+
*/
|
|
6627
6619
|
static arc(ctx, pt, radius, startAngle, endAngle, cc) {
|
|
6628
6620
|
if (!pt)
|
|
6629
6621
|
return;
|
|
@@ -6631,31 +6623,31 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6631
6623
|
ctx.arc(pt[0], pt[1], radius, startAngle, endAngle, cc);
|
|
6632
6624
|
}
|
|
6633
6625
|
/**
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6626
|
+
* Draw an arc.
|
|
6627
|
+
* @param pt center position
|
|
6628
|
+
* @param radius radius of the arc circle
|
|
6629
|
+
* @param startAngle start angle of the arc
|
|
6630
|
+
* @param endAngle end angle of the arc
|
|
6631
|
+
* @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.
|
|
6632
|
+
*/
|
|
6641
6633
|
arc(pt, radius, startAngle, endAngle, cc) {
|
|
6642
|
-
|
|
6634
|
+
_CanvasForm.arc(this._ctx, pt, radius, startAngle, endAngle, cc);
|
|
6643
6635
|
this._paint();
|
|
6644
6636
|
return this;
|
|
6645
6637
|
}
|
|
6646
6638
|
/**
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6639
|
+
* A static function to draw a square.
|
|
6640
|
+
* @param ctx canvas rendering context
|
|
6641
|
+
* @param pt center position of the square
|
|
6642
|
+
* @param halfsize half size of the square
|
|
6643
|
+
*/
|
|
6652
6644
|
static square(ctx, pt, halfsize) {
|
|
6653
6645
|
if (!pt)
|
|
6654
6646
|
return;
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6647
|
+
const x1 = pt[0] - halfsize;
|
|
6648
|
+
const y1 = pt[1] - halfsize;
|
|
6649
|
+
const x2 = pt[0] + halfsize;
|
|
6650
|
+
const y2 = pt[1] + halfsize;
|
|
6659
6651
|
ctx.beginPath();
|
|
6660
6652
|
ctx.moveTo(x1, y1);
|
|
6661
6653
|
ctx.lineTo(x1, y2);
|
|
@@ -6664,26 +6656,26 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6664
6656
|
ctx.closePath();
|
|
6665
6657
|
}
|
|
6666
6658
|
/**
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6659
|
+
* Draw a square, given a center and its half-size.
|
|
6660
|
+
* @param pt center Pt
|
|
6661
|
+
* @param halfsize half-size
|
|
6662
|
+
*/
|
|
6671
6663
|
square(pt, halfsize) {
|
|
6672
|
-
|
|
6664
|
+
_CanvasForm.square(this._ctx, pt, halfsize);
|
|
6673
6665
|
this._paint();
|
|
6674
6666
|
return this;
|
|
6675
6667
|
}
|
|
6676
6668
|
/**
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6669
|
+
* A static function to draw a line or polyline.
|
|
6670
|
+
* @param ctx canvas rendering context
|
|
6671
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6672
|
+
*/
|
|
6681
6673
|
static line(ctx, pts) {
|
|
6682
6674
|
if (!Util.arrayCheck(pts))
|
|
6683
6675
|
return;
|
|
6684
6676
|
let i = 0;
|
|
6685
6677
|
ctx.beginPath();
|
|
6686
|
-
for (
|
|
6678
|
+
for (const it of pts) {
|
|
6687
6679
|
if (it) {
|
|
6688
6680
|
if (i++ > 0) {
|
|
6689
6681
|
ctx.lineTo(it[0], it[1]);
|
|
@@ -6694,41 +6686,41 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6694
6686
|
}
|
|
6695
6687
|
}
|
|
6696
6688
|
/**
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6689
|
+
* Draw a line or polyline.
|
|
6690
|
+
* @param pts a Group or an Iterable<PtLike> representing a line
|
|
6691
|
+
*/
|
|
6700
6692
|
line(pts) {
|
|
6701
|
-
|
|
6693
|
+
_CanvasForm.line(this._ctx, pts);
|
|
6702
6694
|
this._paint();
|
|
6703
6695
|
return this;
|
|
6704
6696
|
}
|
|
6705
6697
|
/**
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6698
|
+
* A static function to draw a polygon.
|
|
6699
|
+
* @param ctx canvas rendering context
|
|
6700
|
+
* @param pts a Group or an Iterable<PtLike> representing a polygon
|
|
6701
|
+
*/
|
|
6710
6702
|
static polygon(ctx, pts) {
|
|
6711
6703
|
if (!Util.arrayCheck(pts))
|
|
6712
6704
|
return;
|
|
6713
|
-
|
|
6705
|
+
_CanvasForm.line(ctx, pts);
|
|
6714
6706
|
ctx.closePath();
|
|
6715
6707
|
}
|
|
6716
6708
|
/**
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6709
|
+
* Draw a polygon.
|
|
6710
|
+
* @param pts a Group or an Iterable<PtLike> representingg a polygon
|
|
6711
|
+
*/
|
|
6720
6712
|
polygon(pts) {
|
|
6721
|
-
|
|
6713
|
+
_CanvasForm.polygon(this._ctx, pts);
|
|
6722
6714
|
this._paint();
|
|
6723
6715
|
return this;
|
|
6724
6716
|
}
|
|
6725
6717
|
/**
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6718
|
+
* A static function to draw a rectangle.
|
|
6719
|
+
* @param ctx canvas rendering context
|
|
6720
|
+
* @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.
|
|
6721
|
+
*/
|
|
6730
6722
|
static rect(ctx, pts) {
|
|
6731
|
-
|
|
6723
|
+
const p = Util.iterToArray(pts);
|
|
6732
6724
|
if (!Util.arrayCheck(p))
|
|
6733
6725
|
return;
|
|
6734
6726
|
ctx.beginPath();
|
|
@@ -6739,29 +6731,29 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6739
6731
|
ctx.closePath();
|
|
6740
6732
|
}
|
|
6741
6733
|
/**
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6734
|
+
* Draw a rectangle.
|
|
6735
|
+
* @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.
|
|
6736
|
+
*/
|
|
6745
6737
|
rect(pts) {
|
|
6746
|
-
|
|
6738
|
+
_CanvasForm.rect(this._ctx, pts);
|
|
6747
6739
|
this._paint();
|
|
6748
6740
|
return this;
|
|
6749
6741
|
}
|
|
6750
6742
|
/**
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6743
|
+
* A static function to draw an image.
|
|
6744
|
+
* @param ctx canvas rendering context
|
|
6745
|
+
* @param img either an [Img](#link) instance or an [`CanvasImageSource`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource) instance (eg the image from `<img>`, `<video>` or `<canvas>`)
|
|
6746
|
+
* @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.
|
|
6747
|
+
* @param orig optionally a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a cropping box in the original target.
|
|
6748
|
+
*/
|
|
6757
6749
|
static image(ctx, ptOrRect, img, orig) {
|
|
6758
|
-
|
|
6750
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6759
6751
|
let pos;
|
|
6760
6752
|
if (typeof t[0] === "number") {
|
|
6761
6753
|
pos = t;
|
|
6762
6754
|
} else {
|
|
6763
6755
|
if (orig) {
|
|
6764
|
-
|
|
6756
|
+
const o = Util.iterToArray(orig);
|
|
6765
6757
|
pos = [
|
|
6766
6758
|
o[0][0],
|
|
6767
6759
|
o[0][1],
|
|
@@ -6785,29 +6777,29 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6785
6777
|
}
|
|
6786
6778
|
}
|
|
6787
6779
|
/**
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6780
|
+
* Draw an image.
|
|
6781
|
+
* @param img either an [Img](#link) instance or an [`CanvasImageSource`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource) instance (eg the image from `<img>`, `<video>` or `<canvas>`)
|
|
6782
|
+
* @param ptOrRect a target area to place the image. Either a PtLike specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left position, bottom-right position) that specifies a bounding box. Default is (0,0) at top-left.
|
|
6783
|
+
* @param orig optionally a Group or an Iterable<PtLike> with 2 Pt (top-left position, bottom-right position) that specifies a cropping box in the original target.
|
|
6784
|
+
*/
|
|
6793
6785
|
image(ptOrRect, img, orig) {
|
|
6794
6786
|
if (img instanceof Img) {
|
|
6795
6787
|
if (img.loaded) {
|
|
6796
|
-
|
|
6788
|
+
_CanvasForm.image(this._ctx, ptOrRect, img.image, orig);
|
|
6797
6789
|
}
|
|
6798
6790
|
} else {
|
|
6799
|
-
|
|
6791
|
+
_CanvasForm.image(this._ctx, ptOrRect, img, orig);
|
|
6800
6792
|
}
|
|
6801
6793
|
return this;
|
|
6802
6794
|
}
|
|
6803
6795
|
/**
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6796
|
+
* A static function to draw ImageData on canvas
|
|
6797
|
+
* @param ctx canvas rendering context
|
|
6798
|
+
* @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.
|
|
6799
|
+
* @param img an ImageData object
|
|
6800
|
+
*/
|
|
6809
6801
|
static imageData(ctx, ptOrRect, img) {
|
|
6810
|
-
|
|
6802
|
+
const t = Util.iterToArray(ptOrRect);
|
|
6811
6803
|
if (typeof t[0] === "number") {
|
|
6812
6804
|
ctx.putImageData(img, t[0], t[1]);
|
|
6813
6805
|
} else {
|
|
@@ -6815,74 +6807,74 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6815
6807
|
}
|
|
6816
6808
|
}
|
|
6817
6809
|
/**
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6810
|
+
* Draw ImageData on canvas using ImageData
|
|
6811
|
+
* @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.
|
|
6812
|
+
* @param img an ImageData object
|
|
6813
|
+
*/
|
|
6822
6814
|
imageData(ptOrRect, img) {
|
|
6823
|
-
|
|
6815
|
+
_CanvasForm.imageData(this._ctx, ptOrRect, img);
|
|
6824
6816
|
return this;
|
|
6825
6817
|
}
|
|
6826
6818
|
/**
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6819
|
+
* A static function to draw text.
|
|
6820
|
+
* @param ctx canvas rendering context
|
|
6821
|
+
* @param `pt` a Point object to specify the anchor point
|
|
6822
|
+
* @param `txt` a string of text to draw
|
|
6823
|
+
* @param `maxWidth` specify a maximum width per line
|
|
6824
|
+
*/
|
|
6833
6825
|
static text(ctx, pt, txt, maxWidth) {
|
|
6834
6826
|
if (!pt)
|
|
6835
6827
|
return;
|
|
6836
6828
|
ctx.fillText(txt, pt[0], pt[1], maxWidth);
|
|
6837
6829
|
}
|
|
6838
6830
|
/**
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6831
|
+
* Draw text on canvas.
|
|
6832
|
+
* @param `pt` a Pt or numeric array to specify the anchor point
|
|
6833
|
+
* @param `txt` text
|
|
6834
|
+
* @param `maxWidth` specify a maximum width per line
|
|
6835
|
+
*/
|
|
6844
6836
|
text(pt, txt, maxWidth) {
|
|
6845
|
-
|
|
6837
|
+
_CanvasForm.text(this._ctx, pt, txt, maxWidth);
|
|
6846
6838
|
return this;
|
|
6847
6839
|
}
|
|
6848
6840
|
/**
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6841
|
+
* Fit a single-line text in a rectangular box.
|
|
6842
|
+
* @param box a rectangle box defined by a Group or an Iterable<Pt>
|
|
6843
|
+
* @param txt string of text
|
|
6844
|
+
* @param tail text to indicate overflow such as "...". Default is empty "".
|
|
6845
|
+
* @param verticalAlign "top", "middle", or "bottom" to specify vertical alignment inside the box
|
|
6846
|
+
* @param overrideBaseline If `true`, use the corresponding baseline as verticalAlign. If `false`, use the current canvas context's textBaseline setting. Default is `true`.
|
|
6847
|
+
*/
|
|
6856
6848
|
textBox(box, txt, verticalAlign = "middle", tail = "", overrideBaseline = true) {
|
|
6857
6849
|
if (overrideBaseline)
|
|
6858
6850
|
this._ctx.textBaseline = verticalAlign;
|
|
6859
|
-
|
|
6860
|
-
|
|
6851
|
+
const size = Rectangle.size(box);
|
|
6852
|
+
const t = this._textTruncate(txt, size[0], tail);
|
|
6861
6853
|
this.text(this._textAlign(box, verticalAlign), t[0]);
|
|
6862
6854
|
return this;
|
|
6863
6855
|
}
|
|
6864
6856
|
/**
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6857
|
+
* Fit multi-line text in a rectangular box. Note that this will also set canvas context's textBaseline to "top".
|
|
6858
|
+
* @param box a Group or an Iterable<PtLike> with 2 Pt that represents a bounding box
|
|
6859
|
+
* @param txt string of text
|
|
6860
|
+
* @param lineHeight line height as a ratio of font size. Default is 1.2.
|
|
6861
|
+
* @param verticalAlign "top", "middle", or "bottom" to specify vertical alignment inside the box
|
|
6862
|
+
* @param crop a boolean to specify whether to crop text when overflowing
|
|
6863
|
+
*/
|
|
6872
6864
|
paragraphBox(box, txt, lineHeight = 1.2, verticalAlign = "top", crop = true) {
|
|
6873
|
-
|
|
6874
|
-
|
|
6865
|
+
const b = Util.iterToArray(box);
|
|
6866
|
+
const size = Rectangle.size(b);
|
|
6875
6867
|
this._ctx.textBaseline = "top";
|
|
6876
|
-
|
|
6877
|
-
|
|
6868
|
+
const lstep = this._font.size * lineHeight;
|
|
6869
|
+
const nextLine = (sub, buffer = [], cc = 0) => {
|
|
6878
6870
|
if (!sub)
|
|
6879
6871
|
return buffer;
|
|
6880
6872
|
if (crop && cc * lstep > size[1] - lstep * 2)
|
|
6881
6873
|
return buffer;
|
|
6882
6874
|
if (cc > 1e4)
|
|
6883
6875
|
throw new Error("max recursion reached (10000)");
|
|
6884
|
-
|
|
6885
|
-
|
|
6876
|
+
const t = this._textTruncate(sub, size[0], "");
|
|
6877
|
+
const newln = t[0].indexOf("\n");
|
|
6886
6878
|
if (newln >= 0) {
|
|
6887
6879
|
buffer.push(t[0].substr(0, newln));
|
|
6888
6880
|
return nextLine(sub.substr(newln + 1), buffer, cc + 1);
|
|
@@ -6890,12 +6882,12 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6890
6882
|
let dt = t[0].lastIndexOf(" ") + 1;
|
|
6891
6883
|
if (dt <= 0 || t[1] === sub.length)
|
|
6892
6884
|
dt = void 0;
|
|
6893
|
-
|
|
6885
|
+
const line = t[0].substr(0, dt);
|
|
6894
6886
|
buffer.push(line);
|
|
6895
6887
|
return t[1] <= 0 || t[1] === sub.length ? buffer : nextLine(sub.substr(dt || t[1]), buffer, cc + 1);
|
|
6896
6888
|
};
|
|
6897
|
-
|
|
6898
|
-
|
|
6889
|
+
const lines = nextLine(txt);
|
|
6890
|
+
const lsize = lines.length * lstep;
|
|
6899
6891
|
let lbox = b;
|
|
6900
6892
|
if (verticalAlign == "middle" || verticalAlign == "center") {
|
|
6901
6893
|
let lpad = (size[1] - lsize) / 2;
|
|
@@ -6907,17 +6899,17 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6907
6899
|
} else {
|
|
6908
6900
|
lbox = new Group(b[0], b[0].$add(size[0], lsize));
|
|
6909
6901
|
}
|
|
6910
|
-
|
|
6902
|
+
const center = Rectangle.center(lbox);
|
|
6911
6903
|
for (let i = 0, len = lines.length; i < len; i++) {
|
|
6912
6904
|
this.text(this._textAlign(lbox, "top", [0, i * lstep], center), lines[i]);
|
|
6913
6905
|
}
|
|
6914
6906
|
return this;
|
|
6915
6907
|
}
|
|
6916
6908
|
/**
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6909
|
+
* Set text alignment and baseline (eg, vertical-align).
|
|
6910
|
+
* @param alignment HTML canvas' textAlign option: "left", "right", "center", "start", or "end"
|
|
6911
|
+
* @param baseline HTML canvas' textBaseline option: "top", "hanging", "middle", "alphabetic", "ideographic", "bottom". For convenience, you can also use "center" (same as "middle"), and "baseline" (same as "alphabetic")
|
|
6912
|
+
*/
|
|
6921
6913
|
alignText(alignment = "left", baseline = "alphabetic") {
|
|
6922
6914
|
if (baseline == "center")
|
|
6923
6915
|
baseline = "middle";
|
|
@@ -6928,11 +6920,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
6928
6920
|
return this;
|
|
6929
6921
|
}
|
|
6930
6922
|
/**
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6923
|
+
* A convenient way to draw some text on canvas for logging or debugging. It'll be draw on the top-left of the canvas as an overlay.
|
|
6924
|
+
* @param txt text
|
|
6925
|
+
*/
|
|
6934
6926
|
log(txt) {
|
|
6935
|
-
|
|
6927
|
+
const w = this._ctx.measureText(txt).width + 20;
|
|
6936
6928
|
this.stroke(false).fill("rgba(0,0,0,.4)").rect([[0, 0], [w, 20]]);
|
|
6937
6929
|
this.fill("#fff").text([10, 14], txt);
|
|
6938
6930
|
return this;
|
|
@@ -7401,7 +7393,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7401
7393
|
return Num.lerp(Num.lerp(n00, n10, tx), Num.lerp(n01, n11, tx), _fade(y));
|
|
7402
7394
|
}
|
|
7403
7395
|
};
|
|
7404
|
-
var Delaunay = class extends Group {
|
|
7396
|
+
var Delaunay = class _Delaunay extends Group {
|
|
7405
7397
|
constructor() {
|
|
7406
7398
|
super(...arguments);
|
|
7407
7399
|
this._mesh = [];
|
|
@@ -7448,7 +7440,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7448
7440
|
edges.push(circum.i, circum.j, circum.j, circum.k, circum.k, circum.i);
|
|
7449
7441
|
opened.splice(j, 1);
|
|
7450
7442
|
}
|
|
7451
|
-
|
|
7443
|
+
_Delaunay._dedupe(edges);
|
|
7452
7444
|
j = edges.length;
|
|
7453
7445
|
while (j > 1) {
|
|
7454
7446
|
opened.push(this._circum(edges[--j], edges[--j], c, false, pts));
|
|
@@ -7594,7 +7586,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7594
7586
|
__export(Color_exports, {
|
|
7595
7587
|
Color: () => Color
|
|
7596
7588
|
});
|
|
7597
|
-
var _Color = class extends Pt {
|
|
7589
|
+
var _Color = class _Color extends Pt {
|
|
7598
7590
|
/**
|
|
7599
7591
|
* Create a Color. Same as creating a Pt. Optionally you may use [`Color.from`](#link) to create a color.
|
|
7600
7592
|
* @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties
|
|
@@ -7609,8 +7601,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7609
7601
|
* @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties
|
|
7610
7602
|
*/
|
|
7611
7603
|
static from(...args) {
|
|
7612
|
-
|
|
7613
|
-
|
|
7604
|
+
const p = [1, 1, 1, 1];
|
|
7605
|
+
const c = Util.getArgs(args);
|
|
7614
7606
|
for (let i = 0, len = p.length; i < len; i++) {
|
|
7615
7607
|
if (i < c.length)
|
|
7616
7608
|
p[i] = c[i];
|
|
@@ -7625,7 +7617,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7625
7617
|
if (hex[0] == "#")
|
|
7626
7618
|
hex = hex.substr(1);
|
|
7627
7619
|
if (hex.length <= 3) {
|
|
7628
|
-
|
|
7620
|
+
const fn = (i) => hex[i] || "F";
|
|
7629
7621
|
hex = `${fn(0)}${fn(0)}${fn(1)}${fn(1)}${fn(2)}${fn(2)}`;
|
|
7630
7622
|
}
|
|
7631
7623
|
let alpha = 1;
|
|
@@ -7633,7 +7625,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7633
7625
|
alpha = hex.substr(6) && 255 / 255;
|
|
7634
7626
|
hex = hex.substring(0, 6);
|
|
7635
7627
|
}
|
|
7636
|
-
|
|
7628
|
+
const hexVal = parseInt(hex, 16);
|
|
7637
7629
|
return new _Color(hexVal >> 16, hexVal >> 8 & 255, hexVal & 255, alpha);
|
|
7638
7630
|
}
|
|
7639
7631
|
/**
|
|
@@ -7715,7 +7707,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7715
7707
|
* Clone this Color.
|
|
7716
7708
|
*/
|
|
7717
7709
|
clone() {
|
|
7718
|
-
|
|
7710
|
+
const c = new _Color(this);
|
|
7719
7711
|
c.toMode(this._mode);
|
|
7720
7712
|
return c;
|
|
7721
7713
|
}
|
|
@@ -7726,7 +7718,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7726
7718
|
*/
|
|
7727
7719
|
toMode(mode, convert = false) {
|
|
7728
7720
|
if (convert) {
|
|
7729
|
-
|
|
7721
|
+
const fname = this._mode.toUpperCase() + "to" + mode.toUpperCase();
|
|
7730
7722
|
if (_Color[fname]) {
|
|
7731
7723
|
this.to(_Color[fname](this, this._isNorm, this._isNorm));
|
|
7732
7724
|
} else {
|
|
@@ -7778,7 +7770,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7778
7770
|
return this._mode == "lch" ? this[2] : this[0];
|
|
7779
7771
|
}
|
|
7780
7772
|
set h(n) {
|
|
7781
|
-
|
|
7773
|
+
const i = this._mode == "lch" ? 2 : 0;
|
|
7782
7774
|
this[i] = n;
|
|
7783
7775
|
}
|
|
7784
7776
|
/**
|
|
@@ -7797,7 +7789,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7797
7789
|
return this._mode == "hsl" ? this[2] : this[0];
|
|
7798
7790
|
}
|
|
7799
7791
|
set l(n) {
|
|
7800
|
-
|
|
7792
|
+
const i = this._mode == "hsl" ? 2 : 0;
|
|
7801
7793
|
this[i] = n;
|
|
7802
7794
|
}
|
|
7803
7795
|
// lab, lch, luv
|
|
@@ -7863,7 +7855,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7863
7855
|
normalize(toNorm = true) {
|
|
7864
7856
|
if (this._isNorm == toNorm)
|
|
7865
7857
|
return this;
|
|
7866
|
-
|
|
7858
|
+
const ranges = _Color.ranges[this._mode];
|
|
7867
7859
|
for (let i = 0; i < 3; i++) {
|
|
7868
7860
|
this[i] = !toNorm ? Num.mapToRange(this[i], 0, 1, ranges[i][0], ranges[i][1]) : Num.mapToRange(this[i], ranges[i][0], ranges[i][1], 0, 1);
|
|
7869
7861
|
}
|
|
@@ -7884,8 +7876,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7884
7876
|
*/
|
|
7885
7877
|
toString(format = "mode") {
|
|
7886
7878
|
if (format == "hex") {
|
|
7887
|
-
|
|
7888
|
-
|
|
7879
|
+
const _hex = (n) => {
|
|
7880
|
+
const s = Math.floor(n).toString(16);
|
|
7889
7881
|
return s.length < 2 ? "0" + s : s;
|
|
7890
7882
|
};
|
|
7891
7883
|
return `#${_hex(this[0])}${_hex(this[1])}${_hex(this[2])}`;
|
|
@@ -7905,17 +7897,17 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7905
7897
|
* @returns a new HSL Color
|
|
7906
7898
|
*/
|
|
7907
7899
|
static RGBtoHSL(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7900
|
+
const [r, g, b] = !normalizedInput ? rgb.$normalize() : rgb;
|
|
7901
|
+
const max = Math.max(r, g, b);
|
|
7902
|
+
const min = Math.min(r, g, b);
|
|
7911
7903
|
let h = (max + min) / 2;
|
|
7912
7904
|
let s = h;
|
|
7913
|
-
|
|
7905
|
+
const l = h;
|
|
7914
7906
|
if (max == min) {
|
|
7915
7907
|
h = 0;
|
|
7916
7908
|
s = 0;
|
|
7917
7909
|
} else {
|
|
7918
|
-
|
|
7910
|
+
const d = max - min;
|
|
7919
7911
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
7920
7912
|
h = 0;
|
|
7921
7913
|
if (max === r) {
|
|
@@ -7941,9 +7933,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7941
7933
|
h = h / 360;
|
|
7942
7934
|
if (s == 0)
|
|
7943
7935
|
return _Color.rgb(l * 255, l * 255, l * 255, hsl.alpha);
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7936
|
+
const q = l <= 0.5 ? l * (1 + s) : l + s - l * s;
|
|
7937
|
+
const p = 2 * l - q;
|
|
7938
|
+
const convert = (t) => {
|
|
7947
7939
|
t = t < 0 ? t + 1 : t > 1 ? t - 1 : t;
|
|
7948
7940
|
if (t * 6 < 1) {
|
|
7949
7941
|
return p + (q - p) * t * 6;
|
|
@@ -7955,7 +7947,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7955
7947
|
return p;
|
|
7956
7948
|
}
|
|
7957
7949
|
};
|
|
7958
|
-
|
|
7950
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
7959
7951
|
return _Color.rgb(
|
|
7960
7952
|
sc * convert(h + 1 / 3),
|
|
7961
7953
|
sc * convert(h),
|
|
@@ -7971,13 +7963,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
7971
7963
|
* @returns a new HSB Color
|
|
7972
7964
|
*/
|
|
7973
7965
|
static RGBtoHSB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7966
|
+
const [r, g, b] = !normalizedInput ? rgb.$normalize() : rgb;
|
|
7967
|
+
const max = Math.max(r, g, b);
|
|
7968
|
+
const min = Math.min(r, g, b);
|
|
7969
|
+
const d = max - min;
|
|
7978
7970
|
let h = 0;
|
|
7979
|
-
|
|
7980
|
-
|
|
7971
|
+
const s = max === 0 ? 0 : d / max;
|
|
7972
|
+
const v = max;
|
|
7981
7973
|
if (max != min) {
|
|
7982
7974
|
if (max === r) {
|
|
7983
7975
|
h = (g - b) / d + (g < b ? 6 : 0);
|
|
@@ -8000,12 +7992,12 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8000
7992
|
let [h, s, v] = hsb;
|
|
8001
7993
|
if (!normalizedInput)
|
|
8002
7994
|
h = h / 360;
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
7995
|
+
const i = Math.floor(h * 6);
|
|
7996
|
+
const f = h * 6 - i;
|
|
7997
|
+
const p = v * (1 - s);
|
|
7998
|
+
const q = v * (1 - f * s);
|
|
7999
|
+
const t = v * (1 - (1 - f) * s);
|
|
8000
|
+
const pick = [
|
|
8009
8001
|
[v, t, p],
|
|
8010
8002
|
[q, v, p],
|
|
8011
8003
|
[p, v, t],
|
|
@@ -8013,8 +8005,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8013
8005
|
[t, p, v],
|
|
8014
8006
|
[v, p, q]
|
|
8015
8007
|
];
|
|
8016
|
-
|
|
8017
|
-
|
|
8008
|
+
const c = pick[i % 6];
|
|
8009
|
+
const sc = normalizedOutput ? 1 : 255;
|
|
8018
8010
|
return _Color.rgb(
|
|
8019
8011
|
sc * c[0],
|
|
8020
8012
|
sc * c[1],
|
|
@@ -8030,7 +8022,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8030
8022
|
* @returns a new LAB Color
|
|
8031
8023
|
*/
|
|
8032
8024
|
static RGBtoLAB(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8033
|
-
|
|
8025
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
8034
8026
|
return _Color.XYZtoLAB(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
8035
8027
|
}
|
|
8036
8028
|
/**
|
|
@@ -8041,7 +8033,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8041
8033
|
* @returns a new RGB Color
|
|
8042
8034
|
*/
|
|
8043
8035
|
static LABtoRGB(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8044
|
-
|
|
8036
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8045
8037
|
return _Color.XYZtoRGB(_Color.LABtoXYZ(c), false, normalizedOutput);
|
|
8046
8038
|
}
|
|
8047
8039
|
/**
|
|
@@ -8052,7 +8044,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8052
8044
|
* @returns a new LCH Color
|
|
8053
8045
|
*/
|
|
8054
8046
|
static RGBtoLCH(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8055
|
-
|
|
8047
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
8056
8048
|
return _Color.LABtoLCH(_Color.RGBtoLAB(c), false, normalizedOutput);
|
|
8057
8049
|
}
|
|
8058
8050
|
/**
|
|
@@ -8063,7 +8055,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8063
8055
|
* @returns a new RGB Color
|
|
8064
8056
|
*/
|
|
8065
8057
|
static LCHtoRGB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
8066
|
-
|
|
8058
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8067
8059
|
return _Color.LABtoRGB(_Color.LCHtoLAB(c), false, normalizedOutput);
|
|
8068
8060
|
}
|
|
8069
8061
|
/**
|
|
@@ -8074,7 +8066,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8074
8066
|
* @returns a new LUV Color
|
|
8075
8067
|
*/
|
|
8076
8068
|
static RGBtoLUV(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8077
|
-
|
|
8069
|
+
const c = normalizedInput ? rgb.$normalize(false) : rgb;
|
|
8078
8070
|
return _Color.XYZtoLUV(_Color.RGBtoXYZ(c), false, normalizedOutput);
|
|
8079
8071
|
}
|
|
8080
8072
|
/**
|
|
@@ -8085,7 +8077,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8085
8077
|
* @returns a new RGB Color
|
|
8086
8078
|
*/
|
|
8087
8079
|
static LUVtoRGB(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8088
|
-
|
|
8080
|
+
const c = normalizedInput ? luv.$normalize(false) : luv;
|
|
8089
8081
|
return _Color.XYZtoRGB(_Color.LUVtoXYZ(c), false, normalizedOutput);
|
|
8090
8082
|
}
|
|
8091
8083
|
/**
|
|
@@ -8096,13 +8088,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8096
8088
|
* @returns a new XYZ Color
|
|
8097
8089
|
*/
|
|
8098
8090
|
static RGBtoXYZ(rgb, normalizedInput = false, normalizedOutput = false) {
|
|
8099
|
-
|
|
8091
|
+
const c = !normalizedInput ? rgb.$normalize() : rgb.clone();
|
|
8100
8092
|
for (let i = 0; i < 3; i++) {
|
|
8101
8093
|
c[i] = c[i] > 0.04045 ? Math.pow((c[i] + 0.055) / 1.055, 2.4) : c[i] / 12.92;
|
|
8102
8094
|
if (!normalizedOutput)
|
|
8103
8095
|
c[i] = c[i] * 100;
|
|
8104
8096
|
}
|
|
8105
|
-
|
|
8097
|
+
const cc = _Color.xyz(
|
|
8106
8098
|
c[0] * 0.4124564 + c[1] * 0.3575761 + c[2] * 0.1804375,
|
|
8107
8099
|
c[0] * 0.2126729 + c[1] * 0.7151522 + c[2] * 0.072175,
|
|
8108
8100
|
c[0] * 0.0193339 + c[1] * 0.119192 + c[2] * 0.9503041,
|
|
@@ -8118,8 +8110,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8118
8110
|
* @returns a new RGB Color
|
|
8119
8111
|
*/
|
|
8120
8112
|
static XYZtoRGB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8121
|
-
|
|
8122
|
-
|
|
8113
|
+
const [x, y, z] = !normalizedInput ? xyz.$normalize() : xyz;
|
|
8114
|
+
const rgb = [
|
|
8123
8115
|
x * 3.2406254773200533 + y * -1.5372079722103187 + z * -0.4986285986982479,
|
|
8124
8116
|
x * -0.9689307147293197 + y * 1.8757560608852415 + z * 0.041517523842953964,
|
|
8125
8117
|
x * 0.055710120445510616 + y * -0.2040210505984867 + z * 1.0569959422543882
|
|
@@ -8130,7 +8122,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8130
8122
|
if (!normalizedOutput)
|
|
8131
8123
|
rgb[i] = Math.round(rgb[i] * 255);
|
|
8132
8124
|
}
|
|
8133
|
-
|
|
8125
|
+
const cc = _Color.rgb(rgb[0], rgb[1], rgb[2], xyz.alpha);
|
|
8134
8126
|
return normalizedOutput ? cc.normalize() : cc;
|
|
8135
8127
|
}
|
|
8136
8128
|
/**
|
|
@@ -8141,13 +8133,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8141
8133
|
* @returns a new LAB Color
|
|
8142
8134
|
*/
|
|
8143
8135
|
static XYZtoLAB(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8144
|
-
|
|
8136
|
+
const c = normalizedInput ? xyz.$normalize(false) : xyz.clone();
|
|
8145
8137
|
const eps = 0.00885645167;
|
|
8146
8138
|
const kap = 903.296296296;
|
|
8147
8139
|
c.divide(_Color.D65);
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8140
|
+
const fn = (n) => n > eps ? Math.pow(n, 1 / 3) : (kap * n + 16) / 116;
|
|
8141
|
+
const cy = fn(c[1]);
|
|
8142
|
+
const cc = _Color.lab(
|
|
8151
8143
|
116 * cy - 16,
|
|
8152
8144
|
500 * (fn(c[0]) - cy),
|
|
8153
8145
|
200 * (cy - fn(c[2])),
|
|
@@ -8163,16 +8155,16 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8163
8155
|
* @returns a new XYZ Color
|
|
8164
8156
|
*/
|
|
8165
8157
|
static LABtoXYZ(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8158
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8159
|
+
const y = (c[0] + 16) / 116;
|
|
8160
|
+
const x = c[1] / 500 + y;
|
|
8161
|
+
const z = y - c[2] / 200;
|
|
8170
8162
|
const eps = 0.00885645167;
|
|
8171
8163
|
const kap = 903.296296296;
|
|
8172
|
-
|
|
8164
|
+
const d = _Color.D65;
|
|
8173
8165
|
const xxx = Math.pow(x, 3);
|
|
8174
8166
|
const zzz = Math.pow(z, 3);
|
|
8175
|
-
|
|
8167
|
+
const cc = _Color.xyz(
|
|
8176
8168
|
d[0] * (xxx > eps ? xxx : (116 * x - 16) / kap),
|
|
8177
8169
|
d[1] * (c[0] > kap * eps ? Math.pow((c[0] + 16) / 116, 3) : c[0] / kap),
|
|
8178
8170
|
d[2] * (zzz > eps ? zzz : (116 * z - 16) / kap),
|
|
@@ -8189,13 +8181,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8189
8181
|
*/
|
|
8190
8182
|
static XYZtoLUV(xyz, normalizedInput = false, normalizedOutput = false) {
|
|
8191
8183
|
let [x, y, z] = normalizedInput ? xyz.$normalize(false) : xyz;
|
|
8192
|
-
|
|
8193
|
-
|
|
8184
|
+
const u = 4 * x / (x + 15 * y + 3 * z);
|
|
8185
|
+
const v = 9 * y / (x + 15 * y + 3 * z);
|
|
8194
8186
|
y = y / 100;
|
|
8195
8187
|
y = y > 8856e-6 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8188
|
+
const refU = 4 * _Color.D65[0] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8189
|
+
const refV = 9 * _Color.D65[1] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8190
|
+
const L = 116 * y - 16;
|
|
8199
8191
|
return _Color.luv(
|
|
8200
8192
|
L,
|
|
8201
8193
|
13 * L * (u - refU),
|
|
@@ -8213,15 +8205,15 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8213
8205
|
static LUVtoXYZ(luv, normalizedInput = false, normalizedOutput = false) {
|
|
8214
8206
|
let [l, u, v] = normalizedInput ? luv.$normalize(false) : luv;
|
|
8215
8207
|
let y = (l + 16) / 116;
|
|
8216
|
-
|
|
8208
|
+
const cubeY = y * y * y;
|
|
8217
8209
|
y = cubeY > 8856e-6 ? cubeY : (y - 16 / 116) / 7.787;
|
|
8218
|
-
|
|
8219
|
-
|
|
8210
|
+
const refU = 4 * _Color.D65[0] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8211
|
+
const refV = 9 * _Color.D65[1] / (_Color.D65[0] + 15 * _Color.D65[1] + 3 * _Color.D65[2]);
|
|
8220
8212
|
u = u / (13 * l) + refU;
|
|
8221
8213
|
v = v / (13 * l) + refV;
|
|
8222
8214
|
y = y * 100;
|
|
8223
|
-
|
|
8224
|
-
|
|
8215
|
+
const x = -1 * (9 * y * u) / ((u - 4) * v - u * v);
|
|
8216
|
+
const z = (9 * y - 15 * v * y - v * x) / (3 * v);
|
|
8225
8217
|
return _Color.xyz(x, y, z, luv.alpha);
|
|
8226
8218
|
}
|
|
8227
8219
|
/**
|
|
@@ -8232,8 +8224,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8232
8224
|
* @returns a new LCH Color
|
|
8233
8225
|
*/
|
|
8234
8226
|
static LABtoLCH(lab, normalizedInput = false, normalizedOutput = false) {
|
|
8235
|
-
|
|
8236
|
-
|
|
8227
|
+
const c = normalizedInput ? lab.$normalize(false) : lab;
|
|
8228
|
+
const h = Geom.toDegree(Geom.boundRadian(Math.atan2(c[2], c[1])));
|
|
8237
8229
|
return _Color.lch(
|
|
8238
8230
|
c[0],
|
|
8239
8231
|
Math.sqrt(c[1] * c[1] + c[2] * c[2]),
|
|
@@ -8249,8 +8241,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8249
8241
|
* @returns a new LAB Color
|
|
8250
8242
|
*/
|
|
8251
8243
|
static LCHtoLAB(lch, normalizedInput = false, normalizedOutput = false) {
|
|
8252
|
-
|
|
8253
|
-
|
|
8244
|
+
const c = normalizedInput ? lch.$normalize(false) : lch;
|
|
8245
|
+
const rad = Geom.toRadian(c[2]);
|
|
8254
8246
|
return _Color.lab(
|
|
8255
8247
|
c[0],
|
|
8256
8248
|
Math.cos(rad) * c[1],
|
|
@@ -8259,13 +8251,12 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8259
8251
|
);
|
|
8260
8252
|
}
|
|
8261
8253
|
};
|
|
8262
|
-
var Color = _Color;
|
|
8263
8254
|
// XYZ property for Standard Observer 2deg, Daylight/sRGB illuminant D65
|
|
8264
|
-
|
|
8255
|
+
_Color.D65 = new Pt(95.047, 100, 108.883, 1);
|
|
8265
8256
|
/**
|
|
8266
8257
|
* Value range for each color space
|
|
8267
8258
|
*/
|
|
8268
|
-
|
|
8259
|
+
_Color.ranges = {
|
|
8269
8260
|
rgb: new Group(new Pt(0, 255), new Pt(0, 255), new Pt(0, 255)),
|
|
8270
8261
|
hsl: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
8271
8262
|
hsb: new Group(new Pt(0, 360), new Pt(0, 1), new Pt(0, 1)),
|
|
@@ -8274,6 +8265,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8274
8265
|
luv: new Group(new Pt(0, 100), new Pt(-134, 220), new Pt(-140, 122)),
|
|
8275
8266
|
xyz: new Group(new Pt(0, 100), new Pt(0, 100), new Pt(0, 100))
|
|
8276
8267
|
};
|
|
8268
|
+
var Color = _Color;
|
|
8277
8269
|
|
|
8278
8270
|
// src/Dom.ts
|
|
8279
8271
|
var Dom_exports = {};
|
|
@@ -8282,7 +8274,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8282
8274
|
HTMLForm: () => HTMLForm,
|
|
8283
8275
|
HTMLSpace: () => HTMLSpace
|
|
8284
8276
|
});
|
|
8285
|
-
var DOMSpace = class extends MultiTouchSpace {
|
|
8277
|
+
var DOMSpace = class _DOMSpace extends MultiTouchSpace {
|
|
8286
8278
|
/**
|
|
8287
8279
|
* Create a DOMSpace for HTML DOM elements
|
|
8288
8280
|
* @param elem Specify an element by its "id" attribute as string, or by the element object itself. Use css to customize its appearance if needed.
|
|
@@ -8295,8 +8287,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8295
8287
|
this._autoResize = true;
|
|
8296
8288
|
this._bgcolor = "#e1e9f0";
|
|
8297
8289
|
this._css = {};
|
|
8298
|
-
|
|
8299
|
-
|
|
8290
|
+
let _selector = null;
|
|
8291
|
+
let _existed = false;
|
|
8300
8292
|
this.id = "pts";
|
|
8301
8293
|
if (elem instanceof Element) {
|
|
8302
8294
|
_selector = elem;
|
|
@@ -8307,8 +8299,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8307
8299
|
this.id = elem.substr(1);
|
|
8308
8300
|
}
|
|
8309
8301
|
if (!_selector) {
|
|
8310
|
-
this._container =
|
|
8311
|
-
this._canvas =
|
|
8302
|
+
this._container = _DOMSpace.createElement("div", "pts_container");
|
|
8303
|
+
this._canvas = _DOMSpace.createElement("div", "pts_element");
|
|
8312
8304
|
this._container.appendChild(this._canvas);
|
|
8313
8305
|
document.body.appendChild(this._container);
|
|
8314
8306
|
_existed = false;
|
|
@@ -8570,7 +8562,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8570
8562
|
return super.removeAll();
|
|
8571
8563
|
}
|
|
8572
8564
|
};
|
|
8573
|
-
var _HTMLForm = class extends VisualForm {
|
|
8565
|
+
var _HTMLForm = class _HTMLForm extends VisualForm {
|
|
8574
8566
|
/**
|
|
8575
8567
|
* Create a new `HTMLForm`. Alternatively, you can use [`HTMLSpace.getForm`](#link) function to get an instance of HTMLForm.
|
|
8576
8568
|
* @param space the space to use
|
|
@@ -8989,9 +8981,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8989
8981
|
return this;
|
|
8990
8982
|
}
|
|
8991
8983
|
};
|
|
8984
|
+
_HTMLForm.groupID = 0;
|
|
8985
|
+
_HTMLForm.domID = 0;
|
|
8992
8986
|
var HTMLForm = _HTMLForm;
|
|
8993
|
-
HTMLForm.groupID = 0;
|
|
8994
|
-
HTMLForm.domID = 0;
|
|
8995
8987
|
|
|
8996
8988
|
// src/Svg.ts
|
|
8997
8989
|
var Svg_exports = {};
|
|
@@ -8999,7 +8991,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
8999
8991
|
SVGForm: () => SVGForm,
|
|
9000
8992
|
SVGSpace: () => SVGSpace
|
|
9001
8993
|
});
|
|
9002
|
-
var SVGSpace = class extends DOMSpace {
|
|
8994
|
+
var SVGSpace = class _SVGSpace extends DOMSpace {
|
|
9003
8995
|
/**
|
|
9004
8996
|
* Create a SVGSpace which represents a Space for SVG elements.
|
|
9005
8997
|
* @param elem Specify an element by its "id" attribute as string, or by the element object itself. An element can be an existing `<svg>`, or a `<div>` container in which a new `<svg>` will be created. If left empty, a `<div id="pt_container"><svg id="pt" /></div>` will be added to DOM. Use css to customize its appearance if needed.
|
|
@@ -9010,7 +9002,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9010
9002
|
super(elem, callback);
|
|
9011
9003
|
this._bgcolor = "#999";
|
|
9012
9004
|
if (this._canvas.nodeName.toLowerCase() != "svg") {
|
|
9013
|
-
let s =
|
|
9005
|
+
let s = _SVGSpace.svgElement(this._canvas, "svg", `${this.id}_svg`);
|
|
9014
9006
|
this._container = this._canvas;
|
|
9015
9007
|
this._canvas = s;
|
|
9016
9008
|
}
|
|
@@ -9036,7 +9028,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9036
9028
|
*/
|
|
9037
9029
|
resize(b, evt) {
|
|
9038
9030
|
super.resize(b, evt);
|
|
9039
|
-
|
|
9031
|
+
_SVGSpace.setAttr(this.element, {
|
|
9040
9032
|
"viewBox": `0 0 ${this.bound.width} ${this.bound.height}`,
|
|
9041
9033
|
"width": `${this.bound.width}`,
|
|
9042
9034
|
"height": `${this.bound.height}`,
|
|
@@ -9081,7 +9073,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9081
9073
|
return super.removeAll();
|
|
9082
9074
|
}
|
|
9083
9075
|
};
|
|
9084
|
-
var _SVGForm = class extends VisualForm {
|
|
9076
|
+
var _SVGForm = class _SVGForm extends VisualForm {
|
|
9085
9077
|
/**
|
|
9086
9078
|
* Create a new SVGForm. You may also use [`SVGSpace.getForm`](#link) to get a default form directly.
|
|
9087
9079
|
* @param space an instance of SVGSpace
|
|
@@ -9575,9 +9567,9 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9575
9567
|
return this;
|
|
9576
9568
|
}
|
|
9577
9569
|
};
|
|
9570
|
+
_SVGForm.groupID = 0;
|
|
9571
|
+
_SVGForm.domID = 0;
|
|
9578
9572
|
var SVGForm = _SVGForm;
|
|
9579
|
-
SVGForm.groupID = 0;
|
|
9580
|
-
SVGForm.domID = 0;
|
|
9581
9573
|
|
|
9582
9574
|
// src/Physics.ts
|
|
9583
9575
|
var Physics_exports = {};
|
|
@@ -9586,7 +9578,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9586
9578
|
Particle: () => Particle,
|
|
9587
9579
|
World: () => World
|
|
9588
9580
|
});
|
|
9589
|
-
var World = class {
|
|
9581
|
+
var World = class _World {
|
|
9590
9582
|
/**
|
|
9591
9583
|
* Create a `World` for 2D physics simulation.
|
|
9592
9584
|
* @param bound a Group or an Iterable<Pt> representing a rectangular bounding box
|
|
@@ -9674,13 +9666,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9674
9666
|
* @returns a Body, or undefined if not found
|
|
9675
9667
|
*/
|
|
9676
9668
|
body(id) {
|
|
9677
|
-
let idx = id;
|
|
9678
9669
|
if (typeof id === "string" && id.length > 0) {
|
|
9679
|
-
|
|
9670
|
+
return this._bodies[this._bnames.indexOf(id)];
|
|
9680
9671
|
}
|
|
9681
|
-
|
|
9682
|
-
return void 0;
|
|
9683
|
-
return this._bodies[idx];
|
|
9672
|
+
return typeof id === "number" && id >= 0 ? this._bodies[id] : void 0;
|
|
9684
9673
|
}
|
|
9685
9674
|
/**
|
|
9686
9675
|
* Get a particle in this world by index or string id.
|
|
@@ -9688,13 +9677,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9688
9677
|
* @returns a Particle, or undefined if not found
|
|
9689
9678
|
*/
|
|
9690
9679
|
particle(id) {
|
|
9691
|
-
let idx = id;
|
|
9692
9680
|
if (typeof id === "string" && id.length > 0) {
|
|
9693
|
-
|
|
9681
|
+
return this._particles[this._pnames.indexOf(id)];
|
|
9694
9682
|
}
|
|
9695
|
-
|
|
9696
|
-
return void 0;
|
|
9697
|
-
return this._particles[idx];
|
|
9683
|
+
return typeof id === "number" && id >= 0 ? this._particles[id] : void 0;
|
|
9698
9684
|
}
|
|
9699
9685
|
/**
|
|
9700
9686
|
* Given a body's name, return its index in the bodies array, or -1 if not found.
|
|
@@ -9841,7 +9827,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9841
9827
|
for (let i = 0, len = this._particles.length; i < len; i++) {
|
|
9842
9828
|
let p = this._particles[i];
|
|
9843
9829
|
this.integrate(p, dt, this._lastTime);
|
|
9844
|
-
|
|
9830
|
+
_World.boundConstraint(p, this._bound, this._damping);
|
|
9845
9831
|
for (let k = i + 1; k < len; k++) {
|
|
9846
9832
|
if (i !== k) {
|
|
9847
9833
|
let p2 = this._particles[k];
|
|
@@ -9862,7 +9848,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
9862
9848
|
if (bds) {
|
|
9863
9849
|
for (let k = 0, klen = bds.length; k < klen; k++) {
|
|
9864
9850
|
let bk = bds[k];
|
|
9865
|
-
|
|
9851
|
+
_World.boundConstraint(bk, this._bound, this._damping);
|
|
9866
9852
|
this.integrate(bk, dt, this._lastTime);
|
|
9867
9853
|
}
|
|
9868
9854
|
for (let k = i + 1; k < len; k++) {
|
|
@@ -10045,7 +10031,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10045
10031
|
return `Particle: ${this[0]} ${this[1]} | previous ${this._prev[0]} ${this._prev[1]} | mass ${this._mass}`;
|
|
10046
10032
|
}
|
|
10047
10033
|
};
|
|
10048
|
-
var Body = class extends Group {
|
|
10034
|
+
var Body = class _Body extends Group {
|
|
10049
10035
|
/**
|
|
10050
10036
|
* Create an empty Body, this is usually followed by [`Body.init`](#link) to populate the Body. Alternatively, use static function [`Body.fromGroup`](#link) to create and initate a body directly.
|
|
10051
10037
|
*/
|
|
@@ -10064,7 +10050,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10064
10050
|
* @param autoMass Automatically calculate the mass based on the area of the polygon. Default is true.
|
|
10065
10051
|
*/
|
|
10066
10052
|
static fromGroup(body, stiff = 1, autoLink = true, autoMass = true) {
|
|
10067
|
-
let b = new
|
|
10053
|
+
let b = new _Body().init(body);
|
|
10068
10054
|
if (autoLink)
|
|
10069
10055
|
b.linkAll(stiff);
|
|
10070
10056
|
if (autoMass)
|
|
@@ -10224,7 +10210,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10224
10210
|
Sound: () => Sound,
|
|
10225
10211
|
Tempo: () => Tempo
|
|
10226
10212
|
});
|
|
10227
|
-
var Tempo = class {
|
|
10213
|
+
var Tempo = class _Tempo {
|
|
10228
10214
|
/**
|
|
10229
10215
|
* Construct a new Tempo instance by beats-per-minute. Alternatively, you can use [`Tempo.fromBeat`](#link) to create from milliseconds.
|
|
10230
10216
|
* @param bpm beats per minute
|
|
@@ -10240,7 +10226,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10240
10226
|
* @param ms milliseconds per beat
|
|
10241
10227
|
*/
|
|
10242
10228
|
static fromBeat(ms) {
|
|
10243
|
-
return new
|
|
10229
|
+
return new _Tempo(6e4 / ms);
|
|
10244
10230
|
}
|
|
10245
10231
|
/**
|
|
10246
10232
|
* Beats-per-minute value
|
|
@@ -10282,16 +10268,16 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10282
10268
|
* @returns an object with chainable functions
|
|
10283
10269
|
*/
|
|
10284
10270
|
every(beats) {
|
|
10285
|
-
|
|
10286
|
-
|
|
10271
|
+
const self = this;
|
|
10272
|
+
const p = Array.isArray(beats) ? beats[0] : beats;
|
|
10287
10273
|
return {
|
|
10288
10274
|
start: function(fn, offset = 0, name) {
|
|
10289
|
-
|
|
10275
|
+
const id = name || self._createID(fn);
|
|
10290
10276
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: false, fn };
|
|
10291
10277
|
return this;
|
|
10292
10278
|
},
|
|
10293
10279
|
progress: function(fn, offset = 0, name) {
|
|
10294
|
-
|
|
10280
|
+
const id = name || self._createID(fn);
|
|
10295
10281
|
self._listeners[id] = { name: id, beats, period: p, index: 0, offset, duration: -1, continuous: true, fn };
|
|
10296
10282
|
return this;
|
|
10297
10283
|
}
|
|
@@ -10303,11 +10289,11 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10303
10289
|
* @param time current time in milliseconds
|
|
10304
10290
|
*/
|
|
10305
10291
|
track(time) {
|
|
10306
|
-
for (
|
|
10292
|
+
for (const k in this._listeners) {
|
|
10307
10293
|
if (this._listeners.hasOwnProperty(k)) {
|
|
10308
|
-
|
|
10309
|
-
|
|
10310
|
-
|
|
10294
|
+
const li = this._listeners[k];
|
|
10295
|
+
const _t = li.offset ? time + li.offset : time;
|
|
10296
|
+
const ms = li.period * this._ms;
|
|
10311
10297
|
let isStart = false;
|
|
10312
10298
|
if (_t > li.duration + ms) {
|
|
10313
10299
|
li.duration = _t - _t % this._ms;
|
|
@@ -10317,10 +10303,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10317
10303
|
}
|
|
10318
10304
|
isStart = true;
|
|
10319
10305
|
}
|
|
10320
|
-
|
|
10321
|
-
|
|
10306
|
+
const count = Math.max(0, Math.ceil(Math.floor(li.duration / this._ms) / li.period));
|
|
10307
|
+
const params = li.continuous ? [count, Num.clamp((_t - li.duration) / ms, 0, 1), _t, isStart] : [count];
|
|
10322
10308
|
if (li.continuous || isStart) {
|
|
10323
|
-
|
|
10309
|
+
const done = li.fn.apply(li, params);
|
|
10324
10310
|
if (done)
|
|
10325
10311
|
delete this._listeners[li.name];
|
|
10326
10312
|
}
|
|
@@ -10354,7 +10340,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10354
10340
|
return;
|
|
10355
10341
|
}
|
|
10356
10342
|
};
|
|
10357
|
-
var Sound = class {
|
|
10343
|
+
var Sound = class _Sound {
|
|
10358
10344
|
// Tracking play time against ctx.currentTime
|
|
10359
10345
|
/**
|
|
10360
10346
|
* Construct a `Sound` instance. Usually, it's more convenient to use one of the static methods like [`Sound.load`](#function_load) or [`Sound.from`](#function_from).
|
|
@@ -10369,7 +10355,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10369
10355
|
* Create an AudioContext instance. This is called internally only.
|
|
10370
10356
|
*/
|
|
10371
10357
|
_createAudioContext() {
|
|
10372
|
-
|
|
10358
|
+
const _ctx = window.AudioContext;
|
|
10373
10359
|
if (!_ctx)
|
|
10374
10360
|
throw new Error("Your browser doesn't support Web Audio. (No AudioContext)");
|
|
10375
10361
|
this._ctx = _ctx ? new _ctx() : void 0;
|
|
@@ -10383,7 +10369,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10383
10369
|
* @returns a `Sound` instance
|
|
10384
10370
|
*/
|
|
10385
10371
|
static from(node, ctx, type = "gen", stream) {
|
|
10386
|
-
|
|
10372
|
+
const s = new _Sound(type);
|
|
10387
10373
|
s._node = node;
|
|
10388
10374
|
s._ctx = ctx;
|
|
10389
10375
|
if (stream)
|
|
@@ -10399,7 +10385,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10399
10385
|
*/
|
|
10400
10386
|
static load(source, crossOrigin = "anonymous") {
|
|
10401
10387
|
return new Promise((resolve, reject) => {
|
|
10402
|
-
|
|
10388
|
+
const s = new _Sound("file");
|
|
10403
10389
|
s._source = typeof source === "string" ? new Audio(source) : source;
|
|
10404
10390
|
s._source.autoplay = false;
|
|
10405
10391
|
s._source.crossOrigin = crossOrigin;
|
|
@@ -10424,10 +10410,10 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10424
10410
|
*/
|
|
10425
10411
|
static loadAsBuffer(url) {
|
|
10426
10412
|
return new Promise((resolve, reject) => {
|
|
10427
|
-
|
|
10413
|
+
const request = new XMLHttpRequest();
|
|
10428
10414
|
request.open("GET", url, true);
|
|
10429
10415
|
request.responseType = "arraybuffer";
|
|
10430
|
-
|
|
10416
|
+
const s = new _Sound("file");
|
|
10431
10417
|
request.onload = function() {
|
|
10432
10418
|
s._ctx.decodeAudioData(request.response, function(buffer) {
|
|
10433
10419
|
s.createBuffer(buffer);
|
|
@@ -10459,13 +10445,13 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10459
10445
|
* @example `Sound.generate( 'sine', 120 )`
|
|
10460
10446
|
*/
|
|
10461
10447
|
static generate(type, val) {
|
|
10462
|
-
|
|
10448
|
+
const s = new _Sound("gen");
|
|
10463
10449
|
return s._gen(type, val);
|
|
10464
10450
|
}
|
|
10465
10451
|
// Create the oscillator
|
|
10466
10452
|
_gen(type, val) {
|
|
10467
10453
|
this._node = this._ctx.createOscillator();
|
|
10468
|
-
|
|
10454
|
+
const osc = this._node;
|
|
10469
10455
|
osc.type = type;
|
|
10470
10456
|
if (type === "custom") {
|
|
10471
10457
|
osc.setPeriodicWave(val);
|
|
@@ -10483,7 +10469,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10483
10469
|
static input(constraint) {
|
|
10484
10470
|
return __async(this, null, function* () {
|
|
10485
10471
|
try {
|
|
10486
|
-
|
|
10472
|
+
const s = new _Sound("input");
|
|
10487
10473
|
if (!s)
|
|
10488
10474
|
return void 0;
|
|
10489
10475
|
const c = constraint ? constraint : { audio: true, video: false };
|
|
@@ -10553,7 +10539,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10553
10539
|
get progress() {
|
|
10554
10540
|
let dur = 0;
|
|
10555
10541
|
let curr = 0;
|
|
10556
|
-
if (
|
|
10542
|
+
if (this._buffer) {
|
|
10557
10543
|
dur = this._buffer.duration;
|
|
10558
10544
|
curr = this._timestamp ? this._ctx.currentTime - this._timestamp : 0;
|
|
10559
10545
|
} else {
|
|
@@ -10625,7 +10611,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10625
10611
|
* @param smooth Optional smoothing value (corresponds to `AnalyserNode.smoothingTimeConstant`)
|
|
10626
10612
|
*/
|
|
10627
10613
|
analyze(size = 256, minDb = -100, maxDb = -30, smooth = 0.8) {
|
|
10628
|
-
|
|
10614
|
+
const a = this._ctx.createAnalyser();
|
|
10629
10615
|
a.fftSize = size * 2;
|
|
10630
10616
|
a.minDecibels = minDb;
|
|
10631
10617
|
a.maxDecibels = maxDb;
|
|
@@ -10652,8 +10638,8 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10652
10638
|
}
|
|
10653
10639
|
// Map domain data to another range
|
|
10654
10640
|
_domainTo(time, size, position = [0, 0], trim = [0, 0]) {
|
|
10655
|
-
|
|
10656
|
-
|
|
10641
|
+
const data = time ? this.timeDomain() : this.freqDomain();
|
|
10642
|
+
const g = new Group();
|
|
10657
10643
|
for (let i = trim[0], len = data.length - trim[1]; i < len; i++) {
|
|
10658
10644
|
g.push(new Pt(position[0] + size[0] * i / len, position[1] + size[1] * data[i] / 255));
|
|
10659
10645
|
}
|
|
@@ -10712,7 +10698,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10712
10698
|
this._ctx.resume();
|
|
10713
10699
|
}
|
|
10714
10700
|
if (this._type === "file") {
|
|
10715
|
-
if (
|
|
10701
|
+
if (this._buffer) {
|
|
10716
10702
|
this._node.start(timeAt);
|
|
10717
10703
|
this._timestamp = this._ctx.currentTime + timeAt;
|
|
10718
10704
|
} else {
|
|
@@ -10737,7 +10723,7 @@ See https://github.com/williamngan/pts for details. */
|
|
|
10737
10723
|
if (this._playing)
|
|
10738
10724
|
(this._outputNode || this._node).disconnect(this._ctx.destination);
|
|
10739
10725
|
if (this._type === "file") {
|
|
10740
|
-
if (
|
|
10726
|
+
if (this._buffer) {
|
|
10741
10727
|
if (this.progress < 1)
|
|
10742
10728
|
this._node.stop();
|
|
10743
10729
|
} else {
|