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