@pacem/pacem-2d 1.0.0-abel
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/LICENSE +191 -0
- package/NOTICE +4 -0
- package/dist/browser/pacem-2d.js +2750 -0
- package/dist/browser/pacem-2d.js.map +1 -0
- package/dist/browser/pacem-2d.min.js +2 -0
- package/dist/browser/pacem-2d.min.js.map +1 -0
- package/dist/bundle/pacem-2d.min.mjs +1 -0
- package/dist/bundle/pacem-2d.mjs +2600 -0
- package/dist/bundle/pacem-2d.mjs.map +7 -0
- package/dist/esm/adapter.js +16 -0
- package/dist/esm/constants.js +2 -0
- package/dist/esm/drawable-element.js +45 -0
- package/dist/esm/drawing.js +87 -0
- package/dist/esm/ellipse.js +159 -0
- package/dist/esm/group.js +40 -0
- package/dist/esm/image.js +45 -0
- package/dist/esm/index-components-drawing.js +16 -0
- package/dist/esm/index-components.js +1 -0
- package/dist/esm/index-iife.js +3 -0
- package/dist/esm/index-root.js +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/line.js +55 -0
- package/dist/esm/path.js +32 -0
- package/dist/esm/polygon.js +90 -0
- package/dist/esm/polyline.js +81 -0
- package/dist/esm/rect.js +174 -0
- package/dist/esm/stage-abstractions.js +1 -0
- package/dist/esm/stage.js +366 -0
- package/dist/esm/text.js +57 -0
- package/dist/esm/types.js +140 -0
- package/package.json +38 -0
- package/typings/index.d.ts +613 -0
package/dist/esm/rect.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var PacemRectElement_1;
|
|
8
|
+
import { CustomElement, Watch, PropertyConverters, P, Utils } from '@pacem/pacem-core';
|
|
9
|
+
import { ShapeElement } from './types';
|
|
10
|
+
import { TAG_MIDDLE_NAME } from './constants';
|
|
11
|
+
//namespace Pacem.Components.Drawing {
|
|
12
|
+
/*
|
|
13
|
+
r="4" // every corner has a rx equalt o ry equal to 8 units
|
|
14
|
+
r="4,8 cut" // every corner has a rx equal to 4px and a ry equal to 8px (cut corners)
|
|
15
|
+
r="4,8 cut 5,6 3,20% round 50%,4" // top-left corner has a rx equal to 4px and a ry equal to 8px (cut corner), top-right corner has a rx equal to 5px and a ry equal to 6px,
|
|
16
|
+
// bottom-right corner has a rx equal to 3px and a ry equal to 20% the height,
|
|
17
|
+
// bottom-left corner has a rx equal to 50% the width and a ry equal to 4px.
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
function parseCornerRadius(radius) {
|
|
21
|
+
const rx = radius[2], ry = radius[4] ?? rx, type = radius[6] === 'cut' ? CornerType.Cut : CornerType.Rounded;
|
|
22
|
+
return { rx: parseCornerRadiusComponent(rx), ry: parseCornerRadiusComponent(ry), type };
|
|
23
|
+
}
|
|
24
|
+
function parseCornerRadiusComponent(radius) {
|
|
25
|
+
const val = parseFloat(radius);
|
|
26
|
+
return { value: val, unit: radius.endsWith('%') ? 'pct' : 'u' };
|
|
27
|
+
}
|
|
28
|
+
function stringifyCornerRadiusComponent(radius) {
|
|
29
|
+
return `${radius.value}${radius.unit === 'pct' ? '%' : ''}`;
|
|
30
|
+
}
|
|
31
|
+
const CORNERS_PATTERN = /(([\d\.]+%?)(\s*,?\s*([\d\.]+%?))?(\s+(cut|round))?)/g;
|
|
32
|
+
function parseCornerRadii(radii) {
|
|
33
|
+
let numbers;
|
|
34
|
+
const acc = [];
|
|
35
|
+
while (numbers = CORNERS_PATTERN.exec(radii)) {
|
|
36
|
+
acc.push(numbers);
|
|
37
|
+
}
|
|
38
|
+
switch (acc.length) {
|
|
39
|
+
case 1:
|
|
40
|
+
const single = parseCornerRadius(acc[0]);
|
|
41
|
+
return [single, single, single, single];
|
|
42
|
+
case 4:
|
|
43
|
+
const topLeft = parseCornerRadius(acc[0]);
|
|
44
|
+
const topRight = parseCornerRadius(acc[1]);
|
|
45
|
+
const bottomRight = parseCornerRadius(acc[2]);
|
|
46
|
+
const bottomLeft = parseCornerRadius(acc[3]);
|
|
47
|
+
return [topLeft, topRight, bottomRight, bottomLeft];
|
|
48
|
+
default:
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function stringifyCornerRadii(radii) {
|
|
53
|
+
const topLeft = radii[0], topRight = radii[1], bottomRight = radii[2], bottomLeft = radii[3];
|
|
54
|
+
const tlX = stringifyCornerRadiusComponent(topLeft.rx), tlY = stringifyCornerRadiusComponent(topLeft.ry);
|
|
55
|
+
const trX = stringifyCornerRadiusComponent(topRight.rx), trY = stringifyCornerRadiusComponent(topRight.ry);
|
|
56
|
+
const brX = stringifyCornerRadiusComponent(bottomRight.rx), brY = stringifyCornerRadiusComponent(bottomRight.ry);
|
|
57
|
+
const blX = stringifyCornerRadiusComponent(bottomLeft.rx), blY = stringifyCornerRadiusComponent(bottomLeft.ry);
|
|
58
|
+
return `${tlX},${tlY} ${trX},${trY} ${brX},${brY} ${blX},${blY}`;
|
|
59
|
+
}
|
|
60
|
+
export var CornerType;
|
|
61
|
+
(function (CornerType) {
|
|
62
|
+
CornerType["Rounded"] = "rounded";
|
|
63
|
+
CornerType["Cut"] = "cut";
|
|
64
|
+
})(CornerType || (CornerType = {}));
|
|
65
|
+
let PacemRectElement = PacemRectElement_1 = class PacemRectElement extends ShapeElement {
|
|
66
|
+
propertyChangedCallback(name, old, val, first) {
|
|
67
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
68
|
+
if (!first && (name === 'x' || name === 'y' || name === 'w' || name === 'h' || name === 'r' || name === 'cornerType')) {
|
|
69
|
+
this.recomputeShape();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
getPathData() {
|
|
73
|
+
const x = this.x, y = this.y, w = this.w, h = this.h;
|
|
74
|
+
let r = this.r ?? { rx: { value: 0 }, ry: { value: 0 }, type: CornerType.Rounded };
|
|
75
|
+
if (!Utils.isArray(r)) {
|
|
76
|
+
r = [r, r, r, r];
|
|
77
|
+
}
|
|
78
|
+
// forgiving behavior
|
|
79
|
+
r = r.map(i => { return typeof i === 'number' ? { rx: { value: i }, ry: { value: i }, type: this.cornerType } : i; });
|
|
80
|
+
if (!Utils.isNull(x) && !Utils.isNull(y) && !Utils.isNull(w) && !Utils.isNull(h)) {
|
|
81
|
+
return PacemRectElement_1.getPathData(x, y, w, h, r);
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
getShapeGeometry() {
|
|
86
|
+
const x = this.x, y = this.y, x1 = x + this.w, y1 = y + this.h;
|
|
87
|
+
return {
|
|
88
|
+
pathData: this.getPathData(), vertices: [{ x, y }, { x: x1, y }, { x: x1, y: y1 }, { x, y: y1 }], boundingRect: { x, y, width: this.w, height: this.h }
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
static getPathData(x = NaN, y = NaN, w = NaN, h = NaN, r = null) {
|
|
92
|
+
if (!r) {
|
|
93
|
+
return `M ${x} ${y} h ${w} v ${h} h ${-w} z`;
|
|
94
|
+
}
|
|
95
|
+
if (!Utils.isArray(r)) {
|
|
96
|
+
r = [r, r, r, r];
|
|
97
|
+
}
|
|
98
|
+
const tl = r[0], tr = r[1], br = r[2], bl = r[3];
|
|
99
|
+
const vx = (rx) => rx.unit === 'pct' ? rx.value * .01 * w : rx.value;
|
|
100
|
+
const vy = (ry) => ry.unit === 'pct' ? ry.value * .01 * h : ry.value;
|
|
101
|
+
const tlX = vx(tl.rx), tlY = vy(tl.ry);
|
|
102
|
+
const trX = vx(tr.rx), trY = vy(tr.ry);
|
|
103
|
+
const brX = vx(br.rx), brY = vy(br.ry);
|
|
104
|
+
const blX = vx(bl.rx), blY = vy(bl.ry);
|
|
105
|
+
let retval = `M ${x},${y + tlY}`;
|
|
106
|
+
// top-left
|
|
107
|
+
switch (tl.type) {
|
|
108
|
+
case 'cut':
|
|
109
|
+
retval += ` l ${tlX},${-tlY}`;
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
retval += ` a ${tlX} ${tlY} 0 0 1 ${tlX} ${-tlY}`;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
retval += ` h ${w - tlX - trX}`;
|
|
116
|
+
// top-right
|
|
117
|
+
switch (tr.type) {
|
|
118
|
+
case 'cut':
|
|
119
|
+
retval += ` l ${trX},${trY}`;
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
retval += ` a ${trX} ${trY} 0 0 1 ${trX} ${trY}`;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
retval += ` v ${h - trY - brY}`;
|
|
126
|
+
// bottom-right
|
|
127
|
+
switch (br.type) {
|
|
128
|
+
case 'cut':
|
|
129
|
+
retval += ` l ${-brX},${brY}`;
|
|
130
|
+
break;
|
|
131
|
+
default:
|
|
132
|
+
retval += ` a ${brX} ${brY} 0 0 1 ${-brX} ${brY}`;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
retval += ` h ${-(w - brX - blX)}`;
|
|
136
|
+
// bottom-left
|
|
137
|
+
switch (bl.type) {
|
|
138
|
+
case 'cut':
|
|
139
|
+
retval += ` l ${-blX},${-blY}`;
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
retval += ` a ${blX} ${blY} 0 0 1 ${-blX} ${-blY}`;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
return retval + ' z';
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
__decorate([
|
|
149
|
+
Watch({ emit: false, converter: PropertyConverters.Number })
|
|
150
|
+
], PacemRectElement.prototype, "x", void 0);
|
|
151
|
+
__decorate([
|
|
152
|
+
Watch({ emit: false, converter: PropertyConverters.Number })
|
|
153
|
+
], PacemRectElement.prototype, "y", void 0);
|
|
154
|
+
__decorate([
|
|
155
|
+
Watch({ emit: false, converter: PropertyConverters.Number })
|
|
156
|
+
], PacemRectElement.prototype, "w", void 0);
|
|
157
|
+
__decorate([
|
|
158
|
+
Watch({ emit: false, converter: PropertyConverters.Number })
|
|
159
|
+
], PacemRectElement.prototype, "h", void 0);
|
|
160
|
+
__decorate([
|
|
161
|
+
Watch({
|
|
162
|
+
emit: false, converter: {
|
|
163
|
+
convert: attr => parseCornerRadii(attr),
|
|
164
|
+
convertBack: (radii) => stringifyCornerRadii(radii)
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
], PacemRectElement.prototype, "r", void 0);
|
|
168
|
+
__decorate([
|
|
169
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
170
|
+
], PacemRectElement.prototype, "cornerType", void 0);
|
|
171
|
+
PacemRectElement = PacemRectElement_1 = __decorate([
|
|
172
|
+
CustomElement({ tagName: P + '-' + TAG_MIDDLE_NAME + '-rect' })
|
|
173
|
+
], PacemRectElement);
|
|
174
|
+
export { PacemRectElement };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { CustomElement, Watch, ViewChild, Debounce, PCSS, P, Utils, PropertyConverters, PropertyChangeEvent, CustomEventUtils, avoidHandler, EventKeyModifier, Components } from '@pacem/pacem-core';
|
|
8
|
+
import { Rect, Matrix2D } from '@pacem/pacem-foundation';
|
|
9
|
+
import { TAG_MIDDLE_NAME } from './constants';
|
|
10
|
+
import { DrawableElement } from './drawable-element';
|
|
11
|
+
import { isGroup } from './drawing';
|
|
12
|
+
//namespace Pacem.Components.Drawing {
|
|
13
|
+
// group [1] := align x,[3] := align y,[6] := slice
|
|
14
|
+
const ASPECTRATIO_PATTERN = /^\s*[xX]\s*([Mm](in|ax|id))\s*[yY]\s*([Mm](in|ax|id))(\s+(none|slice|meet))?\s*$/;
|
|
15
|
+
const aspectRatioPropertyConverter = {
|
|
16
|
+
convert: (attr) => {
|
|
17
|
+
const regArr = ASPECTRATIO_PATTERN.exec(attr);
|
|
18
|
+
if (regArr && regArr.length >= 4) {
|
|
19
|
+
return {
|
|
20
|
+
x: regArr[1].toLowerCase(),
|
|
21
|
+
y: regArr[3].toLowerCase(),
|
|
22
|
+
slice: regArr[6] === 'slice'
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return 'none';
|
|
26
|
+
},
|
|
27
|
+
convertBack: (val) => {
|
|
28
|
+
if (Utils.isNull(val) || typeof val === 'string') {
|
|
29
|
+
return 'none';
|
|
30
|
+
}
|
|
31
|
+
return `xM${(val.x.substring(1))}YM${(val.y.substring(1))} ${(val.slice ? 'slice' : 'meet')}`;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const DEFAULT_STAGE_OPTIONS = {
|
|
35
|
+
panControl: true,
|
|
36
|
+
zoomControl: true,
|
|
37
|
+
panModifiers: [EventKeyModifier.AltKey],
|
|
38
|
+
zoomModifiers: [EventKeyModifier.AltKey],
|
|
39
|
+
clickModifiers: []
|
|
40
|
+
};
|
|
41
|
+
export function getStageOptions(stage) {
|
|
42
|
+
const options = stage instanceof Pacem2DElement ? stage.options : {};
|
|
43
|
+
return Utils.extend({}, DEFAULT_STAGE_OPTIONS, options);
|
|
44
|
+
}
|
|
45
|
+
let Pacem2DElement = class Pacem2DElement extends Components.PacemItemsContainerElement {
|
|
46
|
+
constructor() {
|
|
47
|
+
super(...arguments);
|
|
48
|
+
this.#transformMatrix = Matrix2D.identity;
|
|
49
|
+
this.#options = DEFAULT_STAGE_OPTIONS;
|
|
50
|
+
this._resizeHandler = (evt) => {
|
|
51
|
+
this.#size = { x: evt.detail.left, y: evt.detail.top, width: evt.detail.width, height: evt.detail.height };
|
|
52
|
+
const adapter = this.adapter;
|
|
53
|
+
if (!Utils.isNull(adapter)) {
|
|
54
|
+
this._invalidateSize();
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
this._zoomHandler = (evt) => {
|
|
58
|
+
// only trusted ui interaction
|
|
59
|
+
if (!evt.isTrusted) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const opts = this.#options;
|
|
63
|
+
if (opts.zoomControl && CustomEventUtils.matchModifiers(evt, opts.zoomModifiers)) {
|
|
64
|
+
// prevent anything
|
|
65
|
+
avoidHandler(evt);
|
|
66
|
+
const zoomingOut = evt.deltaY < 0;
|
|
67
|
+
// center change?
|
|
68
|
+
const factor = .1, sign = zoomingOut ? -1 : 1, factorWSign = factor * sign, scale = 1 + factorWSign;
|
|
69
|
+
const stageRect = Utils.offsetRect(evt.currentTarget), pt = { x: evt.clientX, y: evt.clientY };
|
|
70
|
+
this._zoom(scale, stageRect, pt);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
this._panHandler = (evt) => {
|
|
74
|
+
const state = this.#panningStart, actual = this._getPanPoint(evt);
|
|
75
|
+
if (!Utils.isNullOrEmpty(state && state.point) && !Utils.isNull(actual)) {
|
|
76
|
+
avoidHandler(evt);
|
|
77
|
+
const factor = state.factor, vbox = state.box, start = state.point;
|
|
78
|
+
this.viewbox = {
|
|
79
|
+
x: vbox.x - factor * (actual.x - start.x),
|
|
80
|
+
y: vbox.y - factor * (actual.y - start.y),
|
|
81
|
+
width: vbox.width,
|
|
82
|
+
height: vbox.height
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
this._panStartHandler = (evt) => {
|
|
87
|
+
const opts = this.#options;
|
|
88
|
+
if (!opts.panControl) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// only trusted ui interaction
|
|
92
|
+
if (!evt.isTrusted) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const size = this.#size, vbox = this.viewbox || { x: 0, y: 0, width: size.width, height: size.height }, start = this._getPanPoint(evt);
|
|
96
|
+
if (start) {
|
|
97
|
+
avoidHandler(evt);
|
|
98
|
+
this._stage.style.pointerEvents = 'none';
|
|
99
|
+
const aspectRatio = this._getActualAspectRatio();
|
|
100
|
+
const wBased = vbox.width / size.width, hBased = vbox.height / size.height, factor = aspectRatio.slice ? Math.min(wBased, hBased) : Math.max(wBased, hBased);
|
|
101
|
+
this.#panningStart = { point: start, box: vbox, factor };
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
this._panEndHandler = (evt) => {
|
|
105
|
+
this._stage.style.pointerEvents = '';
|
|
106
|
+
this.#panningStart = null;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
get stage() {
|
|
110
|
+
return this._stage;
|
|
111
|
+
}
|
|
112
|
+
snapshot(bgColor, type, quality) {
|
|
113
|
+
const adapter = this.adapter;
|
|
114
|
+
if (Utils.isNull(adapter)) {
|
|
115
|
+
return Promise.resolve(null);
|
|
116
|
+
}
|
|
117
|
+
return adapter.snapshot(this, bgColor, type, quality);
|
|
118
|
+
}
|
|
119
|
+
#originalViewBox;
|
|
120
|
+
#transformMatrix;
|
|
121
|
+
get transformMatrix() {
|
|
122
|
+
return this.#transformMatrix;
|
|
123
|
+
}
|
|
124
|
+
_transformMatrixScale() {
|
|
125
|
+
const sizeObj = this.#size || Utils.offsetRect(this._stage);
|
|
126
|
+
var origVbox = this.#originalViewBox || sizeObj;
|
|
127
|
+
const vbox = this.viewbox || origVbox;
|
|
128
|
+
const aspectRatio = this.aspectRatio || 'none';
|
|
129
|
+
const mode = aspectRatio === 'none' ? 'stretch' : (aspectRatio.slice ? 'cover' : 'contain');
|
|
130
|
+
const actual = Rect.findTransform(vbox, origVbox, mode);
|
|
131
|
+
return actual.a;
|
|
132
|
+
}
|
|
133
|
+
validate(item) {
|
|
134
|
+
return item instanceof DrawableElement && /* only direct items */ Utils.isNull(item.parent);
|
|
135
|
+
}
|
|
136
|
+
draw(item, redraw = false) {
|
|
137
|
+
const adapter = this.adapter;
|
|
138
|
+
if (!this.disabled && !Utils.isNull(adapter)) {
|
|
139
|
+
let cancelable = new CustomEvent('predraw', { cancelable: true });
|
|
140
|
+
this.dispatchEvent(cancelable);
|
|
141
|
+
if (!cancelable.defaultPrevented) {
|
|
142
|
+
adapter.draw(this, item, redraw);
|
|
143
|
+
this.dispatchEvent(new CustomEvent('draw'));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
_drawDebounced(item, force = false) {
|
|
148
|
+
if (!Utils.isNull(item) && isGroup(item)) {
|
|
149
|
+
this.draw(item, force);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
this.draw(item);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
requestDraw(item, redraw = false) {
|
|
156
|
+
this._drawDebounced(item, redraw);
|
|
157
|
+
}
|
|
158
|
+
_buildUpDatasourceFromDOM() {
|
|
159
|
+
this.datasource = (this.items || []).slice();
|
|
160
|
+
}
|
|
161
|
+
#options;
|
|
162
|
+
#size;
|
|
163
|
+
_getActualAspectRatio() {
|
|
164
|
+
const aspectRatio = this.aspectRatio || 'none';
|
|
165
|
+
const alignmentX = aspectRatio === 'none' ? 'mid' : aspectRatio.x;
|
|
166
|
+
const alignmentY = aspectRatio === 'none' ? 'mid' : aspectRatio.y;
|
|
167
|
+
const slice = aspectRatio === 'none' ? false : aspectRatio.slice;
|
|
168
|
+
return { x: alignmentX, y: alignmentY, slice };
|
|
169
|
+
}
|
|
170
|
+
_zoomFromValue(scale) {
|
|
171
|
+
const sizeObj = this.#size;
|
|
172
|
+
if (Utils.isNull(sizeObj)) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const sizeRect = sizeObj;
|
|
176
|
+
const origVbox = this.#originalViewBox || sizeRect, vbox = this.viewbox || origVbox;
|
|
177
|
+
const aspectRatio = this.aspectRatio || 'none';
|
|
178
|
+
const mode = aspectRatio === 'none' ? 'stretch' : (aspectRatio.slice ? 'cover' : 'contain');
|
|
179
|
+
const actual = Rect.findTransform(vbox, sizeRect, mode);
|
|
180
|
+
const original = Rect.findTransform(origVbox, sizeRect, mode);
|
|
181
|
+
const actualScale = actual.a;
|
|
182
|
+
const origScale = original.a;
|
|
183
|
+
const targetScale = origScale * scale;
|
|
184
|
+
const incrementalInverseScale = actualScale / targetScale;
|
|
185
|
+
this._zoom(incrementalInverseScale);
|
|
186
|
+
}
|
|
187
|
+
_zoom(scale, stageRect, pt) {
|
|
188
|
+
if (Utils.isNull(stageRect)) {
|
|
189
|
+
stageRect = Utils.offsetRect(this._stage);
|
|
190
|
+
}
|
|
191
|
+
if (Utils.isNull(pt)) {
|
|
192
|
+
pt = { x: stageRect.x + stageRect.width * .5, y: stageRect.y + stageRect.height * .5 };
|
|
193
|
+
}
|
|
194
|
+
const sizeObj = this.#size, vbox = this.viewbox || sizeObj;
|
|
195
|
+
const vsize = Math.min(vbox.width, vbox.height), targetWidth = vsize * scale, targetHeight = vsize * scale;
|
|
196
|
+
if (targetWidth > 0 && targetHeight > 0) {
|
|
197
|
+
const aspectRatio = this._getActualAspectRatio();
|
|
198
|
+
const alignmentX = aspectRatio.x;
|
|
199
|
+
const alignmentY = aspectRatio.y;
|
|
200
|
+
const slice = aspectRatio.slice;
|
|
201
|
+
// offset
|
|
202
|
+
const vboxRatio = vbox.width / vbox.height, size = slice ? Math.max(stageRect.width, stageRect.height) : Math.min(stageRect.width, stageRect.height);
|
|
203
|
+
let
|
|
204
|
+
// to be adjusted based on aspectRatio
|
|
205
|
+
adjX, adjY;
|
|
206
|
+
;
|
|
207
|
+
switch (alignmentX) {
|
|
208
|
+
case 'mid':
|
|
209
|
+
adjX = (targetWidth - vbox.width) * (pt.x - stageRect.x - .5 * (stageRect.width - size)) / (size * vboxRatio);
|
|
210
|
+
break;
|
|
211
|
+
case 'max':
|
|
212
|
+
adjX = (targetWidth - vbox.width) * (pt.x - stageRect.x - (stageRect.width - size)) / (size * vboxRatio);
|
|
213
|
+
break;
|
|
214
|
+
default:
|
|
215
|
+
adjX = (targetWidth - vbox.width) * (pt.x - stageRect.x) / (size * vboxRatio);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
switch (alignmentY) {
|
|
219
|
+
case 'mid':
|
|
220
|
+
adjY = (targetHeight - vbox.height) * (pt.y - stageRect.y - .5 * (stageRect.height - size)) / (size * vboxRatio);
|
|
221
|
+
break;
|
|
222
|
+
case 'max':
|
|
223
|
+
adjY = (targetHeight - vbox.height) * (pt.y - stageRect.y - (stageRect.height - size)) / (size * vboxRatio);
|
|
224
|
+
break;
|
|
225
|
+
default:
|
|
226
|
+
adjY = (targetHeight - vbox.height) * (pt.y - stageRect.y) / (size * vboxRatio);
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
const targetX = vbox.x - adjX, targetY = vbox.y - adjY;
|
|
230
|
+
this.viewbox = { x: targetX, y: targetY, width: targetWidth, height: targetHeight };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
_getPanPoint(evt) {
|
|
234
|
+
const opts = this.#options;
|
|
235
|
+
if (evt instanceof MouseEvent && CustomEventUtils.matchModifiers(evt, opts.panModifiers)) {
|
|
236
|
+
return CustomEventUtils.getEventCoordinates(evt).page;
|
|
237
|
+
}
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
#panningStart;
|
|
241
|
+
_invalidateSize() {
|
|
242
|
+
this.adapter.invalidateSize(this, this.#size);
|
|
243
|
+
const prevTransformMatrix = this.#transformMatrix;
|
|
244
|
+
this.#transformMatrix = this.adapter.getTransformMatrix(this);
|
|
245
|
+
this.dispatchEvent(new PropertyChangeEvent({ propertyName: 'transformMatrix', currentValue: this.#transformMatrix, oldValue: prevTransformMatrix }));
|
|
246
|
+
this.zoom = this._transformMatrixScale();
|
|
247
|
+
this.dispatchEvent(new Components.ResizeEvent(this.#size));
|
|
248
|
+
}
|
|
249
|
+
viewActivatedCallback() {
|
|
250
|
+
super.viewActivatedCallback();
|
|
251
|
+
const adapter = this.adapter;
|
|
252
|
+
if (!Utils.isNull(adapter)) {
|
|
253
|
+
adapter.initialize(this);
|
|
254
|
+
this._invalidateSize();
|
|
255
|
+
// request draw right away
|
|
256
|
+
this._drawDebounced();
|
|
257
|
+
}
|
|
258
|
+
const resize = this._resize;
|
|
259
|
+
resize.addEventListener(Components.ResizeEventName, this._resizeHandler, false);
|
|
260
|
+
const stage = this._stage;
|
|
261
|
+
resize.target = stage;
|
|
262
|
+
const options = { capture: false, passive: true };
|
|
263
|
+
// zooming
|
|
264
|
+
stage.addEventListener('wheel', this._zoomHandler, false);
|
|
265
|
+
// panning
|
|
266
|
+
stage.addEventListener('mousedown', this._panStartHandler, false);
|
|
267
|
+
stage.addEventListener('touchstart', this._panStartHandler, options);
|
|
268
|
+
window.addEventListener('mousemove', this._panHandler, false);
|
|
269
|
+
window.addEventListener('mouseup', this._panEndHandler, false);
|
|
270
|
+
window.addEventListener('touchmove', this._panHandler, options);
|
|
271
|
+
window.addEventListener('touchend', this._panEndHandler, options);
|
|
272
|
+
}
|
|
273
|
+
propertyChangedCallback(name, old, val, first) {
|
|
274
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
275
|
+
switch (name) {
|
|
276
|
+
case 'adapter':
|
|
277
|
+
if (!Utils.isNull(old)) {
|
|
278
|
+
old.dispose(this);
|
|
279
|
+
}
|
|
280
|
+
if (!Utils.isNull(val)) {
|
|
281
|
+
val.initialize(this);
|
|
282
|
+
this._invalidateSize();
|
|
283
|
+
this._drawDebounced();
|
|
284
|
+
}
|
|
285
|
+
break;
|
|
286
|
+
case 'aspectRatio':
|
|
287
|
+
if (!Utils.isNull(this.adapter)) {
|
|
288
|
+
this._invalidateSize();
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
case 'viewbox':
|
|
292
|
+
if (!Utils.isNull(this.adapter)) {
|
|
293
|
+
this._invalidateSize();
|
|
294
|
+
}
|
|
295
|
+
this.#originalViewBox ??= (this.viewbox || null);
|
|
296
|
+
break;
|
|
297
|
+
case 'items':
|
|
298
|
+
this._buildUpDatasourceFromDOM();
|
|
299
|
+
break;
|
|
300
|
+
case 'zoom':
|
|
301
|
+
if (val !== this._transformMatrixScale()) {
|
|
302
|
+
this._zoomFromValue(val);
|
|
303
|
+
}
|
|
304
|
+
break;
|
|
305
|
+
case 'options':
|
|
306
|
+
this.#options = getStageOptions(this); // Utils.extend({}, DEFAULT_STAGE_OPTIONS, val || {});
|
|
307
|
+
break;
|
|
308
|
+
case 'disabled':
|
|
309
|
+
case 'datasource':
|
|
310
|
+
this._drawDebounced();
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
disconnectedCallback() {
|
|
315
|
+
const resizer = this._resize, stage = this._stage;
|
|
316
|
+
if (!Utils.isNull(resizer)) {
|
|
317
|
+
resizer.removeEventListener(Components.ResizeEventName, this._resizeHandler, false);
|
|
318
|
+
}
|
|
319
|
+
if (!Utils.isNull(stage)) {
|
|
320
|
+
// zooming
|
|
321
|
+
stage.removeEventListener('wheel', this._zoomHandler, false);
|
|
322
|
+
// panning
|
|
323
|
+
stage.removeEventListener('mousedown', this._panStartHandler, false);
|
|
324
|
+
stage.removeEventListener('touchstart', this._panStartHandler);
|
|
325
|
+
window.removeEventListener('mousemove', this._panHandler, false);
|
|
326
|
+
window.removeEventListener('mouseup', this._panEndHandler, false);
|
|
327
|
+
window.removeEventListener('touchmove', this._panHandler);
|
|
328
|
+
window.removeEventListener('touchend', this._panEndHandler);
|
|
329
|
+
}
|
|
330
|
+
if (!Utils.isNull(this.adapter)) {
|
|
331
|
+
this.adapter.dispose(this);
|
|
332
|
+
}
|
|
333
|
+
super.disconnectedCallback();
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
__decorate([
|
|
337
|
+
Watch({ converter: PropertyConverters.Element })
|
|
338
|
+
], Pacem2DElement.prototype, "adapter", void 0);
|
|
339
|
+
__decorate([
|
|
340
|
+
Watch({ reflectBack: true, converter: PropertyConverters.Rect })
|
|
341
|
+
], Pacem2DElement.prototype, "viewbox", void 0);
|
|
342
|
+
__decorate([
|
|
343
|
+
Watch({ emit: false, reflectBack: true, converter: aspectRatioPropertyConverter })
|
|
344
|
+
], Pacem2DElement.prototype, "aspectRatio", void 0);
|
|
345
|
+
__decorate([
|
|
346
|
+
Watch({ emit: false, converter: PropertyConverters.Json })
|
|
347
|
+
], Pacem2DElement.prototype, "datasource", void 0);
|
|
348
|
+
__decorate([
|
|
349
|
+
Watch({ emit: false, converter: PropertyConverters.Json })
|
|
350
|
+
], Pacem2DElement.prototype, "options", void 0);
|
|
351
|
+
__decorate([
|
|
352
|
+
Watch({ converter: PropertyConverters.Number })
|
|
353
|
+
], Pacem2DElement.prototype, "zoom", void 0);
|
|
354
|
+
__decorate([
|
|
355
|
+
ViewChild('.' + PCSS + '-2d')
|
|
356
|
+
], Pacem2DElement.prototype, "_stage", void 0);
|
|
357
|
+
__decorate([
|
|
358
|
+
ViewChild(P + '-resize')
|
|
359
|
+
], Pacem2DElement.prototype, "_resize", void 0);
|
|
360
|
+
__decorate([
|
|
361
|
+
Debounce(true)
|
|
362
|
+
], Pacem2DElement.prototype, "_drawDebounced", null);
|
|
363
|
+
Pacem2DElement = __decorate([
|
|
364
|
+
CustomElement({ tagName: P + '-' + TAG_MIDDLE_NAME, shadow: true, template: `<${P}-resize watch-position="true"></${P}-resize><div class="${PCSS}-2d" part="container"></div><slot></slot>` })
|
|
365
|
+
], Pacem2DElement);
|
|
366
|
+
export { Pacem2DElement };
|
package/dist/esm/text.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { CustomElement, Watch, PropertyConverters, P, Utils } from '@pacem/pacem-core';
|
|
8
|
+
import { UiElement } from './types';
|
|
9
|
+
import { TAG_MIDDLE_NAME } from './constants';
|
|
10
|
+
//namespace Pacem.Components.Drawing {
|
|
11
|
+
let PacemTextElement = class PacemTextElement extends UiElement {
|
|
12
|
+
propertyChangedCallback(name, old, val, first) {
|
|
13
|
+
if (!first) {
|
|
14
|
+
switch (name) {
|
|
15
|
+
case 'text':
|
|
16
|
+
case 'color':
|
|
17
|
+
case 'fontFamily':
|
|
18
|
+
case 'fontSize':
|
|
19
|
+
case 'fontWeight':
|
|
20
|
+
case 'fontStyle':
|
|
21
|
+
case 'anchor':
|
|
22
|
+
if (!Utils.isNull(this.stage)) {
|
|
23
|
+
this.stage.draw(this);
|
|
24
|
+
}
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
__decorate([
|
|
31
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
32
|
+
], PacemTextElement.prototype, "text", void 0);
|
|
33
|
+
__decorate([
|
|
34
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
35
|
+
], PacemTextElement.prototype, "color", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
38
|
+
], PacemTextElement.prototype, "fontFamily", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
Watch({ emit: false, converter: PropertyConverters.Number })
|
|
41
|
+
], PacemTextElement.prototype, "fontSize", void 0);
|
|
42
|
+
__decorate([
|
|
43
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
44
|
+
], PacemTextElement.prototype, "fontWeight", void 0);
|
|
45
|
+
__decorate([
|
|
46
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
47
|
+
], PacemTextElement.prototype, "fontStyle", void 0);
|
|
48
|
+
__decorate([
|
|
49
|
+
Watch({ emit: false, converter: PropertyConverters.Point })
|
|
50
|
+
], PacemTextElement.prototype, "anchor", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
53
|
+
], PacemTextElement.prototype, "textAnchor", void 0);
|
|
54
|
+
PacemTextElement = __decorate([
|
|
55
|
+
CustomElement({ tagName: P + '-' + TAG_MIDDLE_NAME + '-text' })
|
|
56
|
+
], PacemTextElement);
|
|
57
|
+
export { PacemTextElement };
|