modern-path2d 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +338 -265
- package/dist/index.d.cts +133 -78
- package/dist/index.d.mts +133 -78
- package/dist/index.d.ts +133 -78
- package/dist/index.js +1 -1
- package/dist/index.mjs +333 -266
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const lineJoinMap = {
|
|
4
|
+
"arcs": "bevel",
|
|
5
|
+
"bevel": "bevel",
|
|
6
|
+
"miter": "miter",
|
|
7
|
+
"miter-clip": "miter",
|
|
8
|
+
"round": "round"
|
|
9
|
+
};
|
|
10
|
+
function setCanvasContextByPath(ctx, path) {
|
|
11
|
+
const {
|
|
12
|
+
fill = "#000",
|
|
13
|
+
stroke = "none",
|
|
14
|
+
strokeWidth = stroke === "none" ? 0 : 1,
|
|
15
|
+
strokeLinecap = "round",
|
|
16
|
+
strokeLinejoin = "miter",
|
|
17
|
+
strokeMiterlimit = 0,
|
|
18
|
+
strokeDasharray,
|
|
19
|
+
strokeDashoffset = 0
|
|
20
|
+
} = path.style;
|
|
21
|
+
ctx.fillStyle = fill;
|
|
22
|
+
ctx.strokeStyle = stroke;
|
|
23
|
+
ctx.lineWidth = strokeWidth;
|
|
24
|
+
ctx.lineCap = strokeLinecap;
|
|
25
|
+
ctx.lineJoin = lineJoinMap[strokeLinejoin];
|
|
26
|
+
ctx.miterLimit = strokeMiterlimit;
|
|
27
|
+
ctx.lineDashOffset = strokeDashoffset;
|
|
28
|
+
strokeDasharray && ctx.setLineDash(strokeDasharray);
|
|
29
|
+
}
|
|
30
|
+
|
|
3
31
|
class Vector2 {
|
|
4
32
|
constructor(x = 0, y = 0) {
|
|
5
33
|
this.x = x;
|
|
@@ -384,221 +412,175 @@ function parseArcCommand(path, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, s
|
|
|
384
412
|
const cy = Math.sin(xAxisRotation) * cxp + Math.cos(xAxisRotation) * cyp + (start.y + end.y) / 2;
|
|
385
413
|
const theta = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
|
|
386
414
|
const delta = svgAngle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry) % (Math.PI * 2);
|
|
387
|
-
path.
|
|
415
|
+
path.ellipse(cx, cy, rx, ry, xAxisRotation, theta, theta + delta, sweepFlag === 1);
|
|
388
416
|
}
|
|
389
417
|
|
|
390
418
|
function getReflection(a, b) {
|
|
391
419
|
return a - (b - a);
|
|
392
420
|
}
|
|
393
421
|
function addPathCommandsToPath2D(commands, path) {
|
|
394
|
-
const
|
|
422
|
+
const current = new Vector2();
|
|
395
423
|
const control = new Vector2();
|
|
396
|
-
const firstPoint = new Vector2();
|
|
397
|
-
let isFirstPoint = true;
|
|
398
|
-
let doSetFirstPoint = false;
|
|
399
424
|
for (let i = 0, l = commands.length; i < l; i++) {
|
|
400
|
-
const
|
|
401
|
-
if (
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
405
|
-
if (command.type === "m" || command.type === "M") {
|
|
406
|
-
if (command.type === "m") {
|
|
407
|
-
point.x += command.x;
|
|
408
|
-
point.y += command.y;
|
|
425
|
+
const cmd = commands[i];
|
|
426
|
+
if (cmd.type === "m" || cmd.type === "M") {
|
|
427
|
+
if (cmd.type === "m") {
|
|
428
|
+
current.add(cmd);
|
|
409
429
|
} else {
|
|
410
|
-
|
|
411
|
-
point.y = command.y;
|
|
430
|
+
current.copy(cmd);
|
|
412
431
|
}
|
|
413
|
-
|
|
414
|
-
control.
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
if (command.type === "h") {
|
|
419
|
-
point.x += command.x;
|
|
432
|
+
path.moveTo(current.x, current.y);
|
|
433
|
+
control.copy(current);
|
|
434
|
+
} else if (cmd.type === "h" || cmd.type === "H") {
|
|
435
|
+
if (cmd.type === "h") {
|
|
436
|
+
current.x += cmd.x;
|
|
420
437
|
} else {
|
|
421
|
-
|
|
438
|
+
current.x = cmd.x;
|
|
422
439
|
}
|
|
423
|
-
|
|
424
|
-
control.
|
|
425
|
-
|
|
426
|
-
if (
|
|
427
|
-
|
|
428
|
-
} else if (command.type === "v" || command.type === "V") {
|
|
429
|
-
if (command.type === "v") {
|
|
430
|
-
point.y += command.y;
|
|
440
|
+
path.lineTo(current.x, current.y);
|
|
441
|
+
control.copy(current);
|
|
442
|
+
} else if (cmd.type === "v" || cmd.type === "V") {
|
|
443
|
+
if (cmd.type === "v") {
|
|
444
|
+
current.y += cmd.y;
|
|
431
445
|
} else {
|
|
432
|
-
|
|
446
|
+
current.y = cmd.y;
|
|
433
447
|
}
|
|
434
|
-
|
|
435
|
-
control.
|
|
436
|
-
|
|
437
|
-
if (
|
|
438
|
-
|
|
439
|
-
} else if (command.type === "l" || command.type === "L") {
|
|
440
|
-
if (command.type === "l") {
|
|
441
|
-
point.x += command.x;
|
|
442
|
-
point.y += command.y;
|
|
448
|
+
path.lineTo(current.x, current.y);
|
|
449
|
+
control.copy(current);
|
|
450
|
+
} else if (cmd.type === "l" || cmd.type === "L") {
|
|
451
|
+
if (cmd.type === "l") {
|
|
452
|
+
current.add(cmd);
|
|
443
453
|
} else {
|
|
444
|
-
|
|
445
|
-
point.y = command.y;
|
|
454
|
+
current.copy(cmd);
|
|
446
455
|
}
|
|
447
|
-
|
|
448
|
-
control.
|
|
449
|
-
|
|
450
|
-
if (
|
|
451
|
-
firstPoint.copy(point);
|
|
452
|
-
} else if (command.type === "c" || command.type === "C") {
|
|
453
|
-
if (command.type === "c") {
|
|
456
|
+
path.lineTo(current.x, current.y);
|
|
457
|
+
control.copy(current);
|
|
458
|
+
} else if (cmd.type === "c" || cmd.type === "C") {
|
|
459
|
+
if (cmd.type === "c") {
|
|
454
460
|
path.bezierCurveTo(
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
+
current.x + cmd.x1,
|
|
462
|
+
current.y + cmd.y1,
|
|
463
|
+
current.x + cmd.x2,
|
|
464
|
+
current.y + cmd.y2,
|
|
465
|
+
current.x + cmd.x,
|
|
466
|
+
current.y + cmd.y
|
|
461
467
|
);
|
|
462
|
-
control.x =
|
|
463
|
-
control.y =
|
|
464
|
-
|
|
465
|
-
point.y += command.y;
|
|
468
|
+
control.x = current.x + cmd.x2;
|
|
469
|
+
control.y = current.y + cmd.y2;
|
|
470
|
+
current.add(cmd);
|
|
466
471
|
} else {
|
|
467
472
|
path.bezierCurveTo(
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
473
|
+
cmd.x1,
|
|
474
|
+
cmd.y1,
|
|
475
|
+
cmd.x2,
|
|
476
|
+
cmd.y2,
|
|
477
|
+
cmd.x,
|
|
478
|
+
cmd.y
|
|
474
479
|
);
|
|
475
|
-
control.x =
|
|
476
|
-
control.y =
|
|
477
|
-
|
|
478
|
-
point.y = command.y;
|
|
480
|
+
control.x = cmd.x2;
|
|
481
|
+
control.y = cmd.y2;
|
|
482
|
+
current.copy(cmd);
|
|
479
483
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
} else if (command.type === "s" || command.type === "S") {
|
|
483
|
-
if (command.type === "s") {
|
|
484
|
+
} else if (cmd.type === "s" || cmd.type === "S") {
|
|
485
|
+
if (cmd.type === "s") {
|
|
484
486
|
path.bezierCurveTo(
|
|
485
|
-
getReflection(
|
|
486
|
-
getReflection(
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
487
|
+
getReflection(current.x, control.x),
|
|
488
|
+
getReflection(current.y, control.y),
|
|
489
|
+
current.x + cmd.x2,
|
|
490
|
+
current.y + cmd.y2,
|
|
491
|
+
current.x + cmd.x,
|
|
492
|
+
current.y + cmd.y
|
|
491
493
|
);
|
|
492
|
-
control.x =
|
|
493
|
-
control.y =
|
|
494
|
-
|
|
495
|
-
point.y += command.y;
|
|
494
|
+
control.x = current.x + cmd.x2;
|
|
495
|
+
control.y = current.y + cmd.y2;
|
|
496
|
+
current.add(cmd);
|
|
496
497
|
} else {
|
|
497
498
|
path.bezierCurveTo(
|
|
498
|
-
getReflection(
|
|
499
|
-
getReflection(
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
499
|
+
getReflection(current.x, control.x),
|
|
500
|
+
getReflection(current.y, control.y),
|
|
501
|
+
cmd.x2,
|
|
502
|
+
cmd.y2,
|
|
503
|
+
cmd.x,
|
|
504
|
+
cmd.y
|
|
504
505
|
);
|
|
505
|
-
control.x =
|
|
506
|
-
control.y =
|
|
507
|
-
|
|
508
|
-
point.y = command.y;
|
|
506
|
+
control.x = cmd.x2;
|
|
507
|
+
control.y = cmd.y2;
|
|
508
|
+
current.copy(cmd);
|
|
509
509
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
} else if (command.type === "q" || command.type === "Q") {
|
|
513
|
-
if (command.type === "q") {
|
|
510
|
+
} else if (cmd.type === "q" || cmd.type === "Q") {
|
|
511
|
+
if (cmd.type === "q") {
|
|
514
512
|
path.quadraticCurveTo(
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
513
|
+
current.x + cmd.x1,
|
|
514
|
+
current.y + cmd.y1,
|
|
515
|
+
current.x + cmd.x,
|
|
516
|
+
current.y + cmd.y
|
|
519
517
|
);
|
|
520
|
-
control.x =
|
|
521
|
-
control.y =
|
|
522
|
-
|
|
523
|
-
point.y += command.y;
|
|
518
|
+
control.x = current.x + cmd.x1;
|
|
519
|
+
control.y = current.y + cmd.y1;
|
|
520
|
+
current.add(cmd);
|
|
524
521
|
} else {
|
|
525
522
|
path.quadraticCurveTo(
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
523
|
+
cmd.x1,
|
|
524
|
+
cmd.y1,
|
|
525
|
+
cmd.x,
|
|
526
|
+
cmd.y
|
|
530
527
|
);
|
|
531
|
-
control.x =
|
|
532
|
-
control.y =
|
|
533
|
-
|
|
534
|
-
point.y = command.y;
|
|
528
|
+
control.x = cmd.x1;
|
|
529
|
+
control.y = cmd.y1;
|
|
530
|
+
current.copy(cmd);
|
|
535
531
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
const rx = getReflection(point.x, control.x);
|
|
540
|
-
const ry = getReflection(point.y, control.y);
|
|
532
|
+
} else if (cmd.type === "t" || cmd.type === "T") {
|
|
533
|
+
const rx = getReflection(current.x, control.x);
|
|
534
|
+
const ry = getReflection(current.y, control.y);
|
|
541
535
|
control.x = rx;
|
|
542
536
|
control.y = ry;
|
|
543
|
-
if (
|
|
537
|
+
if (cmd.type === "t") {
|
|
544
538
|
path.quadraticCurveTo(
|
|
545
539
|
rx,
|
|
546
540
|
ry,
|
|
547
|
-
|
|
548
|
-
|
|
541
|
+
current.x + cmd.x,
|
|
542
|
+
current.y + cmd.y
|
|
549
543
|
);
|
|
550
|
-
|
|
551
|
-
point.y += command.y;
|
|
544
|
+
current.add(cmd);
|
|
552
545
|
} else {
|
|
553
546
|
path.quadraticCurveTo(
|
|
554
547
|
rx,
|
|
555
548
|
ry,
|
|
556
|
-
|
|
557
|
-
|
|
549
|
+
cmd.x,
|
|
550
|
+
cmd.y
|
|
558
551
|
);
|
|
559
|
-
|
|
560
|
-
point.y = command.y;
|
|
552
|
+
current.copy(cmd);
|
|
561
553
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if (command.x === 0 && command.y === 0)
|
|
554
|
+
} else if (cmd.type === "a" || cmd.type === "A") {
|
|
555
|
+
const start = current.clone();
|
|
556
|
+
if (cmd.type === "a") {
|
|
557
|
+
if (cmd.x === 0 && cmd.y === 0)
|
|
567
558
|
continue;
|
|
568
|
-
|
|
569
|
-
point.y += command.y;
|
|
559
|
+
current.add(cmd);
|
|
570
560
|
} else {
|
|
571
|
-
if (
|
|
561
|
+
if (current.equals(cmd))
|
|
572
562
|
continue;
|
|
573
|
-
|
|
574
|
-
point.y = command.y;
|
|
563
|
+
current.copy(cmd);
|
|
575
564
|
}
|
|
576
|
-
|
|
577
|
-
control.x = point.x;
|
|
578
|
-
control.y = point.y;
|
|
565
|
+
control.copy(current);
|
|
579
566
|
parseArcCommand(
|
|
580
567
|
path,
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
568
|
+
cmd.rx,
|
|
569
|
+
cmd.ry,
|
|
570
|
+
cmd.angle,
|
|
571
|
+
cmd.largeArcFlag,
|
|
572
|
+
cmd.sweepFlag,
|
|
586
573
|
start,
|
|
587
|
-
|
|
574
|
+
current
|
|
588
575
|
);
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
path.currentPath.autoClose = true;
|
|
593
|
-
if (path.currentPath.curves.length > 0) {
|
|
594
|
-
point.copy(firstPoint);
|
|
595
|
-
path.currentPath.currentPoint.copy(point);
|
|
596
|
-
isFirstPoint = true;
|
|
576
|
+
} else if (cmd.type === "z" || cmd.type === "Z") {
|
|
577
|
+
if (path.startPoint) {
|
|
578
|
+
current.copy(path.startPoint);
|
|
597
579
|
}
|
|
580
|
+
path.closePath();
|
|
598
581
|
} else {
|
|
599
|
-
console.warn("Unsupported commands",
|
|
582
|
+
console.warn("Unsupported commands", cmd);
|
|
600
583
|
}
|
|
601
|
-
doSetFirstPoint = false;
|
|
602
584
|
}
|
|
603
585
|
}
|
|
604
586
|
|
|
@@ -1189,15 +1171,15 @@ const tempTransform1$1 = new Matrix3();
|
|
|
1189
1171
|
const tempTransform2$1 = new Matrix3();
|
|
1190
1172
|
const tempV2 = new Vector2();
|
|
1191
1173
|
class EllipseCurve extends Curve {
|
|
1192
|
-
constructor(center = new Vector2(), radiusX = 1, radiusY = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false
|
|
1174
|
+
constructor(center = new Vector2(), radiusX = 1, radiusY = 1, rotation = 0, startAngle = 0, endAngle = Math.PI * 2, clockwise = false) {
|
|
1193
1175
|
super();
|
|
1194
1176
|
this.center = center;
|
|
1195
1177
|
this.radiusX = radiusX;
|
|
1196
1178
|
this.radiusY = radiusY;
|
|
1179
|
+
this.rotation = rotation;
|
|
1197
1180
|
this.startAngle = startAngle;
|
|
1198
1181
|
this.endAngle = endAngle;
|
|
1199
1182
|
this.clockwise = clockwise;
|
|
1200
|
-
this.rotation = rotation;
|
|
1201
1183
|
}
|
|
1202
1184
|
getPoint(t, output = new Vector2()) {
|
|
1203
1185
|
const twoPi = Math.PI * 2;
|
|
@@ -1881,27 +1863,36 @@ class CurvePath extends Curve {
|
|
|
1881
1863
|
constructor(points) {
|
|
1882
1864
|
super();
|
|
1883
1865
|
__publicField$1(this, "curves", []);
|
|
1866
|
+
__publicField$1(this, "startPoint");
|
|
1884
1867
|
__publicField$1(this, "currentPoint", new Vector2());
|
|
1885
1868
|
__publicField$1(this, "autoClose", false);
|
|
1886
1869
|
__publicField$1(this, "_cacheLengths", []);
|
|
1887
1870
|
if (points) {
|
|
1888
|
-
this.
|
|
1871
|
+
this.addPoints(points);
|
|
1889
1872
|
}
|
|
1890
1873
|
}
|
|
1891
1874
|
addCurve(curve) {
|
|
1892
1875
|
this.curves.push(curve);
|
|
1893
1876
|
return this;
|
|
1894
1877
|
}
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
this.
|
|
1878
|
+
addPoints(points) {
|
|
1879
|
+
this.moveTo(points[0].x, points[0].y);
|
|
1880
|
+
for (let i = 1, len = points.length; i < len; i++) {
|
|
1881
|
+
const { x, y } = points[i];
|
|
1882
|
+
this.lineTo(x, y);
|
|
1900
1883
|
}
|
|
1901
1884
|
return this;
|
|
1902
1885
|
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1886
|
+
addCommands(commands) {
|
|
1887
|
+
addPathCommandsToPath2D(commands, this);
|
|
1888
|
+
return this;
|
|
1889
|
+
}
|
|
1890
|
+
addData(data) {
|
|
1891
|
+
this.addCommands(pathDataToPathCommands(data));
|
|
1892
|
+
return this;
|
|
1893
|
+
}
|
|
1894
|
+
getPoint(t, output = new Vector2()) {
|
|
1895
|
+
const d = t * this.getLength();
|
|
1905
1896
|
const curveLengths = this.getCurveLengths();
|
|
1906
1897
|
let i = 0;
|
|
1907
1898
|
while (i < curveLengths.length) {
|
|
@@ -1966,23 +1957,28 @@ class CurvePath extends Curve {
|
|
|
1966
1957
|
}
|
|
1967
1958
|
return points;
|
|
1968
1959
|
}
|
|
1969
|
-
|
|
1970
|
-
this.
|
|
1971
|
-
|
|
1972
|
-
this.
|
|
1960
|
+
_setCurrentPoint(point) {
|
|
1961
|
+
this.currentPoint.copy(point);
|
|
1962
|
+
if (!this.startPoint) {
|
|
1963
|
+
this.startPoint = this.currentPoint.clone();
|
|
1973
1964
|
}
|
|
1974
1965
|
return this;
|
|
1975
1966
|
}
|
|
1976
|
-
|
|
1977
|
-
this.
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
new
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1967
|
+
closePath() {
|
|
1968
|
+
const start = this.startPoint;
|
|
1969
|
+
if (start) {
|
|
1970
|
+
const end = this.currentPoint;
|
|
1971
|
+
if (!start.equals(end)) {
|
|
1972
|
+
this.curves.push(new LineCurve(end, start));
|
|
1973
|
+
this.currentPoint.copy(start);
|
|
1974
|
+
}
|
|
1975
|
+
this.startPoint = void 0;
|
|
1976
|
+
}
|
|
1977
|
+
return this;
|
|
1978
|
+
}
|
|
1979
|
+
moveTo(x, y) {
|
|
1985
1980
|
this.currentPoint.set(x, y);
|
|
1981
|
+
this.startPoint = this.currentPoint.clone();
|
|
1986
1982
|
return this;
|
|
1987
1983
|
}
|
|
1988
1984
|
lineTo(x, y) {
|
|
@@ -1992,64 +1988,56 @@ class CurvePath extends Curve {
|
|
|
1992
1988
|
new Vector2(x, y)
|
|
1993
1989
|
)
|
|
1994
1990
|
);
|
|
1995
|
-
this.
|
|
1996
|
-
return this;
|
|
1997
|
-
}
|
|
1998
|
-
moveTo(x, y) {
|
|
1999
|
-
this.currentPoint.set(x, y);
|
|
1991
|
+
this._setCurrentPoint({ x, y });
|
|
2000
1992
|
return this;
|
|
2001
1993
|
}
|
|
2002
|
-
|
|
1994
|
+
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) {
|
|
2003
1995
|
this.curves.push(
|
|
2004
|
-
new
|
|
1996
|
+
new CubicBezierCurve(
|
|
2005
1997
|
this.currentPoint.clone(),
|
|
2006
|
-
new Vector2(
|
|
1998
|
+
new Vector2(cp1x, cp1y),
|
|
1999
|
+
new Vector2(cp2x, cp2y),
|
|
2007
2000
|
new Vector2(x, y)
|
|
2008
2001
|
)
|
|
2009
2002
|
);
|
|
2010
|
-
this.
|
|
2003
|
+
this._setCurrentPoint({ x, y });
|
|
2011
2004
|
return this;
|
|
2012
2005
|
}
|
|
2013
|
-
|
|
2006
|
+
quadraticCurveTo(cpx, cpy, x, y) {
|
|
2014
2007
|
this.curves.push(
|
|
2015
|
-
new
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2008
|
+
new QuadraticBezierCurve(
|
|
2009
|
+
this.currentPoint.clone(),
|
|
2010
|
+
new Vector2(cpx, cpy),
|
|
2011
|
+
new Vector2(x, y)
|
|
2019
2012
|
)
|
|
2020
2013
|
);
|
|
2021
|
-
this.
|
|
2014
|
+
this._setCurrentPoint({ x, y });
|
|
2022
2015
|
return this;
|
|
2023
2016
|
}
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
this.curves.push(new SplineCurve(npts));
|
|
2027
|
-
this.currentPoint.copy(points[points.length - 1]);
|
|
2017
|
+
arc(x, y, radius, startAngle, endAngle, counterclockwise) {
|
|
2018
|
+
this.ellipse(x, y, radius, radius, 0, startAngle, endAngle, counterclockwise);
|
|
2028
2019
|
return this;
|
|
2029
2020
|
}
|
|
2030
|
-
|
|
2021
|
+
relativeArc(x, y, radius, startAngle, endAngle, counterclockwise) {
|
|
2031
2022
|
const point = this.currentPoint;
|
|
2032
|
-
this.
|
|
2033
|
-
return this;
|
|
2034
|
-
}
|
|
2035
|
-
absarc(x, y, radius, startAngle, endAngle, clockwise = false) {
|
|
2036
|
-
this.absellipse(x, y, radius, radius, startAngle, endAngle, clockwise);
|
|
2023
|
+
this.arc(x + point.x, y + point.y, radius, startAngle, endAngle, counterclockwise);
|
|
2037
2024
|
return this;
|
|
2038
2025
|
}
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2026
|
+
// TODO
|
|
2027
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
2028
|
+
arcTo(x1, y1, x2, y2, radius) {
|
|
2029
|
+
console.warn("Method arcTo not supported yet");
|
|
2042
2030
|
return this;
|
|
2043
2031
|
}
|
|
2044
|
-
|
|
2032
|
+
ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise = true) {
|
|
2045
2033
|
const curve = new EllipseCurve(
|
|
2046
2034
|
new Vector2(x, y),
|
|
2047
2035
|
radiusX,
|
|
2048
2036
|
radiusY,
|
|
2037
|
+
rotation,
|
|
2049
2038
|
startAngle,
|
|
2050
2039
|
endAngle,
|
|
2051
|
-
|
|
2052
|
-
rotation
|
|
2040
|
+
!counterclockwise
|
|
2053
2041
|
);
|
|
2054
2042
|
if (this.curves.length > 0) {
|
|
2055
2043
|
const first = curve.getPoint(0);
|
|
@@ -2058,16 +2046,45 @@ class CurvePath extends Curve {
|
|
|
2058
2046
|
}
|
|
2059
2047
|
}
|
|
2060
2048
|
this.curves.push(curve);
|
|
2061
|
-
this.
|
|
2049
|
+
this._setCurrentPoint(curve.getPoint(1));
|
|
2062
2050
|
return this;
|
|
2063
2051
|
}
|
|
2064
|
-
|
|
2065
|
-
|
|
2052
|
+
relativeEllipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) {
|
|
2053
|
+
const point = this.currentPoint;
|
|
2054
|
+
this.ellipse(x + point.x, y + point.y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise);
|
|
2055
|
+
return this;
|
|
2056
|
+
}
|
|
2057
|
+
rect(x, y, w, h) {
|
|
2058
|
+
this.curves.push(
|
|
2059
|
+
new RectangularCurve(
|
|
2060
|
+
new Vector2(x + w / 2, y + h / 2),
|
|
2061
|
+
w / 2,
|
|
2062
|
+
w / h
|
|
2063
|
+
)
|
|
2064
|
+
);
|
|
2065
|
+
this._setCurrentPoint({ x, y });
|
|
2066
|
+
return this;
|
|
2067
|
+
}
|
|
2068
|
+
splineThru(points) {
|
|
2069
|
+
this.curves.push(new SplineCurve([this.currentPoint.clone()].concat(points)));
|
|
2070
|
+
this._setCurrentPoint(points[points.length - 1]);
|
|
2071
|
+
return this;
|
|
2072
|
+
}
|
|
2073
|
+
transformPoint(cb) {
|
|
2074
|
+
this.curves.forEach((curve) => curve.transformPoint(cb));
|
|
2075
|
+
return this;
|
|
2066
2076
|
}
|
|
2067
2077
|
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
2068
2078
|
this.curves.forEach((curve) => curve.getMinMax(min, max));
|
|
2069
2079
|
return { min, max };
|
|
2070
2080
|
}
|
|
2081
|
+
getBoundingBox() {
|
|
2082
|
+
const { min, max } = this.getMinMax();
|
|
2083
|
+
return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
2084
|
+
}
|
|
2085
|
+
getCommands() {
|
|
2086
|
+
return this.curves.flatMap((curve) => curve.getCommands());
|
|
2087
|
+
}
|
|
2071
2088
|
drawTo(ctx) {
|
|
2072
2089
|
const point = this.curves[0]?.getPoint(0);
|
|
2073
2090
|
if (point) {
|
|
@@ -2091,6 +2108,10 @@ class CurvePath extends Curve {
|
|
|
2091
2108
|
}
|
|
2092
2109
|
}
|
|
2093
2110
|
|
|
2111
|
+
function toKebabCase(str) {
|
|
2112
|
+
return str.replace(/[^a-z0-9]/gi, "-").replace(/\B([A-Z])/g, "-$1").toLowerCase();
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2094
2115
|
var __defProp = Object.defineProperty;
|
|
2095
2116
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
2096
2117
|
var __publicField = (obj, key, value) => {
|
|
@@ -2101,7 +2122,7 @@ class Path2D {
|
|
|
2101
2122
|
constructor(path) {
|
|
2102
2123
|
__publicField(this, "currentPath", new CurvePath());
|
|
2103
2124
|
__publicField(this, "paths", [this.currentPath]);
|
|
2104
|
-
__publicField(this, "
|
|
2125
|
+
__publicField(this, "style", {});
|
|
2105
2126
|
if (path) {
|
|
2106
2127
|
if (path instanceof Path2D) {
|
|
2107
2128
|
this.addPath(path);
|
|
@@ -2112,6 +2133,15 @@ class Path2D {
|
|
|
2112
2133
|
}
|
|
2113
2134
|
}
|
|
2114
2135
|
}
|
|
2136
|
+
get startPoint() {
|
|
2137
|
+
return this.currentPath.startPoint;
|
|
2138
|
+
}
|
|
2139
|
+
get currentPoint() {
|
|
2140
|
+
return this.currentPath.currentPoint;
|
|
2141
|
+
}
|
|
2142
|
+
get strokeWidth() {
|
|
2143
|
+
return this.style.strokeWidth ?? ((this.style.stroke ?? "none") === "none" ? 0 : 1);
|
|
2144
|
+
}
|
|
2115
2145
|
addPath(path) {
|
|
2116
2146
|
if (path instanceof Path2D) {
|
|
2117
2147
|
this.paths.push(...path.paths.map((v) => v.clone()));
|
|
@@ -2121,12 +2151,19 @@ class Path2D {
|
|
|
2121
2151
|
return this;
|
|
2122
2152
|
}
|
|
2123
2153
|
closePath() {
|
|
2124
|
-
this.
|
|
2154
|
+
const startPoint = this.startPoint;
|
|
2155
|
+
if (startPoint) {
|
|
2156
|
+
this.currentPath.closePath();
|
|
2157
|
+
if (this.currentPath.curves.length > 0) {
|
|
2158
|
+
this.currentPath = new CurvePath().moveTo(startPoint.x, startPoint.y);
|
|
2159
|
+
this.paths.push(this.currentPath);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2125
2162
|
return this;
|
|
2126
2163
|
}
|
|
2127
2164
|
moveTo(x, y) {
|
|
2128
2165
|
const { currentPoint, curves } = this.currentPath;
|
|
2129
|
-
if (currentPoint.
|
|
2166
|
+
if (!currentPoint.equals({ x, y })) {
|
|
2130
2167
|
if (curves.length) {
|
|
2131
2168
|
this.currentPath = new CurvePath().moveTo(x, y);
|
|
2132
2169
|
this.paths.push(this.currentPath);
|
|
@@ -2149,17 +2186,15 @@ class Path2D {
|
|
|
2149
2186
|
return this;
|
|
2150
2187
|
}
|
|
2151
2188
|
arc(x, y, radius, startAngle, endAngle, counterclockwise) {
|
|
2152
|
-
this.currentPath.
|
|
2189
|
+
this.currentPath.arc(x, y, radius, startAngle, endAngle, counterclockwise);
|
|
2153
2190
|
return this;
|
|
2154
2191
|
}
|
|
2155
|
-
// TODO
|
|
2156
|
-
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
2157
2192
|
arcTo(x1, y1, x2, y2, radius) {
|
|
2158
|
-
|
|
2193
|
+
this.currentPath.arcTo(x1, y1, x2, y2, radius);
|
|
2159
2194
|
return this;
|
|
2160
2195
|
}
|
|
2161
2196
|
ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) {
|
|
2162
|
-
this.currentPath.
|
|
2197
|
+
this.currentPath.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise);
|
|
2163
2198
|
return this;
|
|
2164
2199
|
}
|
|
2165
2200
|
rect(x, y, w, h) {
|
|
@@ -2194,56 +2229,92 @@ class Path2D {
|
|
|
2194
2229
|
this.forEachCurve((curve) => curve.getMinMax(min, max));
|
|
2195
2230
|
return { min, max };
|
|
2196
2231
|
}
|
|
2197
|
-
getBoundingBox() {
|
|
2232
|
+
getBoundingBox(withStrokeWidth = true) {
|
|
2198
2233
|
const { min, max } = this.getMinMax();
|
|
2199
|
-
|
|
2234
|
+
const bbox = new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
2235
|
+
if (withStrokeWidth) {
|
|
2236
|
+
const strokeWidth = this.strokeWidth;
|
|
2237
|
+
bbox.left -= strokeWidth / 2;
|
|
2238
|
+
bbox.top -= strokeWidth / 2;
|
|
2239
|
+
bbox.width += strokeWidth;
|
|
2240
|
+
bbox.height += strokeWidth;
|
|
2241
|
+
}
|
|
2242
|
+
return bbox;
|
|
2200
2243
|
}
|
|
2201
2244
|
getCommands() {
|
|
2202
|
-
return this.paths.flatMap((path) => path.
|
|
2245
|
+
return this.paths.flatMap((path) => path.getCommands());
|
|
2203
2246
|
}
|
|
2204
2247
|
getData() {
|
|
2205
2248
|
return this.paths.map((path) => path.getData()).join(" ");
|
|
2206
2249
|
}
|
|
2207
|
-
|
|
2250
|
+
getSvgPathXml() {
|
|
2251
|
+
const style = {
|
|
2252
|
+
...this.style,
|
|
2253
|
+
fill: this.style.fill ?? "#000",
|
|
2254
|
+
stroke: this.style.stroke ?? "none"
|
|
2255
|
+
};
|
|
2256
|
+
const cssStyle = {};
|
|
2257
|
+
for (const key in style) {
|
|
2258
|
+
if (style[key] !== void 0) {
|
|
2259
|
+
cssStyle[toKebabCase(key)] = style[key];
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
Object.assign(cssStyle, {
|
|
2263
|
+
"stroke-width": `${this.strokeWidth}px`
|
|
2264
|
+
});
|
|
2265
|
+
let cssText = "";
|
|
2266
|
+
for (const key in cssStyle) {
|
|
2267
|
+
if (cssStyle[key] !== void 0) {
|
|
2268
|
+
cssText += `${key}:${cssStyle[key]};`;
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
return `<path d="${this.getData()}" style="${cssText}"></path>`;
|
|
2272
|
+
}
|
|
2273
|
+
getSvgXml() {
|
|
2208
2274
|
const { x, y, width, height } = this.getBoundingBox();
|
|
2209
|
-
const
|
|
2210
|
-
return `<svg viewBox="${x
|
|
2275
|
+
const path = this.getSvgPathXml();
|
|
2276
|
+
return `<svg viewBox="${x} ${y} ${width} ${height}" width="${width}px" height="${height}px" xmlns="http://www.w3.org/2000/svg">${path}</svg>`;
|
|
2211
2277
|
}
|
|
2212
2278
|
getSvgDataUri() {
|
|
2213
|
-
return `data:image/svg+xml;base64,${btoa(this.
|
|
2279
|
+
return `data:image/svg+xml;base64,${btoa(this.getSvgXml())}`;
|
|
2214
2280
|
}
|
|
2215
2281
|
drawTo(ctx) {
|
|
2282
|
+
const {
|
|
2283
|
+
fill = "#000",
|
|
2284
|
+
stroke = "none"
|
|
2285
|
+
} = this.style;
|
|
2286
|
+
setCanvasContextByPath(ctx, this);
|
|
2216
2287
|
this.paths.forEach((path) => {
|
|
2217
2288
|
path.drawTo(ctx);
|
|
2218
2289
|
});
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
this.drawTo(ctx);
|
|
2226
|
-
ctx.fill();
|
|
2290
|
+
if (fill !== "none") {
|
|
2291
|
+
ctx.fill();
|
|
2292
|
+
}
|
|
2293
|
+
if (stroke !== "none") {
|
|
2294
|
+
ctx.stroke();
|
|
2295
|
+
}
|
|
2227
2296
|
}
|
|
2228
2297
|
copy(source) {
|
|
2229
2298
|
this.currentPath = source.currentPath.clone();
|
|
2230
2299
|
this.paths = source.paths.map((path) => path.clone());
|
|
2231
|
-
this.
|
|
2300
|
+
this.style = { ...source.style };
|
|
2232
2301
|
return this;
|
|
2233
2302
|
}
|
|
2234
|
-
|
|
2235
|
-
|
|
2303
|
+
toSvg() {
|
|
2304
|
+
return new DOMParser().parseFromString(this.getSvgXml(), "image/svg+xml").documentElement;
|
|
2305
|
+
}
|
|
2306
|
+
toCanvas(pixelRatio = 2) {
|
|
2236
2307
|
const { left, top, width, height } = this.getBoundingBox();
|
|
2237
|
-
canvas
|
|
2238
|
-
canvas.
|
|
2308
|
+
const canvas = document.createElement("canvas");
|
|
2309
|
+
canvas.width = width * pixelRatio;
|
|
2310
|
+
canvas.height = height * pixelRatio;
|
|
2311
|
+
canvas.style.width = `${width}px`;
|
|
2312
|
+
canvas.style.height = `${height}px`;
|
|
2239
2313
|
const ctx = canvas.getContext("2d");
|
|
2240
2314
|
if (ctx) {
|
|
2315
|
+
ctx.scale(pixelRatio, pixelRatio);
|
|
2241
2316
|
ctx.translate(-left, -top);
|
|
2242
|
-
|
|
2243
|
-
this.fillTo(ctx);
|
|
2244
|
-
} else {
|
|
2245
|
-
this.strokeTo(ctx);
|
|
2246
|
-
}
|
|
2317
|
+
this.drawTo(ctx);
|
|
2247
2318
|
}
|
|
2248
2319
|
return canvas;
|
|
2249
2320
|
}
|
|
@@ -2452,7 +2523,7 @@ function parseNodeTransform(node) {
|
|
|
2452
2523
|
|
|
2453
2524
|
function parseCircleNode(node) {
|
|
2454
2525
|
return new Path2D().addPath(
|
|
2455
|
-
new CurvePath().
|
|
2526
|
+
new CurvePath().arc(
|
|
2456
2527
|
parseFloatWithUnits(node.getAttribute("cx") || 0),
|
|
2457
2528
|
parseFloatWithUnits(node.getAttribute("cy") || 0),
|
|
2458
2529
|
parseFloatWithUnits(node.getAttribute("r") || 0),
|
|
@@ -2484,12 +2555,13 @@ function parseCSSStylesheet(node, stylesheets) {
|
|
|
2484
2555
|
|
|
2485
2556
|
function parseEllipseNode(node) {
|
|
2486
2557
|
return new Path2D().addPath(
|
|
2487
|
-
new CurvePath().
|
|
2558
|
+
new CurvePath().ellipse(
|
|
2488
2559
|
parseFloatWithUnits(node.getAttribute("cx") || 0),
|
|
2489
2560
|
parseFloatWithUnits(node.getAttribute("cy") || 0),
|
|
2490
2561
|
parseFloatWithUnits(node.getAttribute("rx") || 0),
|
|
2491
2562
|
parseFloatWithUnits(node.getAttribute("ry") || 0),
|
|
2492
2563
|
0,
|
|
2564
|
+
0,
|
|
2493
2565
|
Math.PI * 2
|
|
2494
2566
|
)
|
|
2495
2567
|
);
|
|
@@ -2635,18 +2707,21 @@ function parseStyle(node, style, stylesheets) {
|
|
|
2635
2707
|
function positive(v) {
|
|
2636
2708
|
return Math.max(0, parseFloatWithUnits(v));
|
|
2637
2709
|
}
|
|
2710
|
+
function array(v) {
|
|
2711
|
+
return v.split(" ").filter((v2) => v2 !== "").map((v2) => parseFloatWithUnits(v2));
|
|
2712
|
+
}
|
|
2638
2713
|
addStyle("fill", "fill");
|
|
2639
2714
|
addStyle("fill-opacity", "fillOpacity", clamp);
|
|
2640
2715
|
addStyle("fill-rule", "fillRule");
|
|
2641
2716
|
addStyle("opacity", "opacity", clamp);
|
|
2642
2717
|
addStyle("stroke", "stroke");
|
|
2643
|
-
addStyle("stroke-dashoffset", "strokeDashoffset");
|
|
2644
|
-
addStyle("stroke-dasharray", "strokeDasharray");
|
|
2645
|
-
addStyle("stroke-linecap", "strokeLineCap");
|
|
2646
|
-
addStyle("stroke-linejoin", "strokeLineJoin");
|
|
2647
|
-
addStyle("stroke-miterlimit", "strokeMiterLimit", positive);
|
|
2648
2718
|
addStyle("stroke-opacity", "strokeOpacity", clamp);
|
|
2649
2719
|
addStyle("stroke-width", "strokeWidth", positive);
|
|
2720
|
+
addStyle("stroke-linecap", "strokeLinecap");
|
|
2721
|
+
addStyle("stroke-linejoin", "strokeLinejoin");
|
|
2722
|
+
addStyle("stroke-miterlimit", "strokeMiterlimit", positive);
|
|
2723
|
+
addStyle("stroke-dasharray", "strokeDasharray", array);
|
|
2724
|
+
addStyle("stroke-dashoffset", "strokeDashoffset", parseFloatWithUnits);
|
|
2650
2725
|
addStyle("visibility", "visibility");
|
|
2651
2726
|
return style;
|
|
2652
2727
|
}
|
|
@@ -2721,7 +2796,7 @@ function parseNode(node, style, paths = []) {
|
|
|
2721
2796
|
if (path) {
|
|
2722
2797
|
path.transform(currentTransform);
|
|
2723
2798
|
paths.push(path);
|
|
2724
|
-
path.
|
|
2799
|
+
path.style = style;
|
|
2725
2800
|
}
|
|
2726
2801
|
const childNodes = node.childNodes;
|
|
2727
2802
|
for (let i = 0, len = childNodes.length; i < len; i++) {
|
|
@@ -2765,15 +2840,7 @@ function parseSvgToDom(svg) {
|
|
|
2765
2840
|
}
|
|
2766
2841
|
}
|
|
2767
2842
|
function parseSvg(svg) {
|
|
2768
|
-
return parseNode(parseSvgToDom(svg), {
|
|
2769
|
-
fill: "#000",
|
|
2770
|
-
fillOpacity: 1,
|
|
2771
|
-
strokeOpacity: 1,
|
|
2772
|
-
strokeWidth: 1,
|
|
2773
|
-
strokeLineJoin: "miter",
|
|
2774
|
-
strokeLineCap: "butt",
|
|
2775
|
-
strokeMiterLimit: 4
|
|
2776
|
-
});
|
|
2843
|
+
return parseNode(parseSvgToDom(svg), {});
|
|
2777
2844
|
}
|
|
2778
2845
|
|
|
2779
2846
|
exports.BoundingBox = BoundingBox;
|
|
@@ -2791,5 +2858,11 @@ exports.QuadraticBezierCurve = QuadraticBezierCurve;
|
|
|
2791
2858
|
exports.RectangularCurve = RectangularCurve;
|
|
2792
2859
|
exports.SplineCurve = SplineCurve;
|
|
2793
2860
|
exports.Vector2 = Vector2;
|
|
2861
|
+
exports.addPathCommandsToPath2D = addPathCommandsToPath2D;
|
|
2862
|
+
exports.parseArcCommand = parseArcCommand;
|
|
2863
|
+
exports.parsePathDataArgs = parsePathDataArgs;
|
|
2794
2864
|
exports.parseSvg = parseSvg;
|
|
2795
2865
|
exports.parseSvgToDom = parseSvgToDom;
|
|
2866
|
+
exports.pathCommandsToPathData = pathCommandsToPathData;
|
|
2867
|
+
exports.pathDataToPathCommands = pathDataToPathCommands;
|
|
2868
|
+
exports.setCanvasContextByPath = setCanvasContextByPath;
|