@pacem/pacem-charts 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-charts.js +1623 -0
- package/dist/browser/pacem-charts.js.map +1 -0
- package/dist/browser/pacem-charts.min.js +2 -0
- package/dist/browser/pacem-charts.min.js.map +1 -0
- package/dist/bundle/pacem-charts.min.mjs +1 -0
- package/dist/bundle/pacem-charts.mjs +1462 -0
- package/dist/bundle/pacem-charts.mjs.map +7 -0
- package/dist/esm/column.js +357 -0
- package/dist/esm/generic.js +437 -0
- package/dist/esm/index-components-charts.js +4 -0
- package/dist/esm/index-components.js +1 -0
- package/dist/esm/index-iife.js +3 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/pie.js +306 -0
- package/dist/esm/types.js +504 -0
- package/package.json +38 -0
- package/typings/index.d.ts +239 -0
|
@@ -0,0 +1,437 @@
|
|
|
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, PCSS, Utils, CustomElementUtils, Logging } from '@pacem/pacem-core';
|
|
8
|
+
import { PacemSeriesChartElement } from './types';
|
|
9
|
+
//namespace Pacem.Components.Charts {
|
|
10
|
+
/**
|
|
11
|
+
* Returns the anchor points for a Bézier curve.
|
|
12
|
+
* @param p The actual point.
|
|
13
|
+
* @param p0 The previous point, if any.
|
|
14
|
+
* @param p1 The next point, if any.
|
|
15
|
+
*/
|
|
16
|
+
function getSplineCtrlPoints(p, p0, p1) {
|
|
17
|
+
let c0 = p, c1 = p;
|
|
18
|
+
const p0Null = Utils.isNull(p0), p1Null = Utils.isNull(p1);
|
|
19
|
+
if (!(p0Null && p1Null)) {
|
|
20
|
+
const portion = 3;
|
|
21
|
+
let m0, m1;
|
|
22
|
+
if (!p0Null) {
|
|
23
|
+
m0 = (p.y - p0.y) / (p.x - p0.x);
|
|
24
|
+
}
|
|
25
|
+
if (!p1Null) {
|
|
26
|
+
m1 = (p1.y - p.y) / (p1.x - p.x);
|
|
27
|
+
}
|
|
28
|
+
// average slope
|
|
29
|
+
const m = ((m1 || (m0 || 0)) + (m0 || (m1 || 0))) / 2;
|
|
30
|
+
const dx0 = p0Null ? 0 : (p.x - p0.x) / portion;
|
|
31
|
+
const dx1 = p1Null ? 0 : (p1.x - p.x) / portion;
|
|
32
|
+
c0 = { x: p.x - dx0, y: p.y - dx0 * m };
|
|
33
|
+
c1 = { x: p.x + dx1, y: p.y + dx1 * m };
|
|
34
|
+
}
|
|
35
|
+
return { c0: c0, c1: c1 };
|
|
36
|
+
}
|
|
37
|
+
const GET_VAL = CustomElementUtils.getAttachedPropertyValue;
|
|
38
|
+
const SET_VAL = CustomElementUtils.setAttachedPropertyValue;
|
|
39
|
+
const DEL_VAL = CustomElementUtils.deleteAttachedPropertyValue;
|
|
40
|
+
const PADDING_PIXELS = 24;
|
|
41
|
+
const SERIES_MAGNITUDE = 'pacem:chart-series:area';
|
|
42
|
+
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
43
|
+
let PacemChartElement = class PacemChartElement extends PacemSeriesChartElement {
|
|
44
|
+
constructor() {
|
|
45
|
+
super(...arguments);
|
|
46
|
+
this.#hover = false;
|
|
47
|
+
this._enterHandler = (evt) => {
|
|
48
|
+
this.#hover = true;
|
|
49
|
+
};
|
|
50
|
+
this._leaveHandler = (evt) => {
|
|
51
|
+
this.#hover = false;
|
|
52
|
+
};
|
|
53
|
+
this._moveHandler = (evt) => {
|
|
54
|
+
if (!this.#hover) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
this._chartFillSeries = [];
|
|
59
|
+
}
|
|
60
|
+
// TODO: implement
|
|
61
|
+
// @Watch({ converter: PropertyConverters.String }) hoverMode: 'abscissa' | 'point'; // 'point' assumed as default
|
|
62
|
+
_getVirtualGrid(items, minX, maxX, minY, maxY, xAxisType = this.xAxisType, steps, labels) {
|
|
63
|
+
return super.getVirtualGrid(items, minX, maxX, minY, maxY, xAxisType, steps, labels);
|
|
64
|
+
}
|
|
65
|
+
_wipe(series = this.chartSeries, startIndex = 0) {
|
|
66
|
+
super.wipeOut(series, startIndex);
|
|
67
|
+
}
|
|
68
|
+
viewActivatedCallback() {
|
|
69
|
+
super.viewActivatedCallback();
|
|
70
|
+
this._setupBehavior();
|
|
71
|
+
}
|
|
72
|
+
disconnectedCallback() {
|
|
73
|
+
this._dismantleBehavior();
|
|
74
|
+
super.disconnectedCallback();
|
|
75
|
+
}
|
|
76
|
+
propertyChangedCallback(name, old, val, first) {
|
|
77
|
+
super.propertyChangedCallback(name, old, val, first);
|
|
78
|
+
switch (name) {
|
|
79
|
+
case 'type':
|
|
80
|
+
case 'aspectRatio':
|
|
81
|
+
this.draw();
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
_setupBehavior() {
|
|
86
|
+
this.addEventListener('mouseenter', this._enterHandler, false);
|
|
87
|
+
this.addEventListener('mouseleave', this._enterHandler, false);
|
|
88
|
+
this.addEventListener('mousemove', this._moveHandler, false);
|
|
89
|
+
}
|
|
90
|
+
_dismantleBehavior() {
|
|
91
|
+
this.removeEventListener('mouseenter', this._enterHandler, false);
|
|
92
|
+
this.removeEventListener('mouseleave', this._leaveHandler, false);
|
|
93
|
+
this.removeEventListener('mousemove', this._moveHandler, false);
|
|
94
|
+
}
|
|
95
|
+
#hover;
|
|
96
|
+
_buildLinearGradient(seriesIndex) {
|
|
97
|
+
return super.buildLinearGradient(seriesIndex);
|
|
98
|
+
}
|
|
99
|
+
_setGradientColor(grad, color) {
|
|
100
|
+
super.setGradientColor(grad, color);
|
|
101
|
+
}
|
|
102
|
+
drawSeries(datasource) {
|
|
103
|
+
if (!this.isReady || Utils.isNull(this.chartSize)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.ensureChartContainer();
|
|
107
|
+
const type = this.type || 'line';
|
|
108
|
+
const padding = PADDING_PIXELS;
|
|
109
|
+
// resize all
|
|
110
|
+
var size = this.chartSize;
|
|
111
|
+
if (size.height <= padding || size.width <= padding) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
// items && labels?
|
|
115
|
+
if (Utils.isNullOrEmpty(datasource) || datasource.every(i => Utils.isNullOrEmpty(i.values))) {
|
|
116
|
+
this._wipe();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const body = this.ensureChartBody('line', size.width, size.height);
|
|
120
|
+
// from now on, drawing...
|
|
121
|
+
this.log(Logging.LogLevel.Debug, `Drawing ${type} chart.`);
|
|
122
|
+
// #region computations
|
|
123
|
+
const xAxisType = this.xAxisType || 'string';
|
|
124
|
+
let minY = this.yAxisMin ?? Number.NaN, maxY = this.yAxisMax ?? Number.NaN, minX = Number.NaN, maxX = Number.NaN;
|
|
125
|
+
let stretch = 1;
|
|
126
|
+
// individuate the min/max x & y in order correctly apply aspect ratio...
|
|
127
|
+
for (let series of datasource) {
|
|
128
|
+
let data = series.values;
|
|
129
|
+
if (data && data.length) {
|
|
130
|
+
let j = 0;
|
|
131
|
+
for (let item of data) {
|
|
132
|
+
let pt = this.chartDataItemToPoint(item, data);
|
|
133
|
+
if (Utils.isNull(this.yAxisMin)) {
|
|
134
|
+
minY = isNaN(minY) ? pt.y : Math.min(minY, pt.y);
|
|
135
|
+
}
|
|
136
|
+
if (Utils.isNull(this.yAxisMax)) {
|
|
137
|
+
maxY = isNaN(maxY) ? pt.y : Math.max(maxY, pt.y);
|
|
138
|
+
}
|
|
139
|
+
if (j === 0)
|
|
140
|
+
minX = isNaN(minX) ? pt.x : Math.min(minX, pt.x);
|
|
141
|
+
else if (j === data.length - 1)
|
|
142
|
+
maxX = isNaN(maxX) ? pt.x : Math.max(maxX, pt.x);
|
|
143
|
+
j++;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/** virtual grid made of x- and y-axis labels */
|
|
148
|
+
const withValues = datasource.find(i => !Utils.isNullOrEmpty(i.values));
|
|
149
|
+
const grid = this._getVirtualGrid(withValues.values, minX, maxX, minY, maxY, xAxisType, this.yAxisDensity, this.xAxisDensity);
|
|
150
|
+
const topGrid = grid.y[grid.y.length - 1], bottomGrid = grid.y[0];
|
|
151
|
+
if (topGrid === bottomGrid)
|
|
152
|
+
return;
|
|
153
|
+
// estimate y-axis max width
|
|
154
|
+
const halfPad = padding * .5;
|
|
155
|
+
const maxYLabelLength = grid.y.reduce((max, i) => Math.max(max, this.estimateYAxisLabelWidth(i) + halfPad), padding);
|
|
156
|
+
const maxXLabelHalfLength = grid.x.reduce((max, i) => Math.max(max, this.estimateXAxisLabelWidth(i)), padding) * .5;
|
|
157
|
+
const paddingYAxis = Math.max(maxXLabelHalfLength, maxYLabelLength), paddingYAxisEnd = maxXLabelHalfLength; // Math.max(padding, this.estimateXAxisLabelWidth(minX) * .5 + PADDING_PIXELS);
|
|
158
|
+
/** width of the WHOLE series dedicated area */
|
|
159
|
+
const seriesWidth = size.width - paddingYAxis - paddingYAxisEnd;
|
|
160
|
+
/** height of the WHOLE series dedicated area */
|
|
161
|
+
const gridHeight = (size.height - 2 * padding);
|
|
162
|
+
const seriesHeight = gridHeight * (1 - (topGrid - bottomGrid - (maxY - minY)) / (topGrid - bottomGrid));
|
|
163
|
+
const seriesY = gridHeight * (topGrid - maxY) / (topGrid - bottomGrid);
|
|
164
|
+
// const seriesY2 = gridHeight * (minY - bottomGrid) / (topGrid - bottomGrid);
|
|
165
|
+
// if not a `graph`
|
|
166
|
+
if (xAxisType !== 'number' || (this.aspectRatio !== 'monometric' && this.aspectRatio !== 'logaritmic')) {
|
|
167
|
+
// consider padding
|
|
168
|
+
stretch = seriesWidth / seriesHeight;
|
|
169
|
+
body.setAttribute('height', size.height.toString());
|
|
170
|
+
body.setAttribute('width', size.width.toString());
|
|
171
|
+
}
|
|
172
|
+
body.setAttribute('viewBox', `0 0 ${size.width} ${size.height}`);
|
|
173
|
+
// #endregion
|
|
174
|
+
// #region render series
|
|
175
|
+
let iter = 0;
|
|
176
|
+
// normalize
|
|
177
|
+
const spanX = maxX - minX, spanY = maxY - minY;
|
|
178
|
+
const normX = 100 * stretch / spanX, normY = 100 / spanY;
|
|
179
|
+
const normPadding = 100 * padding / seriesHeight;
|
|
180
|
+
const buildPoint = (it, series) => {
|
|
181
|
+
let p = this.chartDataItemToPoint(it, series);
|
|
182
|
+
//pt.x *= normX;
|
|
183
|
+
p.y *= normY;
|
|
184
|
+
// Limit as much as possible the magnitude of a number inclued in the svg.
|
|
185
|
+
// Big numbers "overflow the renderer".
|
|
186
|
+
p.x = (p.x - minX) * normX;
|
|
187
|
+
//pt.y = (pt.y - minY) * normY;
|
|
188
|
+
return p;
|
|
189
|
+
};
|
|
190
|
+
const chartSeries = this.chartSeries;
|
|
191
|
+
const chartFillSeries = this._chartFillSeries;
|
|
192
|
+
const chartGrid = this.chartGrid;
|
|
193
|
+
const splineHere = type === 'spline' || type === 'splinearea';
|
|
194
|
+
for (let series of datasource) {
|
|
195
|
+
// does the series svg exist?
|
|
196
|
+
let svg, svgFill;
|
|
197
|
+
let grad;
|
|
198
|
+
if (chartSeries.length > iter) {
|
|
199
|
+
svg = chartSeries[iter];
|
|
200
|
+
svgFill = chartFillSeries[iter];
|
|
201
|
+
grad = svgFill.firstElementChild.firstElementChild;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
svg = document.createElementNS(SVG_NS, 'svg');
|
|
205
|
+
svg.setAttribute('pacem', '');
|
|
206
|
+
body.appendChild(svg);
|
|
207
|
+
svgFill = document.createElementNS(SVG_NS, 'svg');
|
|
208
|
+
svgFill.setAttribute('pacem', '');
|
|
209
|
+
body.insertBefore(svgFill, body.children.item(iter + /* <defs> should remain the very first child and 'grid' the very second */ 2));
|
|
210
|
+
// 1st child - defs (gradient)
|
|
211
|
+
const defs = document.createElementNS(SVG_NS, 'defs');
|
|
212
|
+
defs.appendChild(grad = this._buildLinearGradient(iter));
|
|
213
|
+
svgFill.appendChild(defs);
|
|
214
|
+
// 2nd child - fill path
|
|
215
|
+
svgFill.appendChild(document.createElementNS(SVG_NS, 'path'));
|
|
216
|
+
chartFillSeries.push(svgFill);
|
|
217
|
+
// 1st child stroke path
|
|
218
|
+
svg.appendChild(document.createElementNS(SVG_NS, 'path'));
|
|
219
|
+
// 2nd + nth+1 child will be point circles
|
|
220
|
+
chartSeries.push(svg);
|
|
221
|
+
}
|
|
222
|
+
// series positioning:
|
|
223
|
+
/*
|
|
224
|
+
--------------------------------------
|
|
225
|
+
| |--------------------------------|
|
|
226
|
+
|pad| series here |
|
|
227
|
+
| |--------------------------------|
|
|
228
|
+
--------------------------------------
|
|
229
|
+
| | pad |
|
|
230
|
+
--------------------------------------
|
|
231
|
+
*/
|
|
232
|
+
let className = 'chart-series';
|
|
233
|
+
const fill = type === 'area' || type === 'splinearea';
|
|
234
|
+
if (!Utils.isNullOrEmpty(series.className)) {
|
|
235
|
+
className += ' ' + series.className;
|
|
236
|
+
}
|
|
237
|
+
[svg, svgFill].forEach(s => {
|
|
238
|
+
s.setAttribute('class', className);
|
|
239
|
+
s.setAttribute('x', paddingYAxis.toString());
|
|
240
|
+
s.setAttribute('y', seriesY.toString());
|
|
241
|
+
s.setAttribute('width', seriesWidth.toString());
|
|
242
|
+
s.setAttribute('height', (seriesHeight + 2 * padding).toString());
|
|
243
|
+
});
|
|
244
|
+
Utils.addClass(svgFill, PCSS + '-inert');
|
|
245
|
+
// pick path as single child element for the series.
|
|
246
|
+
let pathFill = svgFill.children.item(1);
|
|
247
|
+
let path = svg.firstElementChild;
|
|
248
|
+
path.style.stroke = series.color;
|
|
249
|
+
pathFill.style.stroke =
|
|
250
|
+
path.style.fill = 'none';
|
|
251
|
+
this._setGradientColor(grad, series.color);
|
|
252
|
+
pathFill.style.fill = `url(#${grad.id})`;
|
|
253
|
+
pathFill.style.display = fill ? '' : 'none';
|
|
254
|
+
let d = '';
|
|
255
|
+
let data = series.values;
|
|
256
|
+
if (data && data.length) {
|
|
257
|
+
const addInteractivePoint = (center, j, series, dataItem, color) => {
|
|
258
|
+
const ndx = j + /* count the <path> child */ 1;
|
|
259
|
+
let circle;
|
|
260
|
+
if (svg.children.length > ndx) {
|
|
261
|
+
circle = svg.children.item(ndx);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
circle = document.createElementNS(SVG_NS, 'line');
|
|
265
|
+
circle.setAttribute('class', 'circle');
|
|
266
|
+
svg.appendChild(circle);
|
|
267
|
+
}
|
|
268
|
+
const x1 = center.x.toString(), y1 = (-center.y).toString();
|
|
269
|
+
circle.setAttribute('x1', x1);
|
|
270
|
+
circle.setAttribute('y1', y1);
|
|
271
|
+
circle.setAttribute('x2', x1);
|
|
272
|
+
circle.setAttribute('y2', y1);
|
|
273
|
+
circle.style.stroke = color;
|
|
274
|
+
this.assignUiBehaviors(circle, series, dataItem, color);
|
|
275
|
+
};
|
|
276
|
+
const wipeExceedingPoints = () => {
|
|
277
|
+
const remaining = series.datapoints ? (data.length + 1) : 1;
|
|
278
|
+
for (let k = svg.children.length - 1; k >= remaining; k--) {
|
|
279
|
+
var circle = svg.children.item(k);
|
|
280
|
+
this.disposeUiBehaviors(circle);
|
|
281
|
+
circle.remove();
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
if (splineHere) {
|
|
285
|
+
// #region SPLINE
|
|
286
|
+
let pt0, pt, c0;
|
|
287
|
+
for (let j = 0; j < data.length; j++) {
|
|
288
|
+
const item = data[j];
|
|
289
|
+
if (isNaN(item.value)) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (!pt) {
|
|
293
|
+
pt = buildPoint(item, data);
|
|
294
|
+
}
|
|
295
|
+
let pt1;
|
|
296
|
+
if (splineHere && j < (data.length - 1)) {
|
|
297
|
+
pt1 = buildPoint(data[j + 1], data);
|
|
298
|
+
}
|
|
299
|
+
// accumulate `area` for sorting
|
|
300
|
+
let areaSoFar = GET_VAL(series, SERIES_MAGNITUDE, 0);
|
|
301
|
+
areaSoFar += item.value;
|
|
302
|
+
SET_VAL(series, SERIES_MAGNITUDE, areaSoFar);
|
|
303
|
+
var c = getSplineCtrlPoints(pt, pt0, pt1);
|
|
304
|
+
d += Utils.isNullOrEmpty(d) ? `M${pt.x},${-pt.y} ` : `C${c0.x},${-c0.y} ${c.c0.x},${-c.c0.y} ${pt.x},${-pt.y} `;
|
|
305
|
+
if (series.datapoints) {
|
|
306
|
+
addInteractivePoint(pt, j, series, item, series.color);
|
|
307
|
+
}
|
|
308
|
+
// step next
|
|
309
|
+
pt0 = pt;
|
|
310
|
+
pt = pt1, c0 = c.c1;
|
|
311
|
+
}
|
|
312
|
+
// #endregion
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
// #region LINE
|
|
316
|
+
let j = 0;
|
|
317
|
+
for (let item of data) {
|
|
318
|
+
if (isNaN(item.value)) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
const pt = buildPoint(item, data);
|
|
322
|
+
// accumulate `area` for sorting
|
|
323
|
+
let areaSoFar = GET_VAL(series, SERIES_MAGNITUDE, 0);
|
|
324
|
+
areaSoFar += item.value;
|
|
325
|
+
SET_VAL(series, SERIES_MAGNITUDE, areaSoFar);
|
|
326
|
+
d += Utils.isNullOrEmpty(d) ? `M${pt.x},${-pt.y} ` : `L${pt.x},${-pt.y} `;
|
|
327
|
+
if (series.datapoints) {
|
|
328
|
+
addInteractivePoint(pt, j, series, item, series.color);
|
|
329
|
+
}
|
|
330
|
+
j++;
|
|
331
|
+
}
|
|
332
|
+
// #endregion
|
|
333
|
+
}
|
|
334
|
+
wipeExceedingPoints();
|
|
335
|
+
}
|
|
336
|
+
path.setAttribute('d', d);
|
|
337
|
+
pathFill.setAttribute('d', d + `V${(-minY * normY)} H0 Z`);
|
|
338
|
+
// tick
|
|
339
|
+
iter++;
|
|
340
|
+
}
|
|
341
|
+
// remove exceeding series
|
|
342
|
+
this._wipe(chartFillSeries, iter);
|
|
343
|
+
this._wipe(chartSeries, iter);
|
|
344
|
+
const w0 = 100 * stretch, h0 = 100 + 2 * normPadding, x0 = 0, //minX * normX,
|
|
345
|
+
y0 = maxY * normY + normPadding;
|
|
346
|
+
const svbox = `${x0} ${-y0} ${w0} ${h0}`;
|
|
347
|
+
for (var svg of chartSeries.concat(chartFillSeries)) {
|
|
348
|
+
svg.setAttribute('viewBox', svbox);
|
|
349
|
+
}
|
|
350
|
+
const chartMask = this.chartMask;
|
|
351
|
+
let mask = chartMask.children.item(1);
|
|
352
|
+
mask.setAttribute('x', x0.toString());
|
|
353
|
+
mask.setAttribute('height', (size.height - padding).toString());
|
|
354
|
+
// #endregion
|
|
355
|
+
// #region grid
|
|
356
|
+
chartGrid.setAttribute('viewBox', `0 0 ${size.width} ${size.height}`);
|
|
357
|
+
if (grid.x.length <= 1 || grid.y.length <= 1) {
|
|
358
|
+
for (let j = chartGrid.children.length - 1; j >= 0; j--) {
|
|
359
|
+
chartGrid.children.item(j).remove();
|
|
360
|
+
}
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
let pgrid;
|
|
364
|
+
if (chartGrid.children.length > 0) {
|
|
365
|
+
pgrid = chartGrid.children.item(0);
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
pgrid = document.createElementNS(SVG_NS, 'path');
|
|
369
|
+
chartGrid.appendChild(pgrid);
|
|
370
|
+
}
|
|
371
|
+
const tick = padding * .25;
|
|
372
|
+
let lblCounter = 0;
|
|
373
|
+
let ensureLabel = (index, x, y, txt) => {
|
|
374
|
+
const ndx = index + /* <path> is the first child element */ 1;
|
|
375
|
+
let lbl;
|
|
376
|
+
if (chartGrid.children.length <= ndx) {
|
|
377
|
+
lbl = document.createElementNS(SVG_NS, 'text');
|
|
378
|
+
chartGrid.appendChild(lbl);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
lbl = chartGrid.children.item(ndx);
|
|
382
|
+
}
|
|
383
|
+
lbl.textContent = txt;
|
|
384
|
+
lbl.setAttribute('x', x.toString());
|
|
385
|
+
lbl.setAttribute('y', y.toString());
|
|
386
|
+
return lbl;
|
|
387
|
+
};
|
|
388
|
+
let dgrid = `M${paddingYAxis},${padding} v${gridHeight}`; //H${w}
|
|
389
|
+
// x
|
|
390
|
+
let j = 0;
|
|
391
|
+
const xincr = seriesWidth / (grid.x.length - 1), yincr = gridHeight / (grid.y.length - 1);
|
|
392
|
+
if (this.xAxisPosition !== 'none') {
|
|
393
|
+
for (var x of grid.x) {
|
|
394
|
+
const xcoord = paddingYAxis + j * xincr;
|
|
395
|
+
if (this.xAxisPosition === 'top') {
|
|
396
|
+
dgrid += ` M${xcoord},${padding} v${-tick}`;
|
|
397
|
+
let lbl = ensureLabel(lblCounter++, xcoord, 0, x);
|
|
398
|
+
lbl.setAttribute('text-anchor', 'middle');
|
|
399
|
+
lbl.setAttribute('alignment-baseline', 'hanging');
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
let ycoord = gridHeight + padding;
|
|
403
|
+
dgrid += ` M${xcoord},${ycoord} v${tick}`;
|
|
404
|
+
ensureLabel(lblCounter++, xcoord, ycoord + padding, x).setAttribute('text-anchor', 'middle');
|
|
405
|
+
}
|
|
406
|
+
j++;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// y
|
|
410
|
+
j = 0;
|
|
411
|
+
for (var y of grid.y) {
|
|
412
|
+
const ycoord = gridHeight + padding - j * yincr, xcoord = paddingYAxis - tick;
|
|
413
|
+
dgrid += ` M${xcoord},${ycoord} H${(seriesWidth + paddingYAxis)}`;
|
|
414
|
+
let txt = this.formatYAxisLabel(y);
|
|
415
|
+
ensureLabel(lblCounter++, xcoord - tick, ycoord, txt).setAttribute('text-anchor', 'end');
|
|
416
|
+
j++;
|
|
417
|
+
}
|
|
418
|
+
pgrid.setAttribute('d', dgrid);
|
|
419
|
+
// exceeding labels?
|
|
420
|
+
for (let j = chartGrid.children.length - 1; j > lblCounter; j--) {
|
|
421
|
+
chartGrid.children.item(j).remove();
|
|
422
|
+
}
|
|
423
|
+
// #endregion
|
|
424
|
+
// #region abscissa cursor
|
|
425
|
+
// #endregion
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
__decorate([
|
|
429
|
+
Watch({ emit: false, converter: PropertyConverters.String })
|
|
430
|
+
], PacemChartElement.prototype, "type", void 0);
|
|
431
|
+
__decorate([
|
|
432
|
+
Watch({ converter: PropertyConverters.String })
|
|
433
|
+
], PacemChartElement.prototype, "aspectRatio", void 0);
|
|
434
|
+
PacemChartElement = __decorate([
|
|
435
|
+
CustomElement({ tagName: P + '-chart' })
|
|
436
|
+
], PacemChartElement);
|
|
437
|
+
export { PacemChartElement };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as Charts from './index-components-charts';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as Components from './index-components';
|