@pacem/pacem-2d 1.0.0-bessel → 1.0.0-binet
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/pacem-2d.js +149 -2
- package/dist/browser/pacem-2d.js.map +1 -1
- package/dist/browser/pacem-2d.min.js +1 -1
- package/dist/bundle/pacem-2d.min.mjs +1 -1
- package/dist/bundle/pacem-2d.mjs +71 -1
- package/dist/bundle/pacem-2d.mjs.map +2 -2
- package/dist/docs/pacem-2d.json +11549 -0
- package/dist/esm/adapter.js +15 -1
- package/dist/esm/constants.js +3 -1
- package/dist/esm/drawable-element.js +8 -1
- package/dist/esm/drawing.js +28 -1
- package/dist/esm/ellipse.js +20 -1
- package/dist/esm/group.js +3 -1
- package/dist/esm/image.js +2 -1
- package/dist/esm/index-components-drawing.js +1 -1
- package/dist/esm/index-components.js +1 -1
- package/dist/esm/index-iife.js +1 -1
- package/dist/esm/index-root.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/line.js +4 -1
- package/dist/esm/path.js +3 -1
- package/dist/esm/polygon.js +11 -1
- package/dist/esm/polyline.js +10 -1
- package/dist/esm/rect.js +4 -1
- package/dist/esm/stage-abstractions.js +1 -1
- package/dist/esm/stage.js +14 -1
- package/dist/esm/text.js +2 -1
- package/dist/esm/types.js +18 -1
- package/package.json +2 -1
- package/typings/index.d.ts +236 -1
package/dist/browser/pacem-2d.js
CHANGED
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @pacem/pacem-2d v1.0.0-
|
|
2
|
+
* @pacem/pacem-2d v1.0.0-binet (https://js.pacem.it)
|
|
3
3
|
* Pacem (https://pacem.it)
|
|
4
4
|
* Licensed under Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
(function (pacemFoundation, pacemCore) {
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
/** Middle segment shared by every `<pacem-2d-*>` custom element tag name. */
|
|
9
10
|
const TAG_MIDDLE_NAME = "2d";
|
|
10
11
|
|
|
12
|
+
/** Type guard telling whether `object` implements `Drawable`. */
|
|
11
13
|
function isDrawable(object) {
|
|
12
14
|
return !pacemCore.Utils.isNull(object) && 'stage' in object;
|
|
13
15
|
}
|
|
16
|
+
/** Type guard telling whether `object` implements `UiObject`. */
|
|
14
17
|
function isUiObject(object) {
|
|
15
18
|
return /*'transformMatrix' in object &&*/ isDrawable(object);
|
|
16
19
|
}
|
|
17
20
|
function isGradient(object) {
|
|
18
21
|
return 'stops' in object && pacemCore.Utils.isArray(object.stops);
|
|
19
22
|
}
|
|
23
|
+
/** Type guard telling whether `object` is a `LinearGradient`. */
|
|
20
24
|
function isLinearGradient(object) {
|
|
21
25
|
return isGradient(object) && 'start' in object && pacemFoundation.Point.isPoint(object.start)
|
|
22
26
|
&& 'end' in object && pacemFoundation.Point.isPoint(object.end);
|
|
23
27
|
}
|
|
28
|
+
/** Type guard telling whether `object` is a `RadialGradient`. */
|
|
24
29
|
function isRadialGradient(object) {
|
|
25
30
|
return isGradient(object) && 'center' in object && pacemFoundation.Point.isPoint(object.center)
|
|
26
31
|
&& 'radius' in object && typeof object.radius === 'number';
|
|
27
32
|
}
|
|
33
|
+
/** Static helpers to combine `PresentationState` instances (e.g. a shape's own state with its inherited parent state). */
|
|
28
34
|
class PresentationState {
|
|
35
|
+
/**
|
|
36
|
+
* Combines two presentation states (typically an item's own state and the one inherited from its
|
|
37
|
+
* ancestors), giving precedence to `lhs` whenever both define a value.
|
|
38
|
+
* @param lhs Own/most specific presentation state.
|
|
39
|
+
* @param rhs Inherited/fallback presentation state.
|
|
40
|
+
* @param precomputedMatrix If provided, used as-is instead of multiplying `lhs`'s and `rhs`'s transform matrices.
|
|
41
|
+
*/
|
|
29
42
|
static combine(lhs, rhs, precomputedMatrix = null) {
|
|
30
43
|
return {
|
|
31
44
|
opacity: (lhs.opacity ?? 1) * (rhs.opacity ?? 1),
|
|
@@ -39,6 +52,7 @@
|
|
|
39
52
|
};
|
|
40
53
|
}
|
|
41
54
|
}
|
|
55
|
+
/** Type guard telling whether `object` implements `PresentationObject`. */
|
|
42
56
|
function isPresentationObject(object) {
|
|
43
57
|
return isUiObject(object)
|
|
44
58
|
&& ('fill' in object
|
|
@@ -50,18 +64,26 @@
|
|
|
50
64
|
|| 'opacity' in object
|
|
51
65
|
|| 'lineCap' in object);
|
|
52
66
|
}
|
|
67
|
+
/** Type guard telling whether `object` implements `Shape`. */
|
|
53
68
|
function isShape(object) {
|
|
54
69
|
return isUiObject(object) && 'pathData' in object;
|
|
55
70
|
}
|
|
71
|
+
/** Type guard telling whether `object` implements `Group` and has at least one child drawable. */
|
|
56
72
|
function isGroup(object) {
|
|
57
73
|
return isUiObject(object) && 'childDrawables' in object && !pacemCore.Utils.isNullOrEmpty(object['childDrawables']);
|
|
58
74
|
}
|
|
75
|
+
/** Type guard telling whether `object` implements `Text`. */
|
|
59
76
|
function isText(object) {
|
|
60
77
|
return isUiObject(object) && 'text' in object && typeof object['text'] === 'string';
|
|
61
78
|
}
|
|
79
|
+
/** Type guard telling whether `object` implements `Image`. */
|
|
62
80
|
function isImage(object) {
|
|
63
81
|
return isUiObject(object) && 'src' in object && typeof object['src'] === 'string';
|
|
64
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Base class for the custom UI events dispatched by the 2D stage/adapters, carrying the screen transform
|
|
85
|
+
* matrix in effect at dispatch time so consumers can project screen coordinates into stage coordinates.
|
|
86
|
+
*/
|
|
65
87
|
class UI2DEvent extends pacemCore.CustomUIEvent {
|
|
66
88
|
constructor(type, eventInit, originalEvent, transformMatrix) {
|
|
67
89
|
super(type, eventInit, originalEvent);
|
|
@@ -72,22 +94,28 @@
|
|
|
72
94
|
get transformMatrix() {
|
|
73
95
|
return this.#transformMatrix;
|
|
74
96
|
}
|
|
97
|
+
/** Projects a point (defaults to the event's screen coordinates) through the event's transform matrix. */
|
|
75
98
|
project(pt = { x: this.screenX, y: this.screenY }) {
|
|
76
99
|
return pacemFoundation.Matrix2D.multiply(pt, this.#transformMatrix);
|
|
77
100
|
}
|
|
78
101
|
}
|
|
102
|
+
/** Static helper to build an empty `ShapeGeometry`. */
|
|
79
103
|
class Shape {
|
|
104
|
+
/** Returns an empty `ShapeGeometry` (no path, no vertices, zero-sized bounding rect). */
|
|
80
105
|
static empty() {
|
|
81
106
|
return { pathData: '', vertices: [], boundingRect: { x: 0, y: 0, width: 0, height: 0 } };
|
|
82
107
|
}
|
|
83
108
|
}
|
|
109
|
+
/** Event dispatched throughout a `Drawable`'s drag lifecycle, carrying `DragEventArgs`. */
|
|
84
110
|
class DragEvent extends UI2DEvent {
|
|
85
111
|
}
|
|
112
|
+
/** Event dispatched for pointer interactions (over/out/down/up/click) targeting a `Drawable`. */
|
|
86
113
|
class DrawableEvent extends UI2DEvent {
|
|
87
114
|
constructor(type, args, originalEvent, m) {
|
|
88
115
|
super(type, { detail: args, bubbles: true, cancelable: true }, originalEvent, m);
|
|
89
116
|
}
|
|
90
117
|
}
|
|
118
|
+
/** Event dispatched for pointer interactions (move/down/up/click) targeting a `Stage` at large (i.e. no specific hit `Drawable`). */
|
|
91
119
|
class StageEvent extends UI2DEvent {
|
|
92
120
|
constructor(type, args, originalEvent, m = args.transformMatrix) {
|
|
93
121
|
super(type, { detail: args, bubbles: true, cancelable: true }, originalEvent, m);
|
|
@@ -148,10 +176,20 @@
|
|
|
148
176
|
zoomModifiers: [pacemCore.EventKeyModifier.AltKey],
|
|
149
177
|
clickModifiers: []
|
|
150
178
|
};
|
|
179
|
+
/**
|
|
180
|
+
* Returns the effective `StageOptions` for the given stage, filling in any option left unset with the
|
|
181
|
+
* library defaults.
|
|
182
|
+
* @param stage The stage to resolve options for.
|
|
183
|
+
*/
|
|
151
184
|
function getStageOptions(stage) {
|
|
152
185
|
const options = stage instanceof Pacem2DElement ? stage.options : {};
|
|
153
186
|
return pacemCore.Utils.extend({}, DEFAULT_STAGE_OPTIONS, options);
|
|
154
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* The `<pacem-2d>` element: root stage/scene container for the drawable elements (shapes, text, images,
|
|
190
|
+
* groups...). Delegates actual rendering to the assigned `adapter` (SVG or Canvas) and handles the
|
|
191
|
+
* viewbox/aspect-ratio mapping plus built-in pan and zoom interactions.
|
|
192
|
+
*/
|
|
155
193
|
let Pacem2DElement = class Pacem2DElement extends pacemCore.Components.PacemItemsContainerElement {
|
|
156
194
|
constructor() {
|
|
157
195
|
super(...arguments);
|
|
@@ -216,9 +254,11 @@
|
|
|
216
254
|
this.#panningStart = null;
|
|
217
255
|
};
|
|
218
256
|
}
|
|
257
|
+
/** @readonly Gets the DOM element hosting the stage content. */
|
|
219
258
|
get stage() {
|
|
220
259
|
return this._stage;
|
|
221
260
|
}
|
|
261
|
+
/** Processes the stage content and returns a snapshot image (delegates to the current `adapter`). */
|
|
222
262
|
snapshot(bgColor, type, quality) {
|
|
223
263
|
const adapter = this.adapter;
|
|
224
264
|
if (pacemCore.Utils.isNull(adapter)) {
|
|
@@ -228,6 +268,7 @@
|
|
|
228
268
|
}
|
|
229
269
|
#originalViewBox;
|
|
230
270
|
#transformMatrix;
|
|
271
|
+
/** @readonly Gets the matrix that projects stage coords into screen coords. */
|
|
231
272
|
get transformMatrix() {
|
|
232
273
|
return this.#transformMatrix;
|
|
233
274
|
}
|
|
@@ -479,6 +520,11 @@
|
|
|
479
520
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
480
521
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
481
522
|
};
|
|
523
|
+
/**
|
|
524
|
+
* Root of the `<pacem-2d-*>` drawable elements hierarchy: wires a custom element up to its containing
|
|
525
|
+
* `Pacem2DElement` stage and, in case of nesting, its parent drawable. By default children are not allowed
|
|
526
|
+
* (only `PacemGroupElement` overrides `validate` to accept them).
|
|
527
|
+
*/
|
|
482
528
|
class DrawableElement extends pacemCore.Components.PacemCrossItemsContainerElement {
|
|
483
529
|
validate(_) {
|
|
484
530
|
// by default no children allowed (Group will except)
|
|
@@ -488,9 +534,11 @@
|
|
|
488
534
|
// override
|
|
489
535
|
return this.parent || this.stage;
|
|
490
536
|
}
|
|
537
|
+
/** @readonly Gets the `Pacem2DElement` stage this drawable belongs to. */
|
|
491
538
|
get stage() {
|
|
492
539
|
return this['_scene'] = this['_scene'] || pacemCore.CustomElementUtils.findAncestorOfType(this, Pacem2DElement);
|
|
493
540
|
}
|
|
541
|
+
/** @readonly Gets the closest ancestor `DrawableElement` (e.g. a containing group), if any. */
|
|
494
542
|
get parent() {
|
|
495
543
|
return this['_drawableParent'] = this['_drawableParent'] || pacemCore.CustomElementUtils.findAncestor(this, i => i instanceof DrawableElement);
|
|
496
544
|
}
|
|
@@ -525,6 +573,10 @@
|
|
|
525
573
|
};
|
|
526
574
|
//namespace Pacem.Components.Drawing {
|
|
527
575
|
const DEG2RAD = Math.PI / 180.0;
|
|
576
|
+
/**
|
|
577
|
+
* Base class for every drawable that participates in the 2D transform pipeline (rotation, scale,
|
|
578
|
+
* translation) and exposes an `opacity`. Computes and caches the corresponding `transformMatrix`.
|
|
579
|
+
*/
|
|
528
580
|
class UiElement extends DrawableElement {
|
|
529
581
|
#transformMatrix = pacemFoundation.Matrix2D.identity;
|
|
530
582
|
viewActivatedCallback() {
|
|
@@ -576,6 +628,10 @@
|
|
|
576
628
|
__decorate$b([
|
|
577
629
|
pacemCore.Watch({ emit: false, converter: pacemCore.PropertyConverters.Number })
|
|
578
630
|
], UiElement.prototype, "opacity", void 0);
|
|
631
|
+
/**
|
|
632
|
+
* Base class for drawables that carry stroke/fill presentation state (color, line width, dash pattern,
|
|
633
|
+
* line join/cap), on top of the transform/opacity inherited from `UiElement`.
|
|
634
|
+
*/
|
|
579
635
|
class PresentationElement extends UiElement {
|
|
580
636
|
propertyChangedCallback(name, old, val, first) {
|
|
581
637
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -618,6 +674,11 @@
|
|
|
618
674
|
__decorate$b([
|
|
619
675
|
pacemCore.Watch({ emit: false, converter: pacemCore.PropertyConverters.String })
|
|
620
676
|
], PresentationElement.prototype, "lineCap", void 0);
|
|
677
|
+
/**
|
|
678
|
+
* Base class for drawables whose visual is an SVG path (`pathData`) computed out of their own geometry
|
|
679
|
+
* properties (e.g. center/radius, points, corners). Subclasses implement `getShapeGeometry` and this
|
|
680
|
+
* class takes care of recomputing `data`/`vertices`/`boundingRect` and requesting a redraw.
|
|
681
|
+
*/
|
|
621
682
|
class ShapeElement extends PresentationElement {
|
|
622
683
|
propertyChangedCallback(name, old, val, first) {
|
|
623
684
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -633,20 +694,24 @@
|
|
|
633
694
|
super.viewActivatedCallback();
|
|
634
695
|
this.recomputeShape();
|
|
635
696
|
}
|
|
697
|
+
/** Recomputes `data`, `vertices` and `boundingRect` from `getShapeGeometry()`. */
|
|
636
698
|
recomputeShape() {
|
|
637
699
|
const { pathData, vertices, boundingRect } = this.getShapeGeometry();
|
|
638
700
|
this.#vertices = vertices;
|
|
639
701
|
this.#boundingRect = boundingRect;
|
|
640
702
|
this.data = pathData;
|
|
641
703
|
}
|
|
704
|
+
/** @readonly Gets the SVG path data backing the shape. */
|
|
642
705
|
get pathData() {
|
|
643
706
|
return this.data;
|
|
644
707
|
}
|
|
645
708
|
#boundingRect;
|
|
709
|
+
/** @readonly Gets the bounding rectangle of the shape. */
|
|
646
710
|
get boundingRect() {
|
|
647
711
|
return this.#boundingRect;
|
|
648
712
|
}
|
|
649
713
|
#vertices;
|
|
714
|
+
/** @readonly Gets the vertices making up the shape. */
|
|
650
715
|
get vertices() {
|
|
651
716
|
return this.#vertices;
|
|
652
717
|
}
|
|
@@ -662,11 +727,13 @@
|
|
|
662
727
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
663
728
|
};
|
|
664
729
|
//namespace Pacem.Components.Drawing {
|
|
730
|
+
/** `<pacem-2d-group>`: a container that groups child drawables, applying its own transform/presentation state to all of them. */
|
|
665
731
|
let PacemGroupElement = class PacemGroupElement extends PresentationElement {
|
|
666
732
|
validate(item) {
|
|
667
733
|
return item instanceof DrawableElement && item.parent === this;
|
|
668
734
|
}
|
|
669
735
|
#children = [];
|
|
736
|
+
/** @readonly Gets the child drawables currently in the group. */
|
|
670
737
|
get childDrawables() {
|
|
671
738
|
return this.#children;
|
|
672
739
|
}
|
|
@@ -749,6 +816,7 @@
|
|
|
749
816
|
const threesixty = (start - end).isCloseTo(0);
|
|
750
817
|
return threesixty ? full(c, rx, ry) : sect(c, rx, ry, start, end);
|
|
751
818
|
}
|
|
819
|
+
/** `<pacem-2d-ellipse>`: renders a full ellipse, or a pie-slice sector when `start`/`end` are set. */
|
|
752
820
|
let PacemEllipseElement = PacemEllipseElement_1 = class PacemEllipseElement extends ShapeElement {
|
|
753
821
|
propertyChangedCallback(name, old, val, first) {
|
|
754
822
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -764,6 +832,7 @@
|
|
|
764
832
|
}
|
|
765
833
|
}
|
|
766
834
|
}
|
|
835
|
+
/** Computes the SVG path data of the ellipse (or sector) out of its own `center`/`rx`/`ry`/`start`/`end`. */
|
|
767
836
|
getPathData() {
|
|
768
837
|
const a = this.rx, b = this.ry, c = this.center, s = this.start ?? 0, e = this.end ?? 0;
|
|
769
838
|
if (!pacemCore.Utils.isNull(c) && !pacemCore.Utils.isNull(a) && !pacemCore.Utils.isNull(b)) {
|
|
@@ -776,6 +845,14 @@
|
|
|
776
845
|
const a = this.rx ?? 0, b = this.ry ?? 0;
|
|
777
846
|
return getShapeGeometry(center, a, b, this.start, this.end);
|
|
778
847
|
}
|
|
848
|
+
/**
|
|
849
|
+
* Computes the SVG path data of an ellipse, or of a pie-slice sector when `start`/`end` don't describe a full turn.
|
|
850
|
+
* @param c Center point.
|
|
851
|
+
* @param rx Horizontal radius.
|
|
852
|
+
* @param ry Vertical radius.
|
|
853
|
+
* @param start Sector start angle, in degrees.
|
|
854
|
+
* @param end Sector end angle, in degrees.
|
|
855
|
+
*/
|
|
779
856
|
static getPathData(c = { x: NaN, y: NaN }, rx = NaN, ry = NaN, start, end) {
|
|
780
857
|
const { pathData } = getShapeGeometry(c, rx, ry, start, end);
|
|
781
858
|
return pathData;
|
|
@@ -799,6 +876,7 @@
|
|
|
799
876
|
PacemEllipseElement = PacemEllipseElement_1 = __decorate$9([
|
|
800
877
|
pacemCore.CustomElement({ tagName: pacemCore.P + '-' + TAG_MIDDLE_NAME + '-ellipse' })
|
|
801
878
|
], PacemEllipseElement);
|
|
879
|
+
/** `<pacem-2d-circle>`: renders a full circle, or a pie-slice sector when `start`/`end` are set. */
|
|
802
880
|
let PacemCircleElement = PacemCircleElement_1 = class PacemCircleElement extends ShapeElement {
|
|
803
881
|
propertyChangedCallback(name, old, val, first) {
|
|
804
882
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -813,6 +891,7 @@
|
|
|
813
891
|
}
|
|
814
892
|
}
|
|
815
893
|
}
|
|
894
|
+
/** Computes the SVG path data of the circle (or sector) out of its own `center`/`radius`/`start`/`end`. */
|
|
816
895
|
getPathData() {
|
|
817
896
|
const r = this.radius, c = this.center;
|
|
818
897
|
if (!pacemCore.Utils.isNull(c) && !pacemCore.Utils.isNull(r)) {
|
|
@@ -825,6 +904,13 @@
|
|
|
825
904
|
const r = this.radius ?? 0;
|
|
826
905
|
return getShapeGeometry(center, r, r, this.start, this.end);
|
|
827
906
|
}
|
|
907
|
+
/**
|
|
908
|
+
* Computes the SVG path data of a circle, or of a pie-slice sector when `start`/`end` don't describe a full turn.
|
|
909
|
+
* @param c Center point.
|
|
910
|
+
* @param r Radius.
|
|
911
|
+
* @param start Sector start angle, in degrees.
|
|
912
|
+
* @param end Sector end angle, in degrees.
|
|
913
|
+
*/
|
|
828
914
|
static getPathData(c = { x: NaN, y: NaN }, r = NaN, start, end) {
|
|
829
915
|
return PacemEllipseElement.getPathData(c, r, r, start, end);
|
|
830
916
|
}
|
|
@@ -901,11 +987,13 @@
|
|
|
901
987
|
const blX = stringifyCornerRadiusComponent(bottomLeft.rx), blY = stringifyCornerRadiusComponent(bottomLeft.ry);
|
|
902
988
|
return `${tlX},${tlY} ${trX},${trY} ${brX},${brY} ${blX},${blY}`;
|
|
903
989
|
}
|
|
990
|
+
/** How a `PacemRectElement` corner is rendered: smoothly `Rounded` or straight-line `Cut` (chamfered). */
|
|
904
991
|
var CornerType;
|
|
905
992
|
(function (CornerType) {
|
|
906
993
|
CornerType["Rounded"] = "rounded";
|
|
907
994
|
CornerType["Cut"] = "cut";
|
|
908
995
|
})(CornerType || (CornerType = {}));
|
|
996
|
+
/** `<pacem-2d-rect>`: renders a rectangle, optionally with independently rounded or cut corners. */
|
|
909
997
|
let PacemRectElement = PacemRectElement_1 = class PacemRectElement extends ShapeElement {
|
|
910
998
|
propertyChangedCallback(name, old, val, first) {
|
|
911
999
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -913,6 +1001,7 @@
|
|
|
913
1001
|
this.recomputeShape();
|
|
914
1002
|
}
|
|
915
1003
|
}
|
|
1004
|
+
/** Computes the SVG path data of the rectangle out of its own `x`/`y`/`w`/`h`/`r`/`cornerType`. */
|
|
916
1005
|
getPathData() {
|
|
917
1006
|
const x = this.x, y = this.y, w = this.w, h = this.h;
|
|
918
1007
|
let r = this.r ?? { rx: { value: 0 }, ry: { value: 0 }, type: CornerType.Rounded };
|
|
@@ -1024,6 +1113,7 @@
|
|
|
1024
1113
|
};
|
|
1025
1114
|
var PacemLineElement_1;
|
|
1026
1115
|
//namespace Pacem.Components.Drawing {
|
|
1116
|
+
/** `<pacem-2d-line>`: renders a straight segment between two points. */
|
|
1027
1117
|
let PacemLineElement = PacemLineElement_1 = class PacemLineElement extends ShapeElement {
|
|
1028
1118
|
propertyChangedCallback(name, old, val, first) {
|
|
1029
1119
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -1045,6 +1135,7 @@
|
|
|
1045
1135
|
const boundingRect = { x: Math.min(x0, x1), y: Math.min(y0, y1), width: Math.abs(x0 - x1), height: Math.abs(y0 - y1) };
|
|
1046
1136
|
return { pathData: this.getPathData(), vertices: [from, to], boundingRect };
|
|
1047
1137
|
}
|
|
1138
|
+
/** Computes the SVG path data of the line out of its own `from`/`to` points. */
|
|
1048
1139
|
getPathData() {
|
|
1049
1140
|
const from = this.from, to = this.to;
|
|
1050
1141
|
if (!pacemCore.Utils.isNull(from) && !pacemCore.Utils.isNull(to)) {
|
|
@@ -1052,6 +1143,7 @@
|
|
|
1052
1143
|
}
|
|
1053
1144
|
return null;
|
|
1054
1145
|
}
|
|
1146
|
+
/** Computes the SVG path data of a straight segment between `from` and `to`. */
|
|
1055
1147
|
static getPathData(from = { x: NaN, y: NaN }, to = { x: NaN, y: NaN }) {
|
|
1056
1148
|
const x0 = from.x, y0 = from.y, x1 = to.x, y1 = to.y;
|
|
1057
1149
|
return `M ${x0} ${y0} L ${x1} ${y1}`;
|
|
@@ -1074,9 +1166,11 @@
|
|
|
1074
1166
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1075
1167
|
};
|
|
1076
1168
|
//namespace Pacem.Components.Drawing {
|
|
1169
|
+
/** `<pacem-2d-path>`: renders an arbitrary SVG path, provided verbatim through the `d` property. */
|
|
1077
1170
|
let PacemPathElement = class PacemPathElement extends ShapeElement {
|
|
1078
1171
|
constructor() {
|
|
1079
1172
|
super(...arguments);
|
|
1173
|
+
/** Returns the raw path data, i.e. `d`. */
|
|
1080
1174
|
this.getPathData = () => this.d;
|
|
1081
1175
|
}
|
|
1082
1176
|
propertyChangedCallback(name, old, val, first) {
|
|
@@ -1104,6 +1198,7 @@
|
|
|
1104
1198
|
};
|
|
1105
1199
|
var PacemPolygonElement_1;
|
|
1106
1200
|
//namespace Pacem.Components.Drawing {
|
|
1201
|
+
/** `<pacem-2d-polygon>`: renders a regular polygon (or, with `starIndent` set, a star) centered on `center`. */
|
|
1107
1202
|
let PacemPolygonElement = PacemPolygonElement_1 = class PacemPolygonElement extends ShapeElement {
|
|
1108
1203
|
propertyChangedCallback(name, old, val, first) {
|
|
1109
1204
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -1117,6 +1212,7 @@
|
|
|
1117
1212
|
}
|
|
1118
1213
|
}
|
|
1119
1214
|
}
|
|
1215
|
+
/** Computes the SVG path data of the polygon out of its own `center`, `radius`, `sides` and `starIndent`. */
|
|
1120
1216
|
getPathData() {
|
|
1121
1217
|
const sides = this.sides, radius = this.radius, center = this.center;
|
|
1122
1218
|
if (!pacemCore.Utils.isNull(sides) && !pacemCore.Utils.isNull(radius)) {
|
|
@@ -1131,6 +1227,13 @@
|
|
|
1131
1227
|
}
|
|
1132
1228
|
return PacemPolygonElement_1.getShapeGeometry(c, r, sides, si);
|
|
1133
1229
|
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Computes the geometry (path data, vertices, bounding rect) of a regular polygon or star.
|
|
1232
|
+
* @param center Center point.
|
|
1233
|
+
* @param radius Circumradius.
|
|
1234
|
+
* @param sides Number of sides (or points, for a star).
|
|
1235
|
+
* @param starIndent Star indentation factor (0 = regular polygon).
|
|
1236
|
+
*/
|
|
1134
1237
|
static getShapeGeometry(center, radius, sides, starIndent = .0) {
|
|
1135
1238
|
const p0 = { x: center.x, y: center.y - radius };
|
|
1136
1239
|
let retval = `M ${p0.x} ${(p0.y)}`;
|
|
@@ -1161,6 +1264,7 @@
|
|
|
1161
1264
|
pathData: retval + ' Z', vertices, boundingRect: { x: p0.x - radius, y: p0.y, width, height: width }
|
|
1162
1265
|
};
|
|
1163
1266
|
}
|
|
1267
|
+
/** Computes the SVG path data of a regular polygon or star. See `getShapeGeometry` for the parameters. */
|
|
1164
1268
|
static getPathData(center, radius, sides, starIndent = .0) {
|
|
1165
1269
|
const { pathData } = PacemPolygonElement_1.getShapeGeometry(center, radius, sides, starIndent);
|
|
1166
1270
|
return pathData;
|
|
@@ -1190,6 +1294,7 @@
|
|
|
1190
1294
|
};
|
|
1191
1295
|
var PacemPolylineElement_1;
|
|
1192
1296
|
//namespace Pacem.Components.Drawing {
|
|
1297
|
+
/** Converts the `points` attribute either from a flat `x1,y1,x2,y2,...` numeric list or from JSON. */
|
|
1193
1298
|
const PointArrayOrJsonConverter = {
|
|
1194
1299
|
convert: (attr) => {
|
|
1195
1300
|
const arr = pacemFoundation.parseAsNumericalArray(attr);
|
|
@@ -1204,6 +1309,7 @@
|
|
|
1204
1309
|
},
|
|
1205
1310
|
convertBack: (prop) => JSON.stringify(prop)
|
|
1206
1311
|
};
|
|
1312
|
+
/** `<pacem-2d-polyline>`: renders a series of connected segments through `points`, optionally `closed` into a polygon. */
|
|
1207
1313
|
let PacemPolylineElement = PacemPolylineElement_1 = class PacemPolylineElement extends ShapeElement {
|
|
1208
1314
|
propertyChangedCallback(name, old, val, first) {
|
|
1209
1315
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -1216,6 +1322,11 @@
|
|
|
1216
1322
|
}
|
|
1217
1323
|
}
|
|
1218
1324
|
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Computes the geometry (path data, vertices, bounding rect) of a polyline.
|
|
1327
|
+
* @param points Vertices, in order.
|
|
1328
|
+
* @param closed Whether the polyline is closed back onto its first point.
|
|
1329
|
+
*/
|
|
1219
1330
|
static getShapeGeometry(points, closed) {
|
|
1220
1331
|
if (pacemCore.Utils.isNullOrEmpty(points)) {
|
|
1221
1332
|
return Shape.empty();
|
|
@@ -1239,10 +1350,12 @@
|
|
|
1239
1350
|
getShapeGeometry() {
|
|
1240
1351
|
return PacemPolylineElement_1.getShapeGeometry(this.points, this.closed);
|
|
1241
1352
|
}
|
|
1353
|
+
/** Computes the SVG path data of the polyline out of its own `points`/`closed`. */
|
|
1242
1354
|
getPathData() {
|
|
1243
1355
|
const { pathData } = this.getShapeGeometry();
|
|
1244
1356
|
return pathData;
|
|
1245
1357
|
}
|
|
1358
|
+
/** Computes the SVG path data of a polyline. See `getShapeGeometry` for the parameters. */
|
|
1246
1359
|
static getPathData(points, closed) {
|
|
1247
1360
|
const { pathData } = PacemPolylineElement_1.getShapeGeometry(points, closed);
|
|
1248
1361
|
return pathData;
|
|
@@ -1265,6 +1378,7 @@
|
|
|
1265
1378
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1266
1379
|
};
|
|
1267
1380
|
//namespace Pacem.Components.Drawing {
|
|
1381
|
+
/** `<pacem-2d-image>`: renders a raster image at a given position and size within the stage. */
|
|
1268
1382
|
let PacemImageElement = class PacemImageElement extends UiElement {
|
|
1269
1383
|
propertyChangedCallback(name, old, val, first) {
|
|
1270
1384
|
super.propertyChangedCallback(name, old, val, first);
|
|
@@ -1307,6 +1421,7 @@
|
|
|
1307
1421
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1308
1422
|
};
|
|
1309
1423
|
//namespace Pacem.Components.Drawing {
|
|
1424
|
+
/** `<pacem-2d-text>`: renders a text label anchored at a given point. */
|
|
1310
1425
|
let PacemTextElement = class PacemTextElement extends UiElement {
|
|
1311
1426
|
propertyChangedCallback(name, old, val, first) {
|
|
1312
1427
|
if (!first) {
|
|
@@ -1355,12 +1470,20 @@
|
|
|
1355
1470
|
], PacemTextElement);
|
|
1356
1471
|
|
|
1357
1472
|
//namespace Pacem.Components.Drawing {
|
|
1473
|
+
/** Shared static helpers used by the 2D rendering adapters (SVG/Canvas) to dispatch UI events and validate viewboxes. */
|
|
1358
1474
|
class AdapterUtils {
|
|
1475
|
+
/**
|
|
1476
|
+
* Dispatches a `StageEvent` (prefixed with `'stage'`) on the given stage, when it is an `EventTarget`.
|
|
1477
|
+
* @param stage The target stage.
|
|
1478
|
+
* @param type Short event type name.
|
|
1479
|
+
* @param evt The original event.
|
|
1480
|
+
*/
|
|
1359
1481
|
static stageDispatch(stage, type, evt) {
|
|
1360
1482
|
if (stage instanceof EventTarget) {
|
|
1361
1483
|
stage.dispatchEvent(new StageEvent('stage' + type, stage, evt, stage.transformMatrix));
|
|
1362
1484
|
}
|
|
1363
1485
|
}
|
|
1486
|
+
/** Type guard telling whether `viewbox` is a well-formed, finite `Rect` usable as a stage viewbox. */
|
|
1364
1487
|
static isValidViewbox(viewbox) {
|
|
1365
1488
|
return !pacemCore.Utils.isNullOrEmpty(viewbox) && pacemFoundation.Rect.isRect(viewbox) && Number.isFinite(viewbox.x) // isFinite includes NaN check
|
|
1366
1489
|
&& Number.isFinite(viewbox.y) && Number.isFinite(viewbox.width) && Number.isFinite(viewbox.height);
|
|
@@ -1403,15 +1526,29 @@
|
|
|
1403
1526
|
}
|
|
1404
1527
|
|
|
1405
1528
|
const JPEG_QUALITY = .9;
|
|
1529
|
+
/**
|
|
1530
|
+
* Base class for the rendering adapters (SVG, Canvas) assignable to a `Pacem2DElement` stage. Concrete
|
|
1531
|
+
* adapters are responsible for initializing/disposing the underlying DOM surface, sizing it, drawing the
|
|
1532
|
+
* scene graph, hit-testing and producing snapshot images.
|
|
1533
|
+
*/
|
|
1406
1534
|
class Pacem2DAdapterElement extends pacemCore.PacemEventTarget {
|
|
1407
1535
|
constructor() {
|
|
1408
1536
|
super(...arguments);
|
|
1537
|
+
/** Fallback stroke/fill/lineWidth values used when a shape doesn't provide its own. */
|
|
1409
1538
|
this.DefaultShapeValues = {
|
|
1410
1539
|
stroke: "#000",
|
|
1411
1540
|
lineWidth: 1,
|
|
1412
1541
|
fill: "#fff"
|
|
1413
1542
|
};
|
|
1414
1543
|
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Rasterizes the given DOM element into an image `Blob`, defaulting to JPEG when `bgColor` is provided
|
|
1546
|
+
* (to flatten transparency against it) and to PNG otherwise.
|
|
1547
|
+
* @param element Element to snapshot.
|
|
1548
|
+
* @param bgColor Background color to flatten transparency against; if set, defaults `type` to `'image/jpeg'`.
|
|
1549
|
+
* @param type Explicit image MIME type, overrides the `bgColor`-based default.
|
|
1550
|
+
* @param quality Compression quality, applicable to lossy formats (defaults to `.9` for JPEG).
|
|
1551
|
+
*/
|
|
1415
1552
|
snapshotElement(element, bgColor, type, quality) {
|
|
1416
1553
|
const jpeg = !pacemCore.Utils.isNullOrEmpty(bgColor), mime = type ?? (jpeg ? 'image/jpeg' : null), compression = quality ?? (jpeg ? JPEG_QUALITY : null);
|
|
1417
1554
|
return pacemCore.Utils.snapshotElement(element, bgColor, mime, compression);
|
|
@@ -1435,7 +1572,12 @@
|
|
|
1435
1572
|
function fallback$1(v, f) {
|
|
1436
1573
|
return pacemCore.Utils.isNull(v) ? f : v;
|
|
1437
1574
|
}
|
|
1438
|
-
/**
|
|
1575
|
+
/**
|
|
1576
|
+
* `<pacem-2d-canvas-adapter>`: renders a `Pacem2DElement` stage onto an `HTMLCanvasElement`, redrawing the
|
|
1577
|
+
* whole scene graph on every frame and performing manual (path-based) pointer hit-testing.
|
|
1578
|
+
*
|
|
1579
|
+
* @deprecated Implementation postponed. Focus on SVG adapter.
|
|
1580
|
+
*/
|
|
1439
1581
|
let PacemCanvasAdapterElement = class PacemCanvasAdapterElement extends Pacem2DAdapterElement {
|
|
1440
1582
|
constructor() {
|
|
1441
1583
|
super(...arguments);
|
|
@@ -2063,6 +2205,11 @@
|
|
|
2063
2205
|
return parent.replaceChild(newChild, parent.children.item(targetIndex));
|
|
2064
2206
|
}
|
|
2065
2207
|
}
|
|
2208
|
+
/**
|
|
2209
|
+
* `<pacem-2d-svg-adapter>`: renders a `Pacem2DElement` stage as an inline SVG document, keeping one SVG
|
|
2210
|
+
* element per drawable in sync (path/text/image/group), along with markers and gradients, and drives
|
|
2211
|
+
* pointer hit-testing and drag & drop through the SVG DOM.
|
|
2212
|
+
*/
|
|
2066
2213
|
let PacemSvgAdapterElement = class PacemSvgAdapterElement extends Pacem2DAdapterElement {
|
|
2067
2214
|
constructor() {
|
|
2068
2215
|
super(...arguments);
|