@ixfx/components 0.1.5 → 0.2.0
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/bundle/index.d.ts +105 -37
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +471 -156
- package/bundle/index.js.map +1 -1
- package/dist/charts/plot.d.ts +104 -36
- package/dist/charts/plot.d.ts.map +1 -1
- package/dist/charts/plot.js +621 -175
- package/dist/charts/plot.js.map +1 -1
- package/package.json +13 -13
package/dist/charts/plot.js
CHANGED
|
@@ -6,13 +6,75 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
6
6
|
};
|
|
7
7
|
import { css, html, LitElement } from "lit";
|
|
8
8
|
import { customElement, property } from "lit/decorators.js";
|
|
9
|
-
//import { property } from "lit/decorators/property.js";
|
|
10
9
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
11
10
|
import { CanvasHelper } from "ixfx/visual.js";
|
|
11
|
+
import { Rects } from "ixfx/geometry.js";
|
|
12
|
+
import * as Arrays from 'ixfx/arrays.js';
|
|
12
13
|
import * as Numbers from 'ixfx/numbers.js';
|
|
13
14
|
import { getCssVariable } from 'ixfx/dom.js';
|
|
14
15
|
import { Drawing, Colour } from "ixfx/visual.js";
|
|
15
16
|
import { Pathed } from 'ixfx';
|
|
17
|
+
const rangeIsEqual = (a, b) => {
|
|
18
|
+
if (a === undefined || b === undefined)
|
|
19
|
+
return false;
|
|
20
|
+
return (a.max === b.max && a.min === b.min);
|
|
21
|
+
};
|
|
22
|
+
export class PlotAxis {
|
|
23
|
+
// units: Readonly<{ major: number, minor: number }> = { major: Number.NaN, minor: Number.NaN }
|
|
24
|
+
// altAxisCrossing: AxisCrossing<T> = { at: `min` }
|
|
25
|
+
// ticks: TickMarks = { major: `inside`, minor: `inside` }
|
|
26
|
+
// labels: AxisLabels = `axis`;
|
|
27
|
+
#currentScalerRange;
|
|
28
|
+
#currentScaler;
|
|
29
|
+
constructor(name) {
|
|
30
|
+
this.name = name;
|
|
31
|
+
this.bounds = `automatic`;
|
|
32
|
+
this.#currentScaler = (v) => v;
|
|
33
|
+
}
|
|
34
|
+
humanFormatValue(value) {
|
|
35
|
+
if (value.length === 0)
|
|
36
|
+
return ``;
|
|
37
|
+
const v = value[0];
|
|
38
|
+
if (v < 2)
|
|
39
|
+
return v.toFixed(2);
|
|
40
|
+
return v.toString();
|
|
41
|
+
}
|
|
42
|
+
getRange(series) {
|
|
43
|
+
if (this.bounds === `automatic`)
|
|
44
|
+
return this.computeActualRange(series);
|
|
45
|
+
return this.bounds;
|
|
46
|
+
}
|
|
47
|
+
getCurrentRange() {
|
|
48
|
+
return this.#currentScalerRange;
|
|
49
|
+
}
|
|
50
|
+
getValueScaler(series) {
|
|
51
|
+
const r = this.getRange(series);
|
|
52
|
+
if (!rangeIsEqual(r, this.#currentScalerRange)) {
|
|
53
|
+
this.#currentScalerRange = r;
|
|
54
|
+
this.#currentScaler = Numbers.scaler(r.min, r.max, 0, 1);
|
|
55
|
+
}
|
|
56
|
+
return this.#currentScaler;
|
|
57
|
+
}
|
|
58
|
+
computeActualRange(seriesOnAxis, column = 0) {
|
|
59
|
+
let min = Number.MAX_SAFE_INTEGER;
|
|
60
|
+
let max = Number.MIN_SAFE_INTEGER;
|
|
61
|
+
let count = 0;
|
|
62
|
+
for (const s of seriesOnAxis) {
|
|
63
|
+
for (const [v, _index] of s.getValuesForColumn(column)) {
|
|
64
|
+
if (typeof v !== `number`)
|
|
65
|
+
continue;
|
|
66
|
+
if (Number.isNaN(v))
|
|
67
|
+
continue;
|
|
68
|
+
if (v < min)
|
|
69
|
+
min = v;
|
|
70
|
+
if (v > max)
|
|
71
|
+
max = v;
|
|
72
|
+
}
|
|
73
|
+
count++;
|
|
74
|
+
}
|
|
75
|
+
return { min, max };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
16
78
|
/**
|
|
17
79
|
* Attributes
|
|
18
80
|
* * streaming: true/false (default: true)
|
|
@@ -22,7 +84,7 @@ import { Pathed } from 'ixfx';
|
|
|
22
84
|
*
|
|
23
85
|
* * line-width: stroke width of drawing line (default:2)
|
|
24
86
|
*
|
|
25
|
-
* * render: 'dot' or '
|
|
87
|
+
* * render: 'dot', 'line' or 'bar'(default: 'dot')
|
|
26
88
|
* * hide-legend: If added, legend is not shown
|
|
27
89
|
* * manual-draw: If added, automatic drawning is disabled
|
|
28
90
|
*
|
|
@@ -31,36 +93,107 @@ import { Pathed } from 'ixfx';
|
|
|
31
93
|
*/
|
|
32
94
|
let PlotElement = class PlotElement extends LitElement {
|
|
33
95
|
constructor() {
|
|
96
|
+
//@property({ attribute: `streaming`, type: Boolean })
|
|
97
|
+
//streaming = true;
|
|
34
98
|
super(...arguments);
|
|
35
|
-
this.streaming = true;
|
|
36
99
|
this.hideLegend = false;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
100
|
+
//@property({ attribute: `max-length`, type: Number })
|
|
101
|
+
//maxLength = 500;
|
|
102
|
+
//@property({ attribute: `data-width`, type: Number })
|
|
103
|
+
//dataWidth = 5;
|
|
104
|
+
//@property({ attribute: `fixed-max`, type: Number })
|
|
105
|
+
//fixedMax = Number.NaN;
|
|
106
|
+
//@property({ attribute: `fixed-min`, type: Number })
|
|
107
|
+
//fixedMin = Number.NaN;
|
|
108
|
+
//@property({ attribute: `line-width`, type: Number })
|
|
109
|
+
//lineWidth = 2;
|
|
42
110
|
this.renderStyle = `dot`;
|
|
43
|
-
|
|
111
|
+
//@property({ attribute: `manual-draw`, type: Boolean })
|
|
112
|
+
//manualDraw = false;
|
|
44
113
|
this.padding = 5;
|
|
114
|
+
this.primaryAxis = new PlotAxis(`primary`);
|
|
115
|
+
this.secondaryAxis = new PlotAxis(`secondary`);
|
|
45
116
|
this.paused = false;
|
|
117
|
+
this.plotAreaFormat = {
|
|
118
|
+
fill: { type: `none` },
|
|
119
|
+
outline: { type: `none` }
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Settings used for automatically generating series colour
|
|
123
|
+
*/
|
|
124
|
+
this.automaticSeriesColour = {
|
|
125
|
+
saturation: 1,
|
|
126
|
+
lightness: 0.5,
|
|
127
|
+
alpha: 1
|
|
128
|
+
};
|
|
129
|
+
this.seriesDefault = {};
|
|
46
130
|
this.#series = new Map();
|
|
47
131
|
this.#legendColour = ``;
|
|
48
|
-
this.#
|
|
49
|
-
this
|
|
50
|
-
this
|
|
132
|
+
this.#autoSeriesColour = 0;
|
|
133
|
+
this.#hitboxes = [];
|
|
134
|
+
this.#seriesFormatting = new Map();
|
|
51
135
|
this.#swatchSize = 10;
|
|
136
|
+
this.canvasEl = createRef();
|
|
137
|
+
this.tooltipEl = createRef();
|
|
138
|
+
this.seriesColourGenerate = (_seriesName) => {
|
|
139
|
+
const c = Colour.goldenAngleColour(this.#autoSeriesColour, this.automaticSeriesColour.saturation, this.automaticSeriesColour.lightness, this.automaticSeriesColour.alpha);
|
|
140
|
+
this.#autoSeriesColour++;
|
|
141
|
+
return c;
|
|
142
|
+
};
|
|
52
143
|
}
|
|
53
144
|
#series;
|
|
54
145
|
#canvas;
|
|
55
146
|
#drawing;
|
|
56
147
|
#legendColour;
|
|
57
|
-
#
|
|
148
|
+
#autoSeriesColour;
|
|
149
|
+
#hitboxes;
|
|
150
|
+
#seriesFormatting;
|
|
151
|
+
#swatchSize;
|
|
58
152
|
get series() {
|
|
59
153
|
return [...this.#series.values()];
|
|
60
154
|
}
|
|
61
155
|
get seriesCount() {
|
|
62
156
|
return this.#series.size;
|
|
63
157
|
}
|
|
158
|
+
getSeriesFormatting(seriesName, createIfNeeded) {
|
|
159
|
+
let f = this.#seriesFormatting.get(seriesName);
|
|
160
|
+
if (!f && createIfNeeded) {
|
|
161
|
+
f = {
|
|
162
|
+
axis: `primary`,
|
|
163
|
+
fill: {
|
|
164
|
+
colour: this.seriesColourGenerate(seriesName),
|
|
165
|
+
type: `solid`
|
|
166
|
+
},
|
|
167
|
+
outline: {
|
|
168
|
+
type: `none`
|
|
169
|
+
},
|
|
170
|
+
bar: {
|
|
171
|
+
gapWidth: 10
|
|
172
|
+
},
|
|
173
|
+
dot: {
|
|
174
|
+
gapWidth: 0,
|
|
175
|
+
radius: `automatic`
|
|
176
|
+
},
|
|
177
|
+
line: {
|
|
178
|
+
width: 2,
|
|
179
|
+
cap: `round`,
|
|
180
|
+
join: `round`
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
this.#seriesFormatting.set(seriesName, f);
|
|
184
|
+
}
|
|
185
|
+
return f;
|
|
186
|
+
}
|
|
187
|
+
setSeriesFormatting(seriesName, formatting) {
|
|
188
|
+
let existing = this.getSeriesFormatting(seriesName, true);
|
|
189
|
+
const combined = {
|
|
190
|
+
...existing,
|
|
191
|
+
...formatting
|
|
192
|
+
};
|
|
193
|
+
combined.fill = resolveFillDrawStyle(combined.fill);
|
|
194
|
+
combined.outline = resolveOutlineDrawStyle(combined.outline);
|
|
195
|
+
this.#seriesFormatting.set(seriesName, combined);
|
|
196
|
+
}
|
|
64
197
|
/**
|
|
65
198
|
* Returns a `PlotElement` instance based on a query
|
|
66
199
|
* ```js
|
|
@@ -111,6 +244,7 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
111
244
|
*/
|
|
112
245
|
clear() {
|
|
113
246
|
this.#series.clear();
|
|
247
|
+
this.#autoSeriesColour = 0;
|
|
114
248
|
}
|
|
115
249
|
/**
|
|
116
250
|
* Keeps all series, but deletes their data
|
|
@@ -120,8 +254,54 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
120
254
|
s.clear();
|
|
121
255
|
}
|
|
122
256
|
}
|
|
123
|
-
|
|
124
|
-
|
|
257
|
+
#lastPointerPosition;
|
|
258
|
+
#onPointerLeave() {
|
|
259
|
+
this.#lastPointerPosition = undefined;
|
|
260
|
+
this.#hideTooltip();
|
|
261
|
+
}
|
|
262
|
+
#onPointerMove(event) {
|
|
263
|
+
this.#lastPointerPosition = {
|
|
264
|
+
x: event.offsetX,
|
|
265
|
+
screenX: event.x,
|
|
266
|
+
y: event.offsetY,
|
|
267
|
+
screenY: event.y
|
|
268
|
+
};
|
|
269
|
+
this.#updateToolTip();
|
|
270
|
+
}
|
|
271
|
+
#updateToolTip() {
|
|
272
|
+
if (!this.#lastPointerPosition)
|
|
273
|
+
return;
|
|
274
|
+
for (const hb of this.#hitboxes) {
|
|
275
|
+
if (Rects.intersectsPoint(hb, this.#lastPointerPosition)) {
|
|
276
|
+
if (hb.value) {
|
|
277
|
+
this.#setTooltip(hb.series.humanFormatValue(hb.value));
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
this.#setTooltip(``);
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
this.#hideTooltip();
|
|
286
|
+
}
|
|
287
|
+
#hideTooltip() {
|
|
288
|
+
const v = this.tooltipEl.value;
|
|
289
|
+
if (!v)
|
|
290
|
+
return;
|
|
291
|
+
v.classList.add(`hidden`);
|
|
292
|
+
}
|
|
293
|
+
#setTooltip(innerHtml) {
|
|
294
|
+
const v = this.tooltipEl.value;
|
|
295
|
+
if (!v)
|
|
296
|
+
return;
|
|
297
|
+
const pos = this.#lastPointerPosition;
|
|
298
|
+
v.classList.remove(`hidden`);
|
|
299
|
+
const offset = 10;
|
|
300
|
+
v.innerHTML = innerHtml;
|
|
301
|
+
if (pos) {
|
|
302
|
+
v.style.left = `${pos.screenX + offset}px`;
|
|
303
|
+
v.style.top = `${pos.screenY + offset}px`;
|
|
304
|
+
}
|
|
125
305
|
}
|
|
126
306
|
#setupCanvas() {
|
|
127
307
|
if (this.#canvas !== undefined)
|
|
@@ -138,62 +318,91 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
138
318
|
super.connectedCallback();
|
|
139
319
|
}
|
|
140
320
|
firstUpdated(_changedProperties) {
|
|
141
|
-
// const canvas = this.canvasEl.value!;
|
|
142
321
|
const ro = new ResizeObserver((event) => {
|
|
143
322
|
const c = this.#setupCanvas();
|
|
144
323
|
if (!c)
|
|
145
324
|
return;
|
|
146
325
|
const entry = event[0];
|
|
147
326
|
c.setLogicalSize(entry.contentRect);
|
|
327
|
+
if (this.#hasDirty())
|
|
328
|
+
this.draw();
|
|
148
329
|
});
|
|
149
330
|
ro.observe(this);
|
|
150
331
|
this.updateColours();
|
|
332
|
+
//this.#setupCanvas();
|
|
333
|
+
}
|
|
334
|
+
#hasDirty() {
|
|
335
|
+
for (const s of this.series.values()) {
|
|
336
|
+
if (s.isDirty)
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
return false;
|
|
151
340
|
}
|
|
152
341
|
updateColours() {
|
|
153
342
|
this.#legendColour = getCssVariable(`legend-fg`, `black`);
|
|
154
343
|
}
|
|
155
|
-
plot(value, seriesName = ``, skipDrawing = false) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
344
|
+
//plot(value: number, seriesName = ``, skipDrawing = false) {
|
|
345
|
+
// plotValue(primary: number | string, secondary: number | string, seriesName: string, skipDrawing = false) {
|
|
346
|
+
// //if (typeof primary !== 'number' && typeof primary !== `string`) throw new TypeError(`Can only add numbers. Got: ${ typeof value }`);
|
|
347
|
+
// let s = this.#series.get(seriesName.toLowerCase());
|
|
348
|
+
// if (s === undefined) {
|
|
349
|
+
// s = new PlotSeries(seriesName, this);
|
|
350
|
+
// this.#series.set(seriesName.toLowerCase(), s);
|
|
351
|
+
// }
|
|
352
|
+
// const v: DataValue = { primary, secondary };
|
|
353
|
+
// //s.push(value);
|
|
354
|
+
// s.pushValue(v)
|
|
355
|
+
// if (!this.manualDraw && !skipDrawing) this.draw();
|
|
356
|
+
// return s;
|
|
357
|
+
// }
|
|
358
|
+
setRawValues(values, seriesName, automaticallyDraw) {
|
|
169
359
|
if (!Array.isArray(values))
|
|
170
360
|
throw new TypeError(`Param 'values' is not an array`);
|
|
171
|
-
let s = this
|
|
172
|
-
|
|
173
|
-
s = new PlotSeries(seriesName, this.colourGenerator(seriesName), this);
|
|
174
|
-
this.#series.set(seriesName.toLowerCase(), s);
|
|
175
|
-
}
|
|
176
|
-
s.setValues(values);
|
|
177
|
-
if (!this.manualDraw && !skipDrawing)
|
|
178
|
-
this.draw();
|
|
361
|
+
let s = this.getOrCreateSeries(seriesName);
|
|
362
|
+
s.setRawValues(values, automaticallyDraw);
|
|
179
363
|
return s;
|
|
180
364
|
}
|
|
181
365
|
/**
|
|
182
|
-
*
|
|
366
|
+
* Treats each property of an object as the series name
|
|
183
367
|
* @param value
|
|
368
|
+
* @param automaticallyDraw
|
|
184
369
|
*/
|
|
185
|
-
|
|
370
|
+
appendObjectBySeries(value, automaticallyDraw) {
|
|
186
371
|
for (const p of Pathed.getPathsAndData(value, true)) {
|
|
187
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-
|
|
188
|
-
|
|
372
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
373
|
+
const v = p.value;
|
|
374
|
+
if (typeof v === `number`) {
|
|
375
|
+
this.appendRawValues(v, p.path, false);
|
|
376
|
+
}
|
|
189
377
|
}
|
|
190
|
-
|
|
378
|
+
if (automaticallyDraw)
|
|
379
|
+
this.draw();
|
|
191
380
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
381
|
+
appendRawValues(values, seriesName, automaticallyDraw) {
|
|
382
|
+
if (!Array.isArray(values))
|
|
383
|
+
values = [values];
|
|
384
|
+
let s = this.getOrCreateSeries(seriesName);
|
|
385
|
+
for (const v of values) {
|
|
386
|
+
s.pushValue(v, false);
|
|
387
|
+
}
|
|
388
|
+
if (automaticallyDraw)
|
|
389
|
+
this.draw();
|
|
196
390
|
}
|
|
391
|
+
/**
|
|
392
|
+
* Draw a set of key-value pairs as a batch.
|
|
393
|
+
* @param value
|
|
394
|
+
*/
|
|
395
|
+
// plotObject(value: object) {
|
|
396
|
+
// for (const p of Pathed.getPathsAndData(value, true)) {
|
|
397
|
+
// this.plot(p.value, p.path, true);
|
|
398
|
+
// }
|
|
399
|
+
// this.draw();
|
|
400
|
+
// }
|
|
401
|
+
// colourGenerator(_series: string): Colour.Colourish {
|
|
402
|
+
// const c = Colour.HslSpace.scalar(this.#hue, 0.9, 0.4);
|
|
403
|
+
// this.#hue = Numbers.wrap(this.#hue + 0.1);
|
|
404
|
+
// return c;
|
|
405
|
+
// }
|
|
197
406
|
draw() {
|
|
198
407
|
if (this.paused)
|
|
199
408
|
return;
|
|
@@ -206,16 +415,11 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
206
415
|
const ctx = d.ctx;
|
|
207
416
|
const axisYwidth = this.computeAxisYWidth(c);
|
|
208
417
|
const remainingWidth = c.width - axisYwidth;
|
|
209
|
-
// Legend across bottom
|
|
210
418
|
const clLegend = this.computeLegend(c, remainingWidth, padding);
|
|
211
419
|
const plotHeight = c.height - clLegend.bounds.height - padding;
|
|
212
420
|
const cy = { width: axisYwidth, height: plotHeight };
|
|
213
|
-
const
|
|
214
|
-
const cl = { ...clLegend.bounds, x: cy.width, y:
|
|
215
|
-
let globalScaler;
|
|
216
|
-
if (!Number.isNaN(this.fixedMax) && !Number.isNaN(this.fixedMin)) {
|
|
217
|
-
globalScaler = Numbers.scaler(this.fixedMin, this.fixedMax);
|
|
218
|
-
}
|
|
421
|
+
const plotDataArea = this.calculatePlotDataArea(c, plotHeight, cy.width, padding);
|
|
422
|
+
const cl = { ...clLegend.bounds, x: cy.width, y: plotDataArea.y + plotDataArea.height + padding };
|
|
219
423
|
// Draw legend
|
|
220
424
|
if (!this.hideLegend) {
|
|
221
425
|
ctx.save();
|
|
@@ -224,28 +428,38 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
224
428
|
ctx.restore();
|
|
225
429
|
}
|
|
226
430
|
ctx.save();
|
|
227
|
-
ctx.translate(
|
|
228
|
-
|
|
229
|
-
|
|
431
|
+
ctx.translate(plotDataArea.x + padding, plotDataArea.y + padding);
|
|
432
|
+
if (this.plotAreaFormat.fill.type === `solid`) {
|
|
433
|
+
ctx.fillStyle = Colour.resolveCss(this.plotAreaFormat.fill.colour);
|
|
434
|
+
ctx.fillRect(0, 0, plotDataArea.width, plotDataArea.height);
|
|
435
|
+
}
|
|
436
|
+
if (this.plotAreaFormat.outline.type === `solid`) {
|
|
437
|
+
ctx.strokeStyle = Colour.resolveCss(this.plotAreaFormat.outline.colour);
|
|
438
|
+
ctx.strokeRect(0, 0, plotDataArea.width, plotDataArea.height);
|
|
439
|
+
}
|
|
440
|
+
// Compute axis scaling
|
|
441
|
+
const primaryAxisS = this.primaryAxis.getValueScaler(this.#series.values().filter(s => s.onPrimaryAxis));
|
|
442
|
+
const secondaryAxisAxisS = this.secondaryAxis.getValueScaler(this.#series.values().filter(s => !s.onPrimaryAxis));
|
|
230
443
|
// Draw data
|
|
444
|
+
this.#hitboxes = [];
|
|
231
445
|
for (const series of this.#series.values()) {
|
|
232
|
-
const seriesScale = this.seriesRanges.get(series.name);
|
|
233
|
-
const data = seriesScale === undefined ? (globalScaler === undefined ?
|
|
234
|
-
series.getScaled() :
|
|
235
|
-
series.getScaledBy(globalScaler)) :
|
|
236
|
-
series.getScaledBy(Numbers.scaler(seriesScale[0], seriesScale[1]));
|
|
237
|
-
const colour = Colour.toCssColour(series.colour);
|
|
238
446
|
switch (this.renderStyle) {
|
|
239
447
|
case `line`: {
|
|
240
|
-
this
|
|
448
|
+
this.#drawLineSeries(series, d, series.onPrimaryAxis ? primaryAxisS : secondaryAxisAxisS, plotDataArea, { x: padding, y: padding });
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
case `bar`: {
|
|
452
|
+
this.#drawBarSeries(series, d, series.onPrimaryAxis ? primaryAxisS : secondaryAxisAxisS, plotDataArea, { x: padding, y: padding });
|
|
241
453
|
break;
|
|
242
454
|
}
|
|
243
455
|
default: {
|
|
244
|
-
this
|
|
456
|
+
this.#drawDotSeries(series, d, series.onPrimaryAxis ? primaryAxisS : secondaryAxisAxisS, plotDataArea, { x: padding, y: padding });
|
|
245
457
|
}
|
|
246
458
|
}
|
|
459
|
+
series.isDirty = false;
|
|
247
460
|
}
|
|
248
461
|
ctx.restore();
|
|
462
|
+
this.#updateToolTip();
|
|
249
463
|
}
|
|
250
464
|
drawLegend(cl, d) {
|
|
251
465
|
const textColour = this.#legendColour;
|
|
@@ -255,7 +469,9 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
255
469
|
const swatchSize = 10;
|
|
256
470
|
const ctx = d.ctx;
|
|
257
471
|
for (const series of this.#series.values()) {
|
|
258
|
-
|
|
472
|
+
const f = series.getFormatting();
|
|
473
|
+
const colour = (f.fill.type === `solid`) ? f.fill.colour : `transparent`;
|
|
474
|
+
ctx.fillStyle = Colour.toCssColour(colour);
|
|
259
475
|
ctx.fillRect(x, y, swatchSize, swatchSize);
|
|
260
476
|
ctx.fillStyle = textColour;
|
|
261
477
|
x += swatchSize + padding;
|
|
@@ -269,63 +485,195 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
269
485
|
}
|
|
270
486
|
}
|
|
271
487
|
}
|
|
272
|
-
|
|
273
|
-
|
|
488
|
+
// #drawBarSeries(data: number[], cp: Rect, d: DrawingHelper, series: PlotSeries) {
|
|
489
|
+
// const barWidth = this.streaming ? this.dataWidth : (cp.width / data.length);
|
|
490
|
+
// const formatting = series.getFormatting();
|
|
491
|
+
// let x = 0;
|
|
492
|
+
// if (this.streaming) x = cp.width - (barWidth * data.length);
|
|
493
|
+
// const rects = data.map(d => {
|
|
494
|
+
// x += barWidth;
|
|
495
|
+
// const h = (d) * cp.height;
|
|
496
|
+
// return {
|
|
497
|
+
// x: x,
|
|
498
|
+
// y: cp.height - h,
|
|
499
|
+
// height: h,
|
|
500
|
+
// width: barWidth,
|
|
501
|
+
// value: d
|
|
502
|
+
// };
|
|
503
|
+
// })
|
|
504
|
+
// this.#hitboxes = rects.map(r => {
|
|
505
|
+
// return {
|
|
506
|
+
// ...r,
|
|
507
|
+
// series: series.name
|
|
508
|
+
// }
|
|
509
|
+
// })
|
|
510
|
+
// let drawOptions: { stroke: boolean, filled: boolean, strokeWidth?: number, strokeStyle?: string, fillStyle?: string } = {
|
|
511
|
+
// stroke: false,
|
|
512
|
+
// filled: false
|
|
513
|
+
// }
|
|
514
|
+
// if (formatting.outline.type === `solid`) {
|
|
515
|
+
// drawOptions.stroke = true;
|
|
516
|
+
// drawOptions.strokeStyle = formatting.outline.colour;
|
|
517
|
+
// drawOptions.strokeWidth = 1;
|
|
518
|
+
// }
|
|
519
|
+
// if (formatting.fill.type === `solid`) {
|
|
520
|
+
// drawOptions.filled = true;
|
|
521
|
+
// drawOptions.fillStyle = formatting.fill.colour;
|
|
522
|
+
// }
|
|
523
|
+
// d.rect(rects, drawOptions);
|
|
524
|
+
// }
|
|
525
|
+
#drawLineSeries(series, d, scaler, plotDataArea, plotDataAreaOffset) {
|
|
526
|
+
const formatting = series.getFormatting();
|
|
527
|
+
const lineFormatting = formatting.line;
|
|
528
|
+
const widthPerValue = plotDataArea.width / series.length;
|
|
529
|
+
const xOffset = widthPerValue / 2;
|
|
530
|
+
const lineThickness = lineFormatting.width;
|
|
531
|
+
const lineThicknessHalf = lineThickness / 2;
|
|
532
|
+
const h = plotDataArea.height;
|
|
274
533
|
let x = 0;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
534
|
+
const dotsToDraw = [...series.getValuesForColumn(0)].map(d => {
|
|
535
|
+
const [value, index] = d;
|
|
536
|
+
x += widthPerValue;
|
|
537
|
+
const scaledValue = scaler(value);
|
|
538
|
+
if (Number.isNaN(value))
|
|
539
|
+
return undefined;
|
|
279
540
|
return {
|
|
280
|
-
x: x,
|
|
281
|
-
y: (1 -
|
|
282
|
-
|
|
541
|
+
x: x - xOffset,
|
|
542
|
+
y: (1 - scaledValue) * h,
|
|
543
|
+
value, index
|
|
283
544
|
};
|
|
284
545
|
});
|
|
285
|
-
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
546
|
+
const filtered = dotsToDraw.filter(f => f !== undefined);
|
|
547
|
+
const hitboxes = filtered.map(d => ({
|
|
548
|
+
height: lineThickness,
|
|
549
|
+
width: widthPerValue,
|
|
550
|
+
x: plotDataAreaOffset.x + d.x - lineThicknessHalf,
|
|
551
|
+
y: plotDataAreaOffset.y + d.y - lineThicknessHalf,
|
|
552
|
+
series,
|
|
553
|
+
index: d.index,
|
|
554
|
+
value: series.getValue(d.index),
|
|
555
|
+
}));
|
|
556
|
+
this.#hitboxes.push(...hitboxes);
|
|
557
|
+
const drawOpts = {
|
|
558
|
+
filled: false,
|
|
559
|
+
fillStyle: `transparent`,
|
|
560
|
+
stroked: true,
|
|
561
|
+
strokeStyle: `black`,
|
|
562
|
+
strokeWidth: lineFormatting.width
|
|
563
|
+
};
|
|
564
|
+
if (formatting.outline.type === `solid`) {
|
|
565
|
+
drawOpts.strokeStyle = formatting.outline.colour;
|
|
566
|
+
}
|
|
567
|
+
else if (formatting.fill.type === `solid`) {
|
|
568
|
+
drawOpts.strokeStyle = formatting.fill.colour;
|
|
569
|
+
}
|
|
570
|
+
d.ctx.lineWidth = lineFormatting.width;
|
|
571
|
+
d.ctx.lineCap = lineFormatting.cap;
|
|
572
|
+
d.ctx.lineJoin = lineFormatting.join;
|
|
573
|
+
d.connectedPoints(filtered, drawOpts);
|
|
574
|
+
//d.textBlock([ `hello` ], { fillStyle: `black`, anchor: { x: 1, y: 1 } })
|
|
575
|
+
}
|
|
576
|
+
#drawDotSeries(series, d, scaler, plotDataArea, plotDataAreaOffset) {
|
|
577
|
+
const formatting = series.getFormatting();
|
|
578
|
+
const dotFormatting = formatting.dot;
|
|
579
|
+
const widthPerValue = plotDataArea.width / series.length;
|
|
580
|
+
const radius = dotFormatting.radius === `automatic` ? widthPerValue * 0.3 : dotFormatting.radius;
|
|
581
|
+
const xOffset = widthPerValue / 2;
|
|
582
|
+
const h = plotDataArea.height;
|
|
298
583
|
let x = 0;
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
584
|
+
const dotsToDraw = [...series.getValuesForColumn(0)].map(d => {
|
|
585
|
+
const [value, index] = d;
|
|
586
|
+
x += widthPerValue;
|
|
587
|
+
const scaledValue = scaler(value);
|
|
588
|
+
if (Number.isNaN(value))
|
|
589
|
+
return undefined;
|
|
303
590
|
return {
|
|
304
|
-
x,
|
|
305
|
-
y: (1 -
|
|
306
|
-
radius:
|
|
591
|
+
x: x - xOffset,
|
|
592
|
+
y: (1 - scaledValue) * h,
|
|
593
|
+
radius: radius,
|
|
594
|
+
value, index
|
|
307
595
|
};
|
|
308
596
|
});
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
597
|
+
const filtered = dotsToDraw.filter(f => f !== undefined);
|
|
598
|
+
const hitboxes = filtered.map(d => ({
|
|
599
|
+
height: d.radius * 2,
|
|
600
|
+
width: d.radius * 2,
|
|
601
|
+
x: plotDataAreaOffset.x + d.x - d.radius,
|
|
602
|
+
y: plotDataAreaOffset.y + d.y - d.radius,
|
|
603
|
+
series,
|
|
604
|
+
index: d.index,
|
|
605
|
+
value: series.getValue(d.index),
|
|
606
|
+
}));
|
|
607
|
+
this.#hitboxes.push(...hitboxes);
|
|
608
|
+
const drawOpts = { filled: false, fillStyle: `transparent`, stroked: false, strokeStyle: `transparent` };
|
|
609
|
+
if (formatting.fill.type === `solid`) {
|
|
610
|
+
drawOpts.filled = true;
|
|
611
|
+
drawOpts.fillStyle = formatting.fill.colour;
|
|
612
|
+
}
|
|
613
|
+
if (formatting.outline.type === `solid`) {
|
|
614
|
+
drawOpts.stroked = true;
|
|
615
|
+
drawOpts.strokeStyle = formatting.outline.colour;
|
|
616
|
+
}
|
|
617
|
+
d.dot(filtered, drawOpts);
|
|
618
|
+
//d.textBlock([ `hello` ], { fillStyle: `black`, anchor: { x: 1, y: 1 } })
|
|
619
|
+
}
|
|
620
|
+
#drawBarSeries(series, d, scaler, plotDataArea, plotDataAreaOffset) {
|
|
621
|
+
const formatting = series.getFormatting();
|
|
622
|
+
const barFormatting = formatting.bar;
|
|
623
|
+
const widthPerValue = plotDataArea.width / series.length;
|
|
624
|
+
const rectWidth = widthPerValue - (barFormatting.gapWidth / 2);
|
|
625
|
+
const xOffset = widthPerValue / 2;
|
|
626
|
+
const h = plotDataArea.height;
|
|
627
|
+
let x = 0;
|
|
628
|
+
const rectsToDraw = [...series.getValuesForColumn(0)].map(d => {
|
|
629
|
+
const [value, index] = d;
|
|
630
|
+
x += widthPerValue;
|
|
631
|
+
const scaledValue = scaler(value);
|
|
632
|
+
if (Number.isNaN(value))
|
|
633
|
+
return undefined;
|
|
634
|
+
const barHeight = scaledValue * h;
|
|
635
|
+
return {
|
|
636
|
+
x: x - xOffset,
|
|
637
|
+
y: h - barHeight,
|
|
638
|
+
width: rectWidth,
|
|
639
|
+
height: barHeight,
|
|
640
|
+
value, index
|
|
641
|
+
};
|
|
314
642
|
});
|
|
315
|
-
|
|
643
|
+
const filtered = rectsToDraw.filter(f => f !== undefined);
|
|
644
|
+
const hitboxes = filtered.map(d => ({
|
|
645
|
+
height: Math.max(5, d.height),
|
|
646
|
+
width: d.width,
|
|
647
|
+
x: plotDataAreaOffset.x + d.x,
|
|
648
|
+
y: plotDataAreaOffset.y + d.y,
|
|
649
|
+
series,
|
|
650
|
+
index: d.index,
|
|
651
|
+
value: series.getValue(d.index),
|
|
652
|
+
}));
|
|
653
|
+
this.#hitboxes.push(...hitboxes);
|
|
654
|
+
const drawOpts = { filled: false, fillStyle: `transparent`, stroked: false, strokeStyle: `transparent` };
|
|
655
|
+
if (formatting.fill.type === `solid`) {
|
|
656
|
+
drawOpts.filled = true;
|
|
657
|
+
drawOpts.fillStyle = formatting.fill.colour;
|
|
658
|
+
}
|
|
659
|
+
if (formatting.outline.type === `solid`) {
|
|
660
|
+
drawOpts.stroked = true;
|
|
661
|
+
drawOpts.strokeStyle = formatting.outline.colour;
|
|
662
|
+
}
|
|
663
|
+
d.rect(filtered, drawOpts);
|
|
664
|
+
//d.textBlock([ `hello` ], { fillStyle: `black`, anchor: { x: 1, y: 1 } })
|
|
316
665
|
}
|
|
317
|
-
|
|
666
|
+
calculatePlotDataArea(c, plotHeight, axisYwidth, padding) {
|
|
318
667
|
return {
|
|
319
668
|
x: axisYwidth,
|
|
320
669
|
y: 0,
|
|
321
|
-
width: c.width - axisYwidth - padding,
|
|
322
|
-
height: plotHeight - padding
|
|
670
|
+
width: c.width - axisYwidth - padding - padding,
|
|
671
|
+
height: plotHeight - padding
|
|
323
672
|
};
|
|
324
673
|
}
|
|
325
674
|
computeAxisYWidth(_c) {
|
|
326
675
|
return 0;
|
|
327
676
|
}
|
|
328
|
-
#swatchSize;
|
|
329
677
|
computeLegend(c, maxWidth, padding) {
|
|
330
678
|
if (this.hideLegend) {
|
|
331
679
|
return {
|
|
@@ -367,109 +715,207 @@ let PlotElement = class PlotElement extends LitElement {
|
|
|
367
715
|
bounds, parts
|
|
368
716
|
};
|
|
369
717
|
}
|
|
718
|
+
getOrCreateSeries(name) {
|
|
719
|
+
let s = this.#series.get(name.toLowerCase());
|
|
720
|
+
if (s)
|
|
721
|
+
return s;
|
|
722
|
+
s = new PlotSeries(name, this);
|
|
723
|
+
const seriesDefault = {
|
|
724
|
+
limit: Number.NaN,
|
|
725
|
+
...this.seriesDefault
|
|
726
|
+
};
|
|
727
|
+
if (!Number.isNaN(seriesDefault.limit)) {
|
|
728
|
+
s.setCapacityLimit(seriesDefault.limit);
|
|
729
|
+
}
|
|
730
|
+
this.#series.set(name.toLowerCase(), s);
|
|
731
|
+
return s;
|
|
732
|
+
}
|
|
370
733
|
getSeries(name) {
|
|
371
734
|
return this.#series.get(name);
|
|
372
735
|
}
|
|
736
|
+
render() {
|
|
737
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
738
|
+
return html `<canvas @pointerleave="${this.#onPointerLeave}" @pointermove="${this.#onPointerMove}" ${ref(this.canvasEl)}></canvas><div class="hidden" ${ref(this.tooltipEl)} id="tooltip">Tooltip!</div>`;
|
|
739
|
+
}
|
|
373
740
|
static { this.styles = css `
|
|
374
741
|
:host {
|
|
375
742
|
width: 100%;
|
|
376
743
|
height: 100%;
|
|
377
744
|
display: block;
|
|
378
745
|
}
|
|
746
|
+
|
|
747
|
+
#tooltip {
|
|
748
|
+
border: 1px solid black;
|
|
749
|
+
background: white;
|
|
750
|
+
color: black;
|
|
751
|
+
padding: 0.3em;
|
|
752
|
+
font-size: 10px;
|
|
753
|
+
display: inline-block;
|
|
754
|
+
position: absolute;
|
|
755
|
+
left: 0px;
|
|
756
|
+
top: 0px;
|
|
757
|
+
opacity:1;
|
|
758
|
+
pointer-events: none;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
.hidden {
|
|
762
|
+
opacity:0 !important;
|
|
763
|
+
}
|
|
379
764
|
`; }
|
|
380
765
|
};
|
|
381
|
-
__decorate([
|
|
382
|
-
property({ attribute: `streaming`, type: Boolean })
|
|
383
|
-
], PlotElement.prototype, "streaming", void 0);
|
|
384
766
|
__decorate([
|
|
385
767
|
property({ attribute: `hide-legend`, type: Boolean })
|
|
386
768
|
], PlotElement.prototype, "hideLegend", void 0);
|
|
387
|
-
__decorate([
|
|
388
|
-
property({ attribute: `max-length`, type: Number })
|
|
389
|
-
], PlotElement.prototype, "maxLength", void 0);
|
|
390
|
-
__decorate([
|
|
391
|
-
property({ attribute: `data-width`, type: Number })
|
|
392
|
-
], PlotElement.prototype, "dataWidth", void 0);
|
|
393
|
-
__decorate([
|
|
394
|
-
property({ attribute: `fixed-max`, type: Number })
|
|
395
|
-
], PlotElement.prototype, "fixedMax", void 0);
|
|
396
|
-
__decorate([
|
|
397
|
-
property({ attribute: `fixed-min`, type: Number })
|
|
398
|
-
], PlotElement.prototype, "fixedMin", void 0);
|
|
399
|
-
__decorate([
|
|
400
|
-
property({ attribute: `line-width`, type: Number })
|
|
401
|
-
], PlotElement.prototype, "lineWidth", void 0);
|
|
402
769
|
__decorate([
|
|
403
770
|
property({ attribute: `render`, type: String })
|
|
404
771
|
], PlotElement.prototype, "renderStyle", void 0);
|
|
405
772
|
__decorate([
|
|
406
|
-
property({ attribute: `
|
|
407
|
-
], PlotElement.prototype, "
|
|
773
|
+
property({ attribute: `padding`, type: Number })
|
|
774
|
+
], PlotElement.prototype, "padding", void 0);
|
|
408
775
|
PlotElement = __decorate([
|
|
409
776
|
customElement(`ixfx-plot-element`)
|
|
410
777
|
], PlotElement);
|
|
411
778
|
export { PlotElement };
|
|
779
|
+
const resolveFillDrawStyle = (s) => {
|
|
780
|
+
if (s.type === `none`)
|
|
781
|
+
return s;
|
|
782
|
+
const c = Colour.resolveCss(s.colour);
|
|
783
|
+
return {
|
|
784
|
+
type: `solid`,
|
|
785
|
+
colour: c
|
|
786
|
+
};
|
|
787
|
+
};
|
|
788
|
+
const resolveOutlineDrawStyle = (s) => {
|
|
789
|
+
if (s.type === `none`)
|
|
790
|
+
return s;
|
|
791
|
+
const c = Colour.resolveCss(s.colour);
|
|
792
|
+
return {
|
|
793
|
+
...s,
|
|
794
|
+
colour: c
|
|
795
|
+
};
|
|
796
|
+
};
|
|
797
|
+
//export type Range = { min: number, max: number }
|
|
798
|
+
// const initRange = (): Range => ({ min: Number.MAX_SAFE_INTEGER, max: Number.MIN_SAFE_INTEGER });
|
|
799
|
+
// function computeRangeWithNewValue(v: number | undefined, prev: Range): Range {
|
|
800
|
+
// if (typeof v === `number`) {
|
|
801
|
+
// // Skip creating an object if it's in range
|
|
802
|
+
// if (v >= prev.min && v <= prev.max) return prev;
|
|
803
|
+
// return {
|
|
804
|
+
// min: Math.min(v, prev.min),
|
|
805
|
+
// max: Math.max(v, prev.max),
|
|
806
|
+
// }
|
|
807
|
+
// }
|
|
808
|
+
// return prev;
|
|
809
|
+
// }
|
|
810
|
+
// function computeMergedRange(newRange: Range, existingRange: Range): Range {
|
|
811
|
+
// if (newRange.max <= existingRange.max && newRange.min >= existingRange.min) return existingRange;
|
|
812
|
+
// return {
|
|
813
|
+
// min: Math.min(newRange.min, existingRange.min),
|
|
814
|
+
// max: Math.max(newRange.max, existingRange.max)
|
|
815
|
+
// }
|
|
816
|
+
// }
|
|
412
817
|
export class PlotSeries {
|
|
413
|
-
|
|
818
|
+
#data = [];
|
|
819
|
+
#capacityLimit = Number.NaN;
|
|
820
|
+
#dirty = false;
|
|
821
|
+
#onPrimaryAxis = true;
|
|
822
|
+
constructor(name, plot) {
|
|
414
823
|
this.name = name;
|
|
415
|
-
this.colour = colour;
|
|
416
824
|
this.plot = plot;
|
|
417
|
-
this.data = [];
|
|
418
|
-
this.minSeen = Number.MAX_SAFE_INTEGER;
|
|
419
|
-
this.maxSeen = Number.MIN_SAFE_INTEGER;
|
|
420
825
|
}
|
|
421
|
-
|
|
422
|
-
this.
|
|
423
|
-
this.resetScale();
|
|
826
|
+
get length() {
|
|
827
|
+
return this.#data.length;
|
|
424
828
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
if (Number.isNaN(max))
|
|
437
|
-
max = 1;
|
|
438
|
-
const s = Numbers.scaler(min, max);
|
|
439
|
-
return this.getScaledBy(s);
|
|
440
|
-
}
|
|
441
|
-
getScaledBy(scaler) {
|
|
442
|
-
return this.data.map(v => {
|
|
443
|
-
if (typeof v !== `number`)
|
|
444
|
-
throw new Error(`Data should just be numbers. Got: ${typeof v}`);
|
|
445
|
-
if (Number.isNaN(v))
|
|
446
|
-
throw new Error(`data contains NaN`);
|
|
447
|
-
const scaled = scaler(v);
|
|
448
|
-
if (Number.isNaN(scaled))
|
|
449
|
-
throw new Error(`NaN. v: ${v} scaled: ${scaled}`);
|
|
450
|
-
return Numbers.clamp(scaled);
|
|
451
|
-
});
|
|
829
|
+
*getValuesForColumn(column) {
|
|
830
|
+
let index = 0;
|
|
831
|
+
for (const dv of this.#data) {
|
|
832
|
+
if (dv && column in dv) {
|
|
833
|
+
yield [dv[column], index];
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
yield [Number.NaN, index];
|
|
837
|
+
}
|
|
838
|
+
index++;
|
|
839
|
+
}
|
|
452
840
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
if (
|
|
458
|
-
|
|
841
|
+
getValue(index) {
|
|
842
|
+
return this.#data[index];
|
|
843
|
+
}
|
|
844
|
+
pushValue(value, automaticallyDraw) {
|
|
845
|
+
if (!Array.isArray(value)) {
|
|
846
|
+
value = [value];
|
|
847
|
+
}
|
|
848
|
+
if (value.length === 0)
|
|
849
|
+
throw new Error(`Param 'value' is empty. Expected a value or array of value components`);
|
|
850
|
+
this.#data.push(value);
|
|
851
|
+
if (!Number.isNaN(this.#capacityLimit)) {
|
|
852
|
+
this.#data = Arrays.ensureLength(this.#data, this.#capacityLimit, `undefined`, `from-start`);
|
|
459
853
|
}
|
|
460
|
-
this
|
|
461
|
-
|
|
854
|
+
this.#dirty = true;
|
|
855
|
+
if (automaticallyDraw)
|
|
856
|
+
this.plot.draw();
|
|
462
857
|
}
|
|
463
|
-
setValues(values) {
|
|
858
|
+
setValues(values, automaticallyDraw) {
|
|
464
859
|
if (!Array.isArray(values))
|
|
465
860
|
throw new TypeError(`Param 'values' is not an array`);
|
|
466
|
-
this
|
|
467
|
-
this
|
|
468
|
-
this
|
|
861
|
+
this.#data = Arrays.ensureLength(values, this.#capacityLimit, `undefined`);
|
|
862
|
+
//this.#updateRanges();
|
|
863
|
+
this.#dirty = true;
|
|
864
|
+
if (automaticallyDraw)
|
|
865
|
+
this.plot.draw();
|
|
866
|
+
}
|
|
867
|
+
humanFormatValue(value) {
|
|
868
|
+
let v = `${this.name} `;
|
|
869
|
+
if (this.onPrimaryAxis) {
|
|
870
|
+
v += this.plot.primaryAxis.humanFormatValue(value);
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
v += this.plot.secondaryAxis.humanFormatValue(value);
|
|
874
|
+
}
|
|
875
|
+
return v;
|
|
876
|
+
}
|
|
877
|
+
setRawValues(values, automaticallyDraw) {
|
|
878
|
+
this.setValues(values.map(v => [v]), automaticallyDraw);
|
|
879
|
+
}
|
|
880
|
+
setCapacityLimit(v) {
|
|
881
|
+
if (typeof v !== `number`)
|
|
882
|
+
throw new TypeError(`Expect type number. Got: ${typeof v}`);
|
|
883
|
+
if (!Number.isFinite(v)) {
|
|
884
|
+
throw new TypeError(`Param 'v' is not finite`);
|
|
885
|
+
}
|
|
886
|
+
if (Number.isNaN(v)) {
|
|
887
|
+
throw new TypeError(`Param 'v' is NaN`);
|
|
888
|
+
}
|
|
889
|
+
this.#capacityLimit = v;
|
|
890
|
+
this.#data = Arrays.ensureLength(this.#data, this.#capacityLimit, `undefined`);
|
|
891
|
+
}
|
|
892
|
+
unsetCapacityLimit() {
|
|
893
|
+
this.#capacityLimit = Number.NaN;
|
|
894
|
+
}
|
|
895
|
+
setFormatting(formatting) {
|
|
896
|
+
this.plot.setSeriesFormatting(this.name, formatting);
|
|
469
897
|
}
|
|
470
|
-
|
|
471
|
-
this.
|
|
472
|
-
|
|
898
|
+
getFormatting() {
|
|
899
|
+
return this.plot.getSeriesFormatting(this.name, true);
|
|
900
|
+
}
|
|
901
|
+
get isDirty() {
|
|
902
|
+
return this.#dirty;
|
|
903
|
+
}
|
|
904
|
+
set isDirty(value) {
|
|
905
|
+
this.#dirty = value;
|
|
906
|
+
}
|
|
907
|
+
get onPrimaryAxis() {
|
|
908
|
+
return this.#onPrimaryAxis;
|
|
909
|
+
}
|
|
910
|
+
set onPrimaryAxis(value) {
|
|
911
|
+
if (value === this.#onPrimaryAxis)
|
|
912
|
+
return;
|
|
913
|
+
this.#onPrimaryAxis = value;
|
|
914
|
+
this.#dirty = true;
|
|
915
|
+
}
|
|
916
|
+
clear() {
|
|
917
|
+
this.#data = [];
|
|
918
|
+
this.#dirty = true;
|
|
473
919
|
}
|
|
474
920
|
}
|
|
475
921
|
//# sourceMappingURL=plot.js.map
|