@camstack/ui-library 1.2.304 → 1.2.306
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/{MotionZonesSettings-C3Tj12yc.js → MotionZonesSettings-DR1g9ja3.js} +1 -1
- package/dist/{PrivacyMaskSettings-C9wfHkiB.js → PrivacyMaskSettings-CtetT6Jl.js} +1 -1
- package/dist/{SceneMonitorEditor-30H29vN4.js → SceneMonitorEditor-BQhVO2F2.js} +1 -1
- package/dist/composites/cap-settings/EventHeatmap.d.ts +8 -2
- package/dist/composites/charts/BarSeries.d.ts +49 -0
- package/dist/composites/charts/Sparkline.d.ts +26 -0
- package/dist/composites/charts/StateTimeline.d.ts +47 -0
- package/dist/composites/charts/TimeSeriesChart.d.ts +48 -0
- package/dist/composites/charts/bar-series-model.d.ts +25 -0
- package/dist/composites/charts/chart-data.d.ts +87 -0
- package/dist/composites/charts/chart-frame.d.ts +53 -0
- package/dist/composites/charts/chart-palette.d.ts +46 -0
- package/dist/composites/charts/chart-scale.d.ts +29 -0
- package/dist/composites/charts/chart-uplot.d.ts +44 -0
- package/dist/composites/charts/chart-window.d.ts +19 -0
- package/dist/composites/charts/index.d.ts +16 -0
- package/dist/composites/charts/time-series-model.d.ts +47 -0
- package/dist/composites/charts/uplot-host.d.ts +34 -0
- package/dist/composites/device-history/DeviceHistoryView.d.ts +26 -0
- package/dist/composites/device-history/HistoryChart.d.ts +31 -0
- package/dist/composites/device-history/HistoryWindowBar.d.ts +16 -0
- package/dist/composites/device-history/history-model.d.ts +121 -0
- package/dist/composites/device-history/history-reads.d.ts +43 -0
- package/dist/composites/device-history/history-selection.d.ts +55 -0
- package/dist/composites/device-history/history-window.d.ts +31 -0
- package/dist/composites/device-history/index.d.ts +14 -0
- package/dist/composites/device-history/use-device-history.d.ts +37 -0
- package/dist/composites/device-history/use-history-panels.d.ts +10 -0
- package/dist/composites/index.d.ts +2 -0
- package/dist/composites/log-history-paging.d.ts +62 -0
- package/dist/composites/log-stream.d.ts +6 -10
- package/dist/generated/system-hooks.d.ts +2 -0
- package/dist/hooks/use-log-history.d.ts +26 -0
- package/dist/{icons-B1AFXUaZ.cjs → icons-BTux33dH.cjs} +2 -35
- package/dist/{icons-BT8c2hxp.js → icons-D178phML.js} +1 -34
- package/dist/index.cjs +3509 -122
- package/dist/index.js +3430 -129
- package/dist/uPlot.esm-BbxBUnav.cjs +3767 -0
- package/dist/uPlot.esm-C_8LiAPm.js +3767 -0
- package/package.json +2 -1
- package/src/tailwind/camstack-theme.css +104 -2
|
@@ -0,0 +1,3767 @@
|
|
|
1
|
+
//#region ../../node_modules/uplot/dist/uPlot.esm.js
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025, Leon Sorokin
|
|
4
|
+
* All rights reserved. (MIT Licensed)
|
|
5
|
+
*
|
|
6
|
+
* uPlot.js (μPlot)
|
|
7
|
+
* A small, fast chart for time series, lines, areas, ohlc & bars
|
|
8
|
+
* https://github.com/leeoniya/uPlot (v1.6.32)
|
|
9
|
+
*/
|
|
10
|
+
var FEAT_TIME = true;
|
|
11
|
+
var UPLOT = "uplot";
|
|
12
|
+
var ORI_HZ = "u-hz";
|
|
13
|
+
var ORI_VT = "u-vt";
|
|
14
|
+
var TITLE = "u-title";
|
|
15
|
+
var WRAP = "u-wrap";
|
|
16
|
+
var UNDER = "u-under";
|
|
17
|
+
var OVER = "u-over";
|
|
18
|
+
var AXIS = "u-axis";
|
|
19
|
+
var OFF = "u-off";
|
|
20
|
+
var SELECT = "u-select";
|
|
21
|
+
var CURSOR_X = "u-cursor-x";
|
|
22
|
+
var CURSOR_Y = "u-cursor-y";
|
|
23
|
+
var CURSOR_PT = "u-cursor-pt";
|
|
24
|
+
var LEGEND = "u-legend";
|
|
25
|
+
var LEGEND_LIVE = "u-live";
|
|
26
|
+
var LEGEND_INLINE = "u-inline";
|
|
27
|
+
var LEGEND_SERIES = "u-series";
|
|
28
|
+
var LEGEND_MARKER = "u-marker";
|
|
29
|
+
var LEGEND_LABEL = "u-label";
|
|
30
|
+
var LEGEND_VALUE = "u-value";
|
|
31
|
+
var WIDTH = "width";
|
|
32
|
+
var HEIGHT = "height";
|
|
33
|
+
var TOP = "top";
|
|
34
|
+
var BOTTOM = "bottom";
|
|
35
|
+
var LEFT = "left";
|
|
36
|
+
var RIGHT = "right";
|
|
37
|
+
var hexBlack = "#000";
|
|
38
|
+
var transparent = "#0000";
|
|
39
|
+
var mousemove = "mousemove";
|
|
40
|
+
var mousedown = "mousedown";
|
|
41
|
+
var mouseup = "mouseup";
|
|
42
|
+
var mouseenter = "mouseenter";
|
|
43
|
+
var mouseleave = "mouseleave";
|
|
44
|
+
var dblclick = "dblclick";
|
|
45
|
+
var resize = "resize";
|
|
46
|
+
var scroll = "scroll";
|
|
47
|
+
var change = "change";
|
|
48
|
+
var dppxchange = "dppxchange";
|
|
49
|
+
var LEGEND_DISP = "--";
|
|
50
|
+
var domEnv = typeof window != "undefined";
|
|
51
|
+
var doc = domEnv ? document : null;
|
|
52
|
+
var win = domEnv ? window : null;
|
|
53
|
+
var nav = domEnv ? navigator : null;
|
|
54
|
+
var pxRatio;
|
|
55
|
+
var query;
|
|
56
|
+
function setPxRatio() {
|
|
57
|
+
let _pxRatio = devicePixelRatio;
|
|
58
|
+
if (pxRatio != _pxRatio) {
|
|
59
|
+
pxRatio = _pxRatio;
|
|
60
|
+
query && off(change, query, setPxRatio);
|
|
61
|
+
query = matchMedia(`(min-resolution: ${pxRatio - .001}dppx) and (max-resolution: ${pxRatio + .001}dppx)`);
|
|
62
|
+
on(change, query, setPxRatio);
|
|
63
|
+
win.dispatchEvent(new CustomEvent(dppxchange));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function addClass(el, c) {
|
|
67
|
+
if (c != null) {
|
|
68
|
+
let cl = el.classList;
|
|
69
|
+
!cl.contains(c) && cl.add(c);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function remClass(el, c) {
|
|
73
|
+
let cl = el.classList;
|
|
74
|
+
cl.contains(c) && cl.remove(c);
|
|
75
|
+
}
|
|
76
|
+
function setStylePx(el, name, value) {
|
|
77
|
+
el.style[name] = value + "px";
|
|
78
|
+
}
|
|
79
|
+
function placeTag(tag, cls, targ, refEl) {
|
|
80
|
+
let el = doc.createElement(tag);
|
|
81
|
+
if (cls != null) addClass(el, cls);
|
|
82
|
+
if (targ != null) targ.insertBefore(el, refEl);
|
|
83
|
+
return el;
|
|
84
|
+
}
|
|
85
|
+
function placeDiv(cls, targ) {
|
|
86
|
+
return placeTag("div", cls, targ);
|
|
87
|
+
}
|
|
88
|
+
var xformCache = /* @__PURE__ */ new WeakMap();
|
|
89
|
+
function elTrans(el, xPos, yPos, xMax, yMax) {
|
|
90
|
+
let xform = "translate(" + xPos + "px," + yPos + "px)";
|
|
91
|
+
if (xform != xformCache.get(el)) {
|
|
92
|
+
el.style.transform = xform;
|
|
93
|
+
xformCache.set(el, xform);
|
|
94
|
+
if (xPos < 0 || yPos < 0 || xPos > xMax || yPos > yMax) addClass(el, OFF);
|
|
95
|
+
else remClass(el, OFF);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
var colorCache = /* @__PURE__ */ new WeakMap();
|
|
99
|
+
function elColor(el, background, borderColor) {
|
|
100
|
+
let newColor = background + borderColor;
|
|
101
|
+
if (newColor != colorCache.get(el)) {
|
|
102
|
+
colorCache.set(el, newColor);
|
|
103
|
+
el.style.background = background;
|
|
104
|
+
el.style.borderColor = borderColor;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
var sizeCache = /* @__PURE__ */ new WeakMap();
|
|
108
|
+
function elSize(el, newWid, newHgt, centered) {
|
|
109
|
+
let newSize = newWid + "" + newHgt;
|
|
110
|
+
if (newSize != sizeCache.get(el)) {
|
|
111
|
+
sizeCache.set(el, newSize);
|
|
112
|
+
el.style.height = newHgt + "px";
|
|
113
|
+
el.style.width = newWid + "px";
|
|
114
|
+
el.style.marginLeft = centered ? -newWid / 2 + "px" : 0;
|
|
115
|
+
el.style.marginTop = centered ? -newHgt / 2 + "px" : 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
var evOpts = { passive: true };
|
|
119
|
+
var evOpts2 = {
|
|
120
|
+
...evOpts,
|
|
121
|
+
capture: true
|
|
122
|
+
};
|
|
123
|
+
function on(ev, el, cb, capt) {
|
|
124
|
+
el.addEventListener(ev, cb, capt ? evOpts2 : evOpts);
|
|
125
|
+
}
|
|
126
|
+
function off(ev, el, cb, capt) {
|
|
127
|
+
el.removeEventListener(ev, cb, evOpts);
|
|
128
|
+
}
|
|
129
|
+
domEnv && setPxRatio();
|
|
130
|
+
function closestIdx(num, arr, lo, hi) {
|
|
131
|
+
let mid;
|
|
132
|
+
lo = lo || 0;
|
|
133
|
+
hi = hi || arr.length - 1;
|
|
134
|
+
let bitwise = hi <= 2147483647;
|
|
135
|
+
while (hi - lo > 1) {
|
|
136
|
+
mid = bitwise ? lo + hi >> 1 : floor((lo + hi) / 2);
|
|
137
|
+
if (arr[mid] < num) lo = mid;
|
|
138
|
+
else hi = mid;
|
|
139
|
+
}
|
|
140
|
+
if (num - arr[lo] <= arr[hi] - num) return lo;
|
|
141
|
+
return hi;
|
|
142
|
+
}
|
|
143
|
+
function makeIndexOfs(predicate) {
|
|
144
|
+
let indexOfs = (data, _i0, _i1) => {
|
|
145
|
+
let i0 = -1;
|
|
146
|
+
let i1 = -1;
|
|
147
|
+
for (let i = _i0; i <= _i1; i++) if (predicate(data[i])) {
|
|
148
|
+
i0 = i;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
for (let i = _i1; i >= _i0; i--) if (predicate(data[i])) {
|
|
152
|
+
i1 = i;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
return [i0, i1];
|
|
156
|
+
};
|
|
157
|
+
return indexOfs;
|
|
158
|
+
}
|
|
159
|
+
var notNullish = (v) => v != null;
|
|
160
|
+
var isPositive = (v) => v != null && v > 0;
|
|
161
|
+
var nonNullIdxs = makeIndexOfs(notNullish);
|
|
162
|
+
var positiveIdxs = makeIndexOfs(isPositive);
|
|
163
|
+
function getMinMax(data, _i0, _i1, sorted = 0, log = false) {
|
|
164
|
+
let getEdgeIdxs = log ? positiveIdxs : nonNullIdxs;
|
|
165
|
+
let predicate = log ? isPositive : notNullish;
|
|
166
|
+
[_i0, _i1] = getEdgeIdxs(data, _i0, _i1);
|
|
167
|
+
let _min = data[_i0];
|
|
168
|
+
let _max = data[_i0];
|
|
169
|
+
if (_i0 > -1) if (sorted == 1) {
|
|
170
|
+
_min = data[_i0];
|
|
171
|
+
_max = data[_i1];
|
|
172
|
+
} else if (sorted == -1) {
|
|
173
|
+
_min = data[_i1];
|
|
174
|
+
_max = data[_i0];
|
|
175
|
+
} else for (let i = _i0; i <= _i1; i++) {
|
|
176
|
+
let v = data[i];
|
|
177
|
+
if (predicate(v)) {
|
|
178
|
+
if (v < _min) _min = v;
|
|
179
|
+
else if (v > _max) _max = v;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return [_min ?? inf, _max ?? -inf];
|
|
183
|
+
}
|
|
184
|
+
function rangeLog(min, max, base, fullMags) {
|
|
185
|
+
let minSign = sign(min);
|
|
186
|
+
let maxSign = sign(max);
|
|
187
|
+
if (min == max) if (minSign == -1) {
|
|
188
|
+
min *= base;
|
|
189
|
+
max /= base;
|
|
190
|
+
} else {
|
|
191
|
+
min /= base;
|
|
192
|
+
max *= base;
|
|
193
|
+
}
|
|
194
|
+
let logFn = base == 10 ? log10 : log2;
|
|
195
|
+
let growMinAbs = minSign == 1 ? floor : ceil;
|
|
196
|
+
let growMaxAbs = maxSign == 1 ? ceil : floor;
|
|
197
|
+
let minExp = growMinAbs(logFn(abs(min)));
|
|
198
|
+
let maxExp = growMaxAbs(logFn(abs(max)));
|
|
199
|
+
let minIncr = pow(base, minExp);
|
|
200
|
+
let maxIncr = pow(base, maxExp);
|
|
201
|
+
if (base == 10) {
|
|
202
|
+
if (minExp < 0) minIncr = roundDec(minIncr, -minExp);
|
|
203
|
+
if (maxExp < 0) maxIncr = roundDec(maxIncr, -maxExp);
|
|
204
|
+
}
|
|
205
|
+
if (fullMags || base == 2) {
|
|
206
|
+
min = minIncr * minSign;
|
|
207
|
+
max = maxIncr * maxSign;
|
|
208
|
+
} else {
|
|
209
|
+
min = incrRoundDn(min, minIncr);
|
|
210
|
+
max = incrRoundUp(max, maxIncr);
|
|
211
|
+
}
|
|
212
|
+
return [min, max];
|
|
213
|
+
}
|
|
214
|
+
function rangeAsinh(min, max, base, fullMags) {
|
|
215
|
+
let minMax = rangeLog(min, max, base, fullMags);
|
|
216
|
+
if (min == 0) minMax[0] = 0;
|
|
217
|
+
if (max == 0) minMax[1] = 0;
|
|
218
|
+
return minMax;
|
|
219
|
+
}
|
|
220
|
+
var rangePad = .1;
|
|
221
|
+
var autoRangePart = {
|
|
222
|
+
mode: 3,
|
|
223
|
+
pad: rangePad
|
|
224
|
+
};
|
|
225
|
+
var _eqRangePart = {
|
|
226
|
+
pad: 0,
|
|
227
|
+
soft: null,
|
|
228
|
+
mode: 0
|
|
229
|
+
};
|
|
230
|
+
var _eqRange = {
|
|
231
|
+
min: _eqRangePart,
|
|
232
|
+
max: _eqRangePart
|
|
233
|
+
};
|
|
234
|
+
function rangeNum(_min, _max, mult, extra) {
|
|
235
|
+
if (isObj(mult)) return _rangeNum(_min, _max, mult);
|
|
236
|
+
_eqRangePart.pad = mult;
|
|
237
|
+
_eqRangePart.soft = extra ? 0 : null;
|
|
238
|
+
_eqRangePart.mode = extra ? 3 : 0;
|
|
239
|
+
return _rangeNum(_min, _max, _eqRange);
|
|
240
|
+
}
|
|
241
|
+
function ifNull(lh, rh) {
|
|
242
|
+
return lh == null ? rh : lh;
|
|
243
|
+
}
|
|
244
|
+
function hasData(data, idx0, idx1) {
|
|
245
|
+
idx0 = ifNull(idx0, 0);
|
|
246
|
+
idx1 = ifNull(idx1, data.length - 1);
|
|
247
|
+
while (idx0 <= idx1) {
|
|
248
|
+
if (data[idx0] != null) return true;
|
|
249
|
+
idx0++;
|
|
250
|
+
}
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
function _rangeNum(_min, _max, cfg) {
|
|
254
|
+
let cmin = cfg.min;
|
|
255
|
+
let cmax = cfg.max;
|
|
256
|
+
let padMin = ifNull(cmin.pad, 0);
|
|
257
|
+
let padMax = ifNull(cmax.pad, 0);
|
|
258
|
+
let hardMin = ifNull(cmin.hard, -inf);
|
|
259
|
+
let hardMax = ifNull(cmax.hard, inf);
|
|
260
|
+
let softMin = ifNull(cmin.soft, inf);
|
|
261
|
+
let softMax = ifNull(cmax.soft, -inf);
|
|
262
|
+
let softMinMode = ifNull(cmin.mode, 0);
|
|
263
|
+
let softMaxMode = ifNull(cmax.mode, 0);
|
|
264
|
+
let delta = _max - _min;
|
|
265
|
+
let deltaMag = log10(delta);
|
|
266
|
+
let scalarMax = max(abs(_min), abs(_max));
|
|
267
|
+
let scalarMagDelta = abs(log10(scalarMax) - deltaMag);
|
|
268
|
+
if (delta < 1e-24 || scalarMagDelta > 10) {
|
|
269
|
+
delta = 0;
|
|
270
|
+
if (_min == 0 || _max == 0) {
|
|
271
|
+
delta = 1e-24;
|
|
272
|
+
if (softMinMode == 2 && softMin != inf) padMin = 0;
|
|
273
|
+
if (softMaxMode == 2 && softMax != -inf) padMax = 0;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
let nonZeroDelta = delta || scalarMax || 1e3;
|
|
277
|
+
let base = pow(10, floor(log10(nonZeroDelta)));
|
|
278
|
+
let _newMin = roundDec(incrRoundDn(_min - nonZeroDelta * (delta == 0 ? _min == 0 ? .1 : 1 : padMin), base / 10), 24);
|
|
279
|
+
let _softMin = _min >= softMin && (softMinMode == 1 || softMinMode == 3 && _newMin <= softMin || softMinMode == 2 && _newMin >= softMin) ? softMin : inf;
|
|
280
|
+
let minLim = max(hardMin, _newMin < _softMin && _min >= _softMin ? _softMin : min(_softMin, _newMin));
|
|
281
|
+
let _newMax = roundDec(incrRoundUp(_max + nonZeroDelta * (delta == 0 ? _max == 0 ? .1 : 1 : padMax), base / 10), 24);
|
|
282
|
+
let _softMax = _max <= softMax && (softMaxMode == 1 || softMaxMode == 3 && _newMax >= softMax || softMaxMode == 2 && _newMax <= softMax) ? softMax : -inf;
|
|
283
|
+
let maxLim = min(hardMax, _newMax > _softMax && _max <= _softMax ? _softMax : max(_softMax, _newMax));
|
|
284
|
+
if (minLim == maxLim && minLim == 0) maxLim = 100;
|
|
285
|
+
return [minLim, maxLim];
|
|
286
|
+
}
|
|
287
|
+
var numFormatter = new Intl.NumberFormat(domEnv ? nav.language : "en-US");
|
|
288
|
+
var fmtNum = (val) => numFormatter.format(val);
|
|
289
|
+
var M = Math;
|
|
290
|
+
var PI = M.PI;
|
|
291
|
+
var abs = M.abs;
|
|
292
|
+
var floor = M.floor;
|
|
293
|
+
var round = M.round;
|
|
294
|
+
var ceil = M.ceil;
|
|
295
|
+
var min = M.min;
|
|
296
|
+
var max = M.max;
|
|
297
|
+
var pow = M.pow;
|
|
298
|
+
var sign = M.sign;
|
|
299
|
+
var log10 = M.log10;
|
|
300
|
+
var log2 = M.log2;
|
|
301
|
+
var sinh = (v, linthresh = 1) => M.sinh(v) * linthresh;
|
|
302
|
+
var asinh = (v, linthresh = 1) => M.asinh(v / linthresh);
|
|
303
|
+
var inf = Infinity;
|
|
304
|
+
function numIntDigits(x) {
|
|
305
|
+
return (log10((x ^ x >> 31) - (x >> 31)) | 0) + 1;
|
|
306
|
+
}
|
|
307
|
+
function clamp(num, _min, _max) {
|
|
308
|
+
return min(max(num, _min), _max);
|
|
309
|
+
}
|
|
310
|
+
function isFn(v) {
|
|
311
|
+
return typeof v == "function";
|
|
312
|
+
}
|
|
313
|
+
function fnOrSelf(v) {
|
|
314
|
+
return isFn(v) ? v : () => v;
|
|
315
|
+
}
|
|
316
|
+
var noop = () => {};
|
|
317
|
+
var retArg0 = (_0) => _0;
|
|
318
|
+
var retArg1 = (_0, _1) => _1;
|
|
319
|
+
var retNull = (_) => null;
|
|
320
|
+
var retTrue = (_) => true;
|
|
321
|
+
var retEq = (a, b) => a == b;
|
|
322
|
+
var regex6 = /\.\d*?(?=9{6,}|0{6,})/gm;
|
|
323
|
+
var fixFloat = (val) => {
|
|
324
|
+
if (isInt(val) || fixedDec.has(val)) return val;
|
|
325
|
+
const str = `${val}`;
|
|
326
|
+
const match = str.match(regex6);
|
|
327
|
+
if (match == null) return val;
|
|
328
|
+
let len = match[0].length - 1;
|
|
329
|
+
if (str.indexOf("e-") != -1) {
|
|
330
|
+
let [num, exp] = str.split("e");
|
|
331
|
+
return +`${fixFloat(num)}e${exp}`;
|
|
332
|
+
}
|
|
333
|
+
return roundDec(val, len);
|
|
334
|
+
};
|
|
335
|
+
function incrRound(num, incr) {
|
|
336
|
+
return fixFloat(roundDec(fixFloat(num / incr)) * incr);
|
|
337
|
+
}
|
|
338
|
+
function incrRoundUp(num, incr) {
|
|
339
|
+
return fixFloat(ceil(fixFloat(num / incr)) * incr);
|
|
340
|
+
}
|
|
341
|
+
function incrRoundDn(num, incr) {
|
|
342
|
+
return fixFloat(floor(fixFloat(num / incr)) * incr);
|
|
343
|
+
}
|
|
344
|
+
function roundDec(val, dec = 0) {
|
|
345
|
+
if (isInt(val)) return val;
|
|
346
|
+
let p = 10 ** dec;
|
|
347
|
+
return round(val * p * (1 + Number.EPSILON)) / p;
|
|
348
|
+
}
|
|
349
|
+
var fixedDec = /* @__PURE__ */ new Map();
|
|
350
|
+
function guessDec(num) {
|
|
351
|
+
return (("" + num).split(".")[1] || "").length;
|
|
352
|
+
}
|
|
353
|
+
function genIncrs(base, minExp, maxExp, mults) {
|
|
354
|
+
let incrs = [];
|
|
355
|
+
let multDec = mults.map(guessDec);
|
|
356
|
+
for (let exp = minExp; exp < maxExp; exp++) {
|
|
357
|
+
let expa = abs(exp);
|
|
358
|
+
let mag = roundDec(pow(base, exp), expa);
|
|
359
|
+
for (let i = 0; i < mults.length; i++) {
|
|
360
|
+
let _incr = base == 10 ? +`${mults[i]}e${exp}` : mults[i] * mag;
|
|
361
|
+
let dec = (exp >= 0 ? 0 : expa) + (exp >= multDec[i] ? 0 : multDec[i]);
|
|
362
|
+
let incr = base == 10 ? _incr : roundDec(_incr, dec);
|
|
363
|
+
incrs.push(incr);
|
|
364
|
+
fixedDec.set(incr, dec);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return incrs;
|
|
368
|
+
}
|
|
369
|
+
var EMPTY_OBJ = {};
|
|
370
|
+
var EMPTY_ARR = [];
|
|
371
|
+
var nullNullTuple = [null, null];
|
|
372
|
+
var isArr = Array.isArray;
|
|
373
|
+
var isInt = Number.isInteger;
|
|
374
|
+
var isUndef = (v) => v === void 0;
|
|
375
|
+
function isStr(v) {
|
|
376
|
+
return typeof v == "string";
|
|
377
|
+
}
|
|
378
|
+
function isObj(v) {
|
|
379
|
+
let is = false;
|
|
380
|
+
if (v != null) {
|
|
381
|
+
let c = v.constructor;
|
|
382
|
+
is = c == null || c == Object;
|
|
383
|
+
}
|
|
384
|
+
return is;
|
|
385
|
+
}
|
|
386
|
+
function fastIsObj(v) {
|
|
387
|
+
return v != null && typeof v == "object";
|
|
388
|
+
}
|
|
389
|
+
var TypedArray = Object.getPrototypeOf(Uint8Array);
|
|
390
|
+
var __proto__ = "__proto__";
|
|
391
|
+
function copy(o, _isObj = isObj) {
|
|
392
|
+
let out;
|
|
393
|
+
if (isArr(o)) {
|
|
394
|
+
let val = o.find((v) => v != null);
|
|
395
|
+
if (isArr(val) || _isObj(val)) {
|
|
396
|
+
out = Array(o.length);
|
|
397
|
+
for (let i = 0; i < o.length; i++) out[i] = copy(o[i], _isObj);
|
|
398
|
+
} else out = o.slice();
|
|
399
|
+
} else if (o instanceof TypedArray) out = o.slice();
|
|
400
|
+
else if (_isObj(o)) {
|
|
401
|
+
out = {};
|
|
402
|
+
for (let k in o) if (k != __proto__) out[k] = copy(o[k], _isObj);
|
|
403
|
+
} else out = o;
|
|
404
|
+
return out;
|
|
405
|
+
}
|
|
406
|
+
function assign(targ) {
|
|
407
|
+
let args = arguments;
|
|
408
|
+
for (let i = 1; i < args.length; i++) {
|
|
409
|
+
let src = args[i];
|
|
410
|
+
for (let key in src) if (key != __proto__) if (isObj(targ[key])) assign(targ[key], copy(src[key]));
|
|
411
|
+
else targ[key] = copy(src[key]);
|
|
412
|
+
}
|
|
413
|
+
return targ;
|
|
414
|
+
}
|
|
415
|
+
var NULL_REMOVE = 0;
|
|
416
|
+
var NULL_RETAIN = 1;
|
|
417
|
+
var NULL_EXPAND = 2;
|
|
418
|
+
function nullExpand(yVals, nullIdxs, alignedLen) {
|
|
419
|
+
for (let i = 0, xi, lastNullIdx = -1; i < nullIdxs.length; i++) {
|
|
420
|
+
let nullIdx = nullIdxs[i];
|
|
421
|
+
if (nullIdx > lastNullIdx) {
|
|
422
|
+
xi = nullIdx - 1;
|
|
423
|
+
while (xi >= 0 && yVals[xi] == null) yVals[xi--] = null;
|
|
424
|
+
xi = nullIdx + 1;
|
|
425
|
+
while (xi < alignedLen && yVals[xi] == null) yVals[lastNullIdx = xi++] = null;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
function join(tables, nullModes) {
|
|
430
|
+
if (allHeadersSame(tables)) {
|
|
431
|
+
let table = tables[0].slice();
|
|
432
|
+
for (let i = 1; i < tables.length; i++) table.push(...tables[i].slice(1));
|
|
433
|
+
if (!isAsc(table[0])) table = sortCols(table);
|
|
434
|
+
return table;
|
|
435
|
+
}
|
|
436
|
+
let xVals = /* @__PURE__ */ new Set();
|
|
437
|
+
for (let ti = 0; ti < tables.length; ti++) {
|
|
438
|
+
let xs = tables[ti][0];
|
|
439
|
+
let len = xs.length;
|
|
440
|
+
for (let i = 0; i < len; i++) xVals.add(xs[i]);
|
|
441
|
+
}
|
|
442
|
+
let data = [Array.from(xVals).sort((a, b) => a - b)];
|
|
443
|
+
let alignedLen = data[0].length;
|
|
444
|
+
let xIdxs = /* @__PURE__ */ new Map();
|
|
445
|
+
for (let i = 0; i < alignedLen; i++) xIdxs.set(data[0][i], i);
|
|
446
|
+
for (let ti = 0; ti < tables.length; ti++) {
|
|
447
|
+
let t = tables[ti];
|
|
448
|
+
let xs = t[0];
|
|
449
|
+
for (let si = 1; si < t.length; si++) {
|
|
450
|
+
let ys = t[si];
|
|
451
|
+
let yVals = Array(alignedLen).fill(void 0);
|
|
452
|
+
let nullMode = nullModes ? nullModes[ti][si] : NULL_RETAIN;
|
|
453
|
+
let nullIdxs = [];
|
|
454
|
+
for (let i = 0; i < ys.length; i++) {
|
|
455
|
+
let yVal = ys[i];
|
|
456
|
+
let alignedIdx = xIdxs.get(xs[i]);
|
|
457
|
+
if (yVal === null) {
|
|
458
|
+
if (nullMode != NULL_REMOVE) {
|
|
459
|
+
yVals[alignedIdx] = yVal;
|
|
460
|
+
if (nullMode == NULL_EXPAND) nullIdxs.push(alignedIdx);
|
|
461
|
+
}
|
|
462
|
+
} else yVals[alignedIdx] = yVal;
|
|
463
|
+
}
|
|
464
|
+
nullExpand(yVals, nullIdxs, alignedLen);
|
|
465
|
+
data.push(yVals);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return data;
|
|
469
|
+
}
|
|
470
|
+
var microTask = typeof queueMicrotask == "undefined" ? (fn) => Promise.resolve().then(fn) : queueMicrotask;
|
|
471
|
+
function sortCols(table) {
|
|
472
|
+
let head = table[0];
|
|
473
|
+
let rlen = head.length;
|
|
474
|
+
let idxs = Array(rlen);
|
|
475
|
+
for (let i = 0; i < idxs.length; i++) idxs[i] = i;
|
|
476
|
+
idxs.sort((i0, i1) => head[i0] - head[i1]);
|
|
477
|
+
let table2 = [];
|
|
478
|
+
for (let i = 0; i < table.length; i++) {
|
|
479
|
+
let row = table[i];
|
|
480
|
+
let row2 = Array(rlen);
|
|
481
|
+
for (let j = 0; j < rlen; j++) row2[j] = row[idxs[j]];
|
|
482
|
+
table2.push(row2);
|
|
483
|
+
}
|
|
484
|
+
return table2;
|
|
485
|
+
}
|
|
486
|
+
function allHeadersSame(tables) {
|
|
487
|
+
let vals0 = tables[0][0];
|
|
488
|
+
let len0 = vals0.length;
|
|
489
|
+
for (let i = 1; i < tables.length; i++) {
|
|
490
|
+
let vals1 = tables[i][0];
|
|
491
|
+
if (vals1.length != len0) return false;
|
|
492
|
+
if (vals1 != vals0) {
|
|
493
|
+
for (let j = 0; j < len0; j++) if (vals1[j] != vals0[j]) return false;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
function isAsc(vals, samples = 100) {
|
|
499
|
+
const len = vals.length;
|
|
500
|
+
if (len <= 1) return true;
|
|
501
|
+
let firstIdx = 0;
|
|
502
|
+
let lastIdx = len - 1;
|
|
503
|
+
while (firstIdx <= lastIdx && vals[firstIdx] == null) firstIdx++;
|
|
504
|
+
while (lastIdx >= firstIdx && vals[lastIdx] == null) lastIdx--;
|
|
505
|
+
if (lastIdx <= firstIdx) return true;
|
|
506
|
+
const stride = max(1, floor((lastIdx - firstIdx + 1) / samples));
|
|
507
|
+
for (let prevVal = vals[firstIdx], i = firstIdx + stride; i <= lastIdx; i += stride) {
|
|
508
|
+
const v = vals[i];
|
|
509
|
+
if (v != null) {
|
|
510
|
+
if (v <= prevVal) return false;
|
|
511
|
+
prevVal = v;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return true;
|
|
515
|
+
}
|
|
516
|
+
var months = [
|
|
517
|
+
"January",
|
|
518
|
+
"February",
|
|
519
|
+
"March",
|
|
520
|
+
"April",
|
|
521
|
+
"May",
|
|
522
|
+
"June",
|
|
523
|
+
"July",
|
|
524
|
+
"August",
|
|
525
|
+
"September",
|
|
526
|
+
"October",
|
|
527
|
+
"November",
|
|
528
|
+
"December"
|
|
529
|
+
];
|
|
530
|
+
var days = [
|
|
531
|
+
"Sunday",
|
|
532
|
+
"Monday",
|
|
533
|
+
"Tuesday",
|
|
534
|
+
"Wednesday",
|
|
535
|
+
"Thursday",
|
|
536
|
+
"Friday",
|
|
537
|
+
"Saturday"
|
|
538
|
+
];
|
|
539
|
+
function slice3(str) {
|
|
540
|
+
return str.slice(0, 3);
|
|
541
|
+
}
|
|
542
|
+
var days3 = days.map(slice3);
|
|
543
|
+
var engNames = {
|
|
544
|
+
MMMM: months,
|
|
545
|
+
MMM: months.map(slice3),
|
|
546
|
+
WWWW: days,
|
|
547
|
+
WWW: days3
|
|
548
|
+
};
|
|
549
|
+
function zeroPad2(int) {
|
|
550
|
+
return (int < 10 ? "0" : "") + int;
|
|
551
|
+
}
|
|
552
|
+
function zeroPad3(int) {
|
|
553
|
+
return (int < 10 ? "00" : int < 100 ? "0" : "") + int;
|
|
554
|
+
}
|
|
555
|
+
var subs = {
|
|
556
|
+
YYYY: (d) => d.getFullYear(),
|
|
557
|
+
YY: (d) => (d.getFullYear() + "").slice(2),
|
|
558
|
+
MMMM: (d, names) => names.MMMM[d.getMonth()],
|
|
559
|
+
MMM: (d, names) => names.MMM[d.getMonth()],
|
|
560
|
+
MM: (d) => zeroPad2(d.getMonth() + 1),
|
|
561
|
+
M: (d) => d.getMonth() + 1,
|
|
562
|
+
DD: (d) => zeroPad2(d.getDate()),
|
|
563
|
+
D: (d) => d.getDate(),
|
|
564
|
+
WWWW: (d, names) => names.WWWW[d.getDay()],
|
|
565
|
+
WWW: (d, names) => names.WWW[d.getDay()],
|
|
566
|
+
HH: (d) => zeroPad2(d.getHours()),
|
|
567
|
+
H: (d) => d.getHours(),
|
|
568
|
+
h: (d) => {
|
|
569
|
+
let h = d.getHours();
|
|
570
|
+
return h == 0 ? 12 : h > 12 ? h - 12 : h;
|
|
571
|
+
},
|
|
572
|
+
AA: (d) => d.getHours() >= 12 ? "PM" : "AM",
|
|
573
|
+
aa: (d) => d.getHours() >= 12 ? "pm" : "am",
|
|
574
|
+
a: (d) => d.getHours() >= 12 ? "p" : "a",
|
|
575
|
+
mm: (d) => zeroPad2(d.getMinutes()),
|
|
576
|
+
m: (d) => d.getMinutes(),
|
|
577
|
+
ss: (d) => zeroPad2(d.getSeconds()),
|
|
578
|
+
s: (d) => d.getSeconds(),
|
|
579
|
+
fff: (d) => zeroPad3(d.getMilliseconds())
|
|
580
|
+
};
|
|
581
|
+
function fmtDate(tpl, names) {
|
|
582
|
+
names = names || engNames;
|
|
583
|
+
let parts = [];
|
|
584
|
+
let R = /\{([a-z]+)\}|[^{]+/gi, m;
|
|
585
|
+
while (m = R.exec(tpl)) parts.push(m[0][0] == "{" ? subs[m[1]] : m[0]);
|
|
586
|
+
return (d) => {
|
|
587
|
+
let out = "";
|
|
588
|
+
for (let i = 0; i < parts.length; i++) out += typeof parts[i] == "string" ? parts[i] : parts[i](d, names);
|
|
589
|
+
return out;
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
var localTz = new Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
593
|
+
function tzDate(date, tz) {
|
|
594
|
+
let date2;
|
|
595
|
+
if (tz == "UTC" || tz == "Etc/UTC") date2 = /* @__PURE__ */ new Date(+date + date.getTimezoneOffset() * 6e4);
|
|
596
|
+
else if (tz == localTz) date2 = date;
|
|
597
|
+
else {
|
|
598
|
+
date2 = new Date(date.toLocaleString("en-US", { timeZone: tz }));
|
|
599
|
+
date2.setMilliseconds(date.getMilliseconds());
|
|
600
|
+
}
|
|
601
|
+
return date2;
|
|
602
|
+
}
|
|
603
|
+
var onlyWhole = (v) => v % 1 == 0;
|
|
604
|
+
var allMults = [
|
|
605
|
+
1,
|
|
606
|
+
2,
|
|
607
|
+
2.5,
|
|
608
|
+
5
|
|
609
|
+
];
|
|
610
|
+
var decIncrs = genIncrs(10, -32, 0, allMults);
|
|
611
|
+
var oneIncrs = genIncrs(10, 0, 32, allMults);
|
|
612
|
+
var wholeIncrs = oneIncrs.filter(onlyWhole);
|
|
613
|
+
var numIncrs = decIncrs.concat(oneIncrs);
|
|
614
|
+
var yyyy = "{YYYY}";
|
|
615
|
+
var NLyyyy = "\n{YYYY}";
|
|
616
|
+
var md = "{M}/{D}";
|
|
617
|
+
var NLmd = "\n{M}/{D}";
|
|
618
|
+
var NLmdyy = "\n{M}/{D}/{YY}";
|
|
619
|
+
var hmmaa = "{h}:{mm}{aa}";
|
|
620
|
+
var NLhmmaa = "\n{h}:{mm}{aa}";
|
|
621
|
+
var ss = ":{ss}";
|
|
622
|
+
var _ = null;
|
|
623
|
+
function genTimeStuffs(ms) {
|
|
624
|
+
let s = ms * 1e3, m = s * 60, h = m * 60, d = h * 24, mo = d * 30, y = d * 365;
|
|
625
|
+
let timeIncrs = (ms == 1 ? genIncrs(10, 0, 3, allMults).filter(onlyWhole) : genIncrs(10, -3, 0, allMults)).concat([
|
|
626
|
+
s,
|
|
627
|
+
s * 5,
|
|
628
|
+
s * 10,
|
|
629
|
+
s * 15,
|
|
630
|
+
s * 30,
|
|
631
|
+
m,
|
|
632
|
+
m * 5,
|
|
633
|
+
m * 10,
|
|
634
|
+
m * 15,
|
|
635
|
+
m * 30,
|
|
636
|
+
h,
|
|
637
|
+
h * 2,
|
|
638
|
+
h * 3,
|
|
639
|
+
h * 4,
|
|
640
|
+
h * 6,
|
|
641
|
+
h * 8,
|
|
642
|
+
h * 12,
|
|
643
|
+
d,
|
|
644
|
+
d * 2,
|
|
645
|
+
d * 3,
|
|
646
|
+
d * 4,
|
|
647
|
+
d * 5,
|
|
648
|
+
d * 6,
|
|
649
|
+
d * 7,
|
|
650
|
+
d * 8,
|
|
651
|
+
d * 9,
|
|
652
|
+
d * 10,
|
|
653
|
+
d * 15,
|
|
654
|
+
mo,
|
|
655
|
+
mo * 2,
|
|
656
|
+
mo * 3,
|
|
657
|
+
mo * 4,
|
|
658
|
+
mo * 6,
|
|
659
|
+
y,
|
|
660
|
+
y * 2,
|
|
661
|
+
y * 5,
|
|
662
|
+
y * 10,
|
|
663
|
+
y * 25,
|
|
664
|
+
y * 50,
|
|
665
|
+
y * 100
|
|
666
|
+
]);
|
|
667
|
+
const _timeAxisStamps = [
|
|
668
|
+
[
|
|
669
|
+
y,
|
|
670
|
+
yyyy,
|
|
671
|
+
_,
|
|
672
|
+
_,
|
|
673
|
+
_,
|
|
674
|
+
_,
|
|
675
|
+
_,
|
|
676
|
+
_,
|
|
677
|
+
1
|
|
678
|
+
],
|
|
679
|
+
[
|
|
680
|
+
d * 28,
|
|
681
|
+
"{MMM}",
|
|
682
|
+
NLyyyy,
|
|
683
|
+
_,
|
|
684
|
+
_,
|
|
685
|
+
_,
|
|
686
|
+
_,
|
|
687
|
+
_,
|
|
688
|
+
1
|
|
689
|
+
],
|
|
690
|
+
[
|
|
691
|
+
d,
|
|
692
|
+
md,
|
|
693
|
+
NLyyyy,
|
|
694
|
+
_,
|
|
695
|
+
_,
|
|
696
|
+
_,
|
|
697
|
+
_,
|
|
698
|
+
_,
|
|
699
|
+
1
|
|
700
|
+
],
|
|
701
|
+
[
|
|
702
|
+
h,
|
|
703
|
+
"{h}{aa}",
|
|
704
|
+
NLmdyy,
|
|
705
|
+
_,
|
|
706
|
+
NLmd,
|
|
707
|
+
_,
|
|
708
|
+
_,
|
|
709
|
+
_,
|
|
710
|
+
1
|
|
711
|
+
],
|
|
712
|
+
[
|
|
713
|
+
m,
|
|
714
|
+
hmmaa,
|
|
715
|
+
NLmdyy,
|
|
716
|
+
_,
|
|
717
|
+
NLmd,
|
|
718
|
+
_,
|
|
719
|
+
_,
|
|
720
|
+
_,
|
|
721
|
+
1
|
|
722
|
+
],
|
|
723
|
+
[
|
|
724
|
+
s,
|
|
725
|
+
ss,
|
|
726
|
+
"\n{M}/{D}/{YY} {h}:{mm}{aa}",
|
|
727
|
+
_,
|
|
728
|
+
"\n{M}/{D} {h}:{mm}{aa}",
|
|
729
|
+
_,
|
|
730
|
+
NLhmmaa,
|
|
731
|
+
_,
|
|
732
|
+
1
|
|
733
|
+
],
|
|
734
|
+
[
|
|
735
|
+
ms,
|
|
736
|
+
":{ss}.{fff}",
|
|
737
|
+
"\n{M}/{D}/{YY} {h}:{mm}{aa}",
|
|
738
|
+
_,
|
|
739
|
+
"\n{M}/{D} {h}:{mm}{aa}",
|
|
740
|
+
_,
|
|
741
|
+
NLhmmaa,
|
|
742
|
+
_,
|
|
743
|
+
1
|
|
744
|
+
]
|
|
745
|
+
];
|
|
746
|
+
function timeAxisSplits(tzDate) {
|
|
747
|
+
return (self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace) => {
|
|
748
|
+
let splits = [];
|
|
749
|
+
let isYr = foundIncr >= y;
|
|
750
|
+
let isMo = foundIncr >= mo && foundIncr < y;
|
|
751
|
+
let minDate = tzDate(scaleMin);
|
|
752
|
+
let minDateTs = roundDec(minDate * ms, 3);
|
|
753
|
+
let minMin = mkDate(minDate.getFullYear(), isYr ? 0 : minDate.getMonth(), isMo || isYr ? 1 : minDate.getDate());
|
|
754
|
+
let minMinTs = roundDec(minMin * ms, 3);
|
|
755
|
+
if (isMo || isYr) {
|
|
756
|
+
let moIncr = isMo ? foundIncr / mo : 0;
|
|
757
|
+
let yrIncr = isYr ? foundIncr / y : 0;
|
|
758
|
+
let split = minDateTs == minMinTs ? minDateTs : roundDec(mkDate(minMin.getFullYear() + yrIncr, minMin.getMonth() + moIncr, 1) * ms, 3);
|
|
759
|
+
let splitDate = new Date(round(split / ms));
|
|
760
|
+
let baseYear = splitDate.getFullYear();
|
|
761
|
+
let baseMonth = splitDate.getMonth();
|
|
762
|
+
for (let i = 0; split <= scaleMax; i++) {
|
|
763
|
+
let next = mkDate(baseYear + yrIncr * i, baseMonth + moIncr * i, 1);
|
|
764
|
+
let offs = next - tzDate(roundDec(next * ms, 3));
|
|
765
|
+
split = roundDec((+next + offs) * ms, 3);
|
|
766
|
+
if (split <= scaleMax) splits.push(split);
|
|
767
|
+
}
|
|
768
|
+
} else {
|
|
769
|
+
let incr0 = foundIncr >= d ? d : foundIncr;
|
|
770
|
+
let split = minMinTs + (floor(scaleMin) - floor(minDateTs)) + incrRoundUp(minDateTs - minMinTs, incr0);
|
|
771
|
+
splits.push(split);
|
|
772
|
+
let date0 = tzDate(split);
|
|
773
|
+
let prevHour = date0.getHours() + date0.getMinutes() / m + date0.getSeconds() / h;
|
|
774
|
+
let incrHours = foundIncr / h;
|
|
775
|
+
let pctSpace = foundSpace / self.axes[axisIdx]._space;
|
|
776
|
+
while (1) {
|
|
777
|
+
split = roundDec(split + foundIncr, ms == 1 ? 0 : 3);
|
|
778
|
+
if (split > scaleMax) break;
|
|
779
|
+
if (incrHours > 1) {
|
|
780
|
+
let expectedHour = floor(roundDec(prevHour + incrHours, 6)) % 24;
|
|
781
|
+
let dstShift = tzDate(split).getHours() - expectedHour;
|
|
782
|
+
if (dstShift > 1) dstShift = -1;
|
|
783
|
+
split -= dstShift * h;
|
|
784
|
+
prevHour = (prevHour + incrHours) % 24;
|
|
785
|
+
let prevSplit = splits[splits.length - 1];
|
|
786
|
+
if (roundDec((split - prevSplit) / foundIncr, 3) * pctSpace >= .7) splits.push(split);
|
|
787
|
+
} else splits.push(split);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return splits;
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
return [
|
|
794
|
+
timeIncrs,
|
|
795
|
+
_timeAxisStamps,
|
|
796
|
+
timeAxisSplits
|
|
797
|
+
];
|
|
798
|
+
}
|
|
799
|
+
var [timeIncrsMs, _timeAxisStampsMs, timeAxisSplitsMs] = genTimeStuffs(1);
|
|
800
|
+
var [timeIncrsS, _timeAxisStampsS, timeAxisSplitsS] = genTimeStuffs(.001);
|
|
801
|
+
genIncrs(2, -53, 53, [1]);
|
|
802
|
+
function timeAxisStamps(stampCfg, fmtDate) {
|
|
803
|
+
return stampCfg.map((s) => s.map((v, i) => i == 0 || i == 8 || v == null ? v : fmtDate(i == 1 || s[8] == 0 ? v : s[1] + v)));
|
|
804
|
+
}
|
|
805
|
+
function timeAxisVals(tzDate, stamps) {
|
|
806
|
+
return (self, splits, axisIdx, foundSpace, foundIncr) => {
|
|
807
|
+
let s = stamps.find((s) => foundIncr >= s[0]) || stamps[stamps.length - 1];
|
|
808
|
+
let prevYear;
|
|
809
|
+
let prevMnth;
|
|
810
|
+
let prevDate;
|
|
811
|
+
let prevHour;
|
|
812
|
+
let prevMins;
|
|
813
|
+
let prevSecs;
|
|
814
|
+
return splits.map((split) => {
|
|
815
|
+
let date = tzDate(split);
|
|
816
|
+
let newYear = date.getFullYear();
|
|
817
|
+
let newMnth = date.getMonth();
|
|
818
|
+
let newDate = date.getDate();
|
|
819
|
+
let newHour = date.getHours();
|
|
820
|
+
let newMins = date.getMinutes();
|
|
821
|
+
let newSecs = date.getSeconds();
|
|
822
|
+
let stamp = newYear != prevYear && s[2] || newMnth != prevMnth && s[3] || newDate != prevDate && s[4] || newHour != prevHour && s[5] || newMins != prevMins && s[6] || newSecs != prevSecs && s[7] || s[1];
|
|
823
|
+
prevYear = newYear;
|
|
824
|
+
prevMnth = newMnth;
|
|
825
|
+
prevDate = newDate;
|
|
826
|
+
prevHour = newHour;
|
|
827
|
+
prevMins = newMins;
|
|
828
|
+
prevSecs = newSecs;
|
|
829
|
+
return stamp(date);
|
|
830
|
+
});
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
function timeAxisVal(tzDate, dateTpl) {
|
|
834
|
+
let stamp = fmtDate(dateTpl);
|
|
835
|
+
return (self, splits, axisIdx, foundSpace, foundIncr) => splits.map((split) => stamp(tzDate(split)));
|
|
836
|
+
}
|
|
837
|
+
function mkDate(y, m, d) {
|
|
838
|
+
return new Date(y, m, d);
|
|
839
|
+
}
|
|
840
|
+
function timeSeriesStamp(stampCfg, fmtDate) {
|
|
841
|
+
return fmtDate(stampCfg);
|
|
842
|
+
}
|
|
843
|
+
var _timeSeriesStamp = "{YYYY}-{MM}-{DD} {h}:{mm}{aa}";
|
|
844
|
+
function timeSeriesVal(tzDate, stamp) {
|
|
845
|
+
return (self, val, seriesIdx, dataIdx) => dataIdx == null ? LEGEND_DISP : stamp(tzDate(val));
|
|
846
|
+
}
|
|
847
|
+
function legendStroke(self, seriesIdx) {
|
|
848
|
+
let s = self.series[seriesIdx];
|
|
849
|
+
return s.width ? s.stroke(self, seriesIdx) : s.points.width ? s.points.stroke(self, seriesIdx) : null;
|
|
850
|
+
}
|
|
851
|
+
function legendFill(self, seriesIdx) {
|
|
852
|
+
return self.series[seriesIdx].fill(self, seriesIdx);
|
|
853
|
+
}
|
|
854
|
+
var legendOpts = {
|
|
855
|
+
show: true,
|
|
856
|
+
live: true,
|
|
857
|
+
isolate: false,
|
|
858
|
+
mount: noop,
|
|
859
|
+
markers: {
|
|
860
|
+
show: true,
|
|
861
|
+
width: 2,
|
|
862
|
+
stroke: legendStroke,
|
|
863
|
+
fill: legendFill,
|
|
864
|
+
dash: "solid"
|
|
865
|
+
},
|
|
866
|
+
idx: null,
|
|
867
|
+
idxs: null,
|
|
868
|
+
values: []
|
|
869
|
+
};
|
|
870
|
+
function cursorPointShow(self, si) {
|
|
871
|
+
let o = self.cursor.points;
|
|
872
|
+
let pt = placeDiv();
|
|
873
|
+
let size = o.size(self, si);
|
|
874
|
+
setStylePx(pt, WIDTH, size);
|
|
875
|
+
setStylePx(pt, HEIGHT, size);
|
|
876
|
+
let mar = size / -2;
|
|
877
|
+
setStylePx(pt, "marginLeft", mar);
|
|
878
|
+
setStylePx(pt, "marginTop", mar);
|
|
879
|
+
let width = o.width(self, si, size);
|
|
880
|
+
width && setStylePx(pt, "borderWidth", width);
|
|
881
|
+
return pt;
|
|
882
|
+
}
|
|
883
|
+
function cursorPointFill(self, si) {
|
|
884
|
+
let sp = self.series[si].points;
|
|
885
|
+
return sp._fill || sp._stroke;
|
|
886
|
+
}
|
|
887
|
+
function cursorPointStroke(self, si) {
|
|
888
|
+
let sp = self.series[si].points;
|
|
889
|
+
return sp._stroke || sp._fill;
|
|
890
|
+
}
|
|
891
|
+
function cursorPointSize(self, si) {
|
|
892
|
+
return self.series[si].points.size;
|
|
893
|
+
}
|
|
894
|
+
var moveTuple = [0, 0];
|
|
895
|
+
function cursorMove(self, mouseLeft1, mouseTop1) {
|
|
896
|
+
moveTuple[0] = mouseLeft1;
|
|
897
|
+
moveTuple[1] = mouseTop1;
|
|
898
|
+
return moveTuple;
|
|
899
|
+
}
|
|
900
|
+
function filtBtn0(self, targ, handle, onlyTarg = true) {
|
|
901
|
+
return (e) => {
|
|
902
|
+
e.button == 0 && (!onlyTarg || e.target == targ) && handle(e);
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
function filtTarg(self, targ, handle, onlyTarg = true) {
|
|
906
|
+
return (e) => {
|
|
907
|
+
(!onlyTarg || e.target == targ) && handle(e);
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
var cursorOpts = {
|
|
911
|
+
show: true,
|
|
912
|
+
x: true,
|
|
913
|
+
y: true,
|
|
914
|
+
lock: false,
|
|
915
|
+
move: cursorMove,
|
|
916
|
+
points: {
|
|
917
|
+
one: false,
|
|
918
|
+
show: cursorPointShow,
|
|
919
|
+
size: cursorPointSize,
|
|
920
|
+
width: 0,
|
|
921
|
+
stroke: cursorPointStroke,
|
|
922
|
+
fill: cursorPointFill
|
|
923
|
+
},
|
|
924
|
+
bind: {
|
|
925
|
+
mousedown: filtBtn0,
|
|
926
|
+
mouseup: filtBtn0,
|
|
927
|
+
click: filtBtn0,
|
|
928
|
+
dblclick: filtBtn0,
|
|
929
|
+
mousemove: filtTarg,
|
|
930
|
+
mouseleave: filtTarg,
|
|
931
|
+
mouseenter: filtTarg
|
|
932
|
+
},
|
|
933
|
+
drag: {
|
|
934
|
+
setScale: true,
|
|
935
|
+
x: true,
|
|
936
|
+
y: false,
|
|
937
|
+
dist: 0,
|
|
938
|
+
uni: null,
|
|
939
|
+
click: (self, e) => {
|
|
940
|
+
e.stopPropagation();
|
|
941
|
+
e.stopImmediatePropagation();
|
|
942
|
+
},
|
|
943
|
+
_x: false,
|
|
944
|
+
_y: false
|
|
945
|
+
},
|
|
946
|
+
focus: {
|
|
947
|
+
dist: (self, seriesIdx, dataIdx, valPos, curPos) => valPos - curPos,
|
|
948
|
+
prox: -1,
|
|
949
|
+
bias: 0
|
|
950
|
+
},
|
|
951
|
+
hover: {
|
|
952
|
+
skip: [void 0],
|
|
953
|
+
prox: null,
|
|
954
|
+
bias: 0
|
|
955
|
+
},
|
|
956
|
+
left: -10,
|
|
957
|
+
top: -10,
|
|
958
|
+
idx: null,
|
|
959
|
+
dataIdx: null,
|
|
960
|
+
idxs: null,
|
|
961
|
+
event: null
|
|
962
|
+
};
|
|
963
|
+
var axisLines = {
|
|
964
|
+
show: true,
|
|
965
|
+
stroke: "rgba(0,0,0,0.07)",
|
|
966
|
+
width: 2
|
|
967
|
+
};
|
|
968
|
+
var grid = assign({}, axisLines, { filter: retArg1 });
|
|
969
|
+
var ticks = assign({}, grid, { size: 10 });
|
|
970
|
+
var border = assign({}, axisLines, { show: false });
|
|
971
|
+
var font = "12px system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\"";
|
|
972
|
+
var labelFont = "bold 12px system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\"";
|
|
973
|
+
var lineGap = 1.5;
|
|
974
|
+
var xAxisOpts = {
|
|
975
|
+
show: true,
|
|
976
|
+
scale: "x",
|
|
977
|
+
stroke: hexBlack,
|
|
978
|
+
space: 50,
|
|
979
|
+
gap: 5,
|
|
980
|
+
alignTo: 1,
|
|
981
|
+
size: 50,
|
|
982
|
+
labelGap: 0,
|
|
983
|
+
labelSize: 30,
|
|
984
|
+
labelFont,
|
|
985
|
+
side: 2,
|
|
986
|
+
grid,
|
|
987
|
+
ticks,
|
|
988
|
+
border,
|
|
989
|
+
font,
|
|
990
|
+
lineGap,
|
|
991
|
+
rotate: 0
|
|
992
|
+
};
|
|
993
|
+
var numSeriesLabel = "Value";
|
|
994
|
+
var timeSeriesLabel = "Time";
|
|
995
|
+
var xSeriesOpts = {
|
|
996
|
+
show: true,
|
|
997
|
+
scale: "x",
|
|
998
|
+
auto: false,
|
|
999
|
+
sorted: 1,
|
|
1000
|
+
min: inf,
|
|
1001
|
+
max: -Infinity,
|
|
1002
|
+
idxs: []
|
|
1003
|
+
};
|
|
1004
|
+
function numAxisVals(self, splits, axisIdx, foundSpace, foundIncr) {
|
|
1005
|
+
return splits.map((v) => v == null ? "" : fmtNum(v));
|
|
1006
|
+
}
|
|
1007
|
+
function numAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace, forceMin) {
|
|
1008
|
+
let splits = [];
|
|
1009
|
+
let numDec = fixedDec.get(foundIncr) || 0;
|
|
1010
|
+
scaleMin = forceMin ? scaleMin : roundDec(incrRoundUp(scaleMin, foundIncr), numDec);
|
|
1011
|
+
for (let val = scaleMin; val <= scaleMax; val = roundDec(val + foundIncr, numDec)) splits.push(Object.is(val, -0) ? 0 : val);
|
|
1012
|
+
return splits;
|
|
1013
|
+
}
|
|
1014
|
+
function logAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace, forceMin) {
|
|
1015
|
+
const splits = [];
|
|
1016
|
+
const logBase = self.scales[self.axes[axisIdx].scale].log;
|
|
1017
|
+
foundIncr = pow(logBase, floor((logBase == 10 ? log10 : log2)(scaleMin)));
|
|
1018
|
+
if (logBase == 10) foundIncr = numIncrs[closestIdx(foundIncr, numIncrs)];
|
|
1019
|
+
let split = scaleMin;
|
|
1020
|
+
let nextMagIncr = foundIncr * logBase;
|
|
1021
|
+
if (logBase == 10) nextMagIncr = numIncrs[closestIdx(nextMagIncr, numIncrs)];
|
|
1022
|
+
do {
|
|
1023
|
+
splits.push(split);
|
|
1024
|
+
split = split + foundIncr;
|
|
1025
|
+
if (logBase == 10 && !fixedDec.has(split)) split = roundDec(split, fixedDec.get(foundIncr));
|
|
1026
|
+
if (split >= nextMagIncr) {
|
|
1027
|
+
foundIncr = split;
|
|
1028
|
+
nextMagIncr = foundIncr * logBase;
|
|
1029
|
+
if (logBase == 10) nextMagIncr = numIncrs[closestIdx(nextMagIncr, numIncrs)];
|
|
1030
|
+
}
|
|
1031
|
+
} while (split <= scaleMax);
|
|
1032
|
+
return splits;
|
|
1033
|
+
}
|
|
1034
|
+
function asinhAxisSplits(self, axisIdx, scaleMin, scaleMax, foundIncr, foundSpace, forceMin) {
|
|
1035
|
+
let linthresh = self.scales[self.axes[axisIdx].scale].asinh;
|
|
1036
|
+
let posSplits = scaleMax > linthresh ? logAxisSplits(self, axisIdx, max(linthresh, scaleMin), scaleMax, foundIncr) : [linthresh];
|
|
1037
|
+
let zero = scaleMax >= 0 && scaleMin <= 0 ? [0] : [];
|
|
1038
|
+
return (scaleMin < -linthresh ? logAxisSplits(self, axisIdx, max(linthresh, -scaleMax), -scaleMin, foundIncr) : [linthresh]).reverse().map((v) => -v).concat(zero, posSplits);
|
|
1039
|
+
}
|
|
1040
|
+
var RE_ALL = /./;
|
|
1041
|
+
var RE_12357 = /[12357]/;
|
|
1042
|
+
var RE_125 = /[125]/;
|
|
1043
|
+
var RE_1 = /1/;
|
|
1044
|
+
var _filt = (splits, distr, re, keepMod) => splits.map((v, i) => distr == 4 && v == 0 || i % keepMod == 0 && re.test(v.toExponential()[v < 0 ? 1 : 0]) ? v : null);
|
|
1045
|
+
function log10AxisValsFilt(self, splits, axisIdx, foundSpace, foundIncr) {
|
|
1046
|
+
let axis = self.axes[axisIdx];
|
|
1047
|
+
let scaleKey = axis.scale;
|
|
1048
|
+
let sc = self.scales[scaleKey];
|
|
1049
|
+
let valToPos = self.valToPos;
|
|
1050
|
+
let minSpace = axis._space;
|
|
1051
|
+
let _10 = valToPos(10, scaleKey);
|
|
1052
|
+
let re = valToPos(9, scaleKey) - _10 >= minSpace ? RE_ALL : valToPos(7, scaleKey) - _10 >= minSpace ? RE_12357 : valToPos(5, scaleKey) - _10 >= minSpace ? RE_125 : RE_1;
|
|
1053
|
+
if (re == RE_1) {
|
|
1054
|
+
let magSpace = abs(valToPos(1, scaleKey) - _10);
|
|
1055
|
+
if (magSpace < minSpace) return _filt(splits.slice().reverse(), sc.distr, re, ceil(minSpace / magSpace)).reverse();
|
|
1056
|
+
}
|
|
1057
|
+
return _filt(splits, sc.distr, re, 1);
|
|
1058
|
+
}
|
|
1059
|
+
function log2AxisValsFilt(self, splits, axisIdx, foundSpace, foundIncr) {
|
|
1060
|
+
let axis = self.axes[axisIdx];
|
|
1061
|
+
let scaleKey = axis.scale;
|
|
1062
|
+
let minSpace = axis._space;
|
|
1063
|
+
let valToPos = self.valToPos;
|
|
1064
|
+
let magSpace = abs(valToPos(1, scaleKey) - valToPos(2, scaleKey));
|
|
1065
|
+
if (magSpace < minSpace) return _filt(splits.slice().reverse(), 3, RE_ALL, ceil(minSpace / magSpace)).reverse();
|
|
1066
|
+
return splits;
|
|
1067
|
+
}
|
|
1068
|
+
function numSeriesVal(self, val, seriesIdx, dataIdx) {
|
|
1069
|
+
return dataIdx == null ? LEGEND_DISP : val == null ? "" : fmtNum(val);
|
|
1070
|
+
}
|
|
1071
|
+
var yAxisOpts = {
|
|
1072
|
+
show: true,
|
|
1073
|
+
scale: "y",
|
|
1074
|
+
stroke: hexBlack,
|
|
1075
|
+
space: 30,
|
|
1076
|
+
gap: 5,
|
|
1077
|
+
alignTo: 1,
|
|
1078
|
+
size: 50,
|
|
1079
|
+
labelGap: 0,
|
|
1080
|
+
labelSize: 30,
|
|
1081
|
+
labelFont,
|
|
1082
|
+
side: 3,
|
|
1083
|
+
grid,
|
|
1084
|
+
ticks,
|
|
1085
|
+
border,
|
|
1086
|
+
font,
|
|
1087
|
+
lineGap,
|
|
1088
|
+
rotate: 0
|
|
1089
|
+
};
|
|
1090
|
+
function ptDia(width, mult) {
|
|
1091
|
+
return roundDec((3 + (width || 1) * 2) * mult, 3);
|
|
1092
|
+
}
|
|
1093
|
+
function seriesPointsShow(self, si) {
|
|
1094
|
+
let { scale, idxs } = self.series[0];
|
|
1095
|
+
let xData = self._data[0];
|
|
1096
|
+
let p0 = self.valToPos(xData[idxs[0]], scale, true);
|
|
1097
|
+
let maxPts = abs(self.valToPos(xData[idxs[1]], scale, true) - p0) / (self.series[si].points.space * pxRatio);
|
|
1098
|
+
return idxs[1] - idxs[0] <= maxPts;
|
|
1099
|
+
}
|
|
1100
|
+
var facet = {
|
|
1101
|
+
scale: null,
|
|
1102
|
+
auto: true,
|
|
1103
|
+
sorted: 0,
|
|
1104
|
+
min: inf,
|
|
1105
|
+
max: -Infinity
|
|
1106
|
+
};
|
|
1107
|
+
var gaps = (self, seriesIdx, idx0, idx1, nullGaps) => nullGaps;
|
|
1108
|
+
var xySeriesOpts = {
|
|
1109
|
+
show: true,
|
|
1110
|
+
auto: true,
|
|
1111
|
+
sorted: 0,
|
|
1112
|
+
gaps,
|
|
1113
|
+
alpha: 1,
|
|
1114
|
+
facets: [assign({}, facet, { scale: "x" }), assign({}, facet, { scale: "y" })]
|
|
1115
|
+
};
|
|
1116
|
+
var ySeriesOpts = {
|
|
1117
|
+
scale: "y",
|
|
1118
|
+
auto: true,
|
|
1119
|
+
sorted: 0,
|
|
1120
|
+
show: true,
|
|
1121
|
+
spanGaps: false,
|
|
1122
|
+
gaps,
|
|
1123
|
+
alpha: 1,
|
|
1124
|
+
points: {
|
|
1125
|
+
show: seriesPointsShow,
|
|
1126
|
+
filter: null
|
|
1127
|
+
},
|
|
1128
|
+
values: null,
|
|
1129
|
+
min: inf,
|
|
1130
|
+
max: -Infinity,
|
|
1131
|
+
idxs: [],
|
|
1132
|
+
path: null,
|
|
1133
|
+
clip: null
|
|
1134
|
+
};
|
|
1135
|
+
function clampScale(self, val, scaleMin, scaleMax, scaleKey) {
|
|
1136
|
+
return scaleMin / 10;
|
|
1137
|
+
}
|
|
1138
|
+
var xScaleOpts = {
|
|
1139
|
+
time: FEAT_TIME,
|
|
1140
|
+
auto: true,
|
|
1141
|
+
distr: 1,
|
|
1142
|
+
log: 10,
|
|
1143
|
+
asinh: 1,
|
|
1144
|
+
min: null,
|
|
1145
|
+
max: null,
|
|
1146
|
+
dir: 1,
|
|
1147
|
+
ori: 0
|
|
1148
|
+
};
|
|
1149
|
+
var yScaleOpts = assign({}, xScaleOpts, {
|
|
1150
|
+
time: false,
|
|
1151
|
+
ori: 1
|
|
1152
|
+
});
|
|
1153
|
+
var syncs = {};
|
|
1154
|
+
function _sync(key, opts) {
|
|
1155
|
+
let s = syncs[key];
|
|
1156
|
+
if (!s) {
|
|
1157
|
+
s = {
|
|
1158
|
+
key,
|
|
1159
|
+
plots: [],
|
|
1160
|
+
sub(plot) {
|
|
1161
|
+
s.plots.push(plot);
|
|
1162
|
+
},
|
|
1163
|
+
unsub(plot) {
|
|
1164
|
+
s.plots = s.plots.filter((c) => c != plot);
|
|
1165
|
+
},
|
|
1166
|
+
pub(type, self, x, y, w, h, i) {
|
|
1167
|
+
for (let j = 0; j < s.plots.length; j++) s.plots[j] != self && s.plots[j].pub(type, self, x, y, w, h, i);
|
|
1168
|
+
}
|
|
1169
|
+
};
|
|
1170
|
+
if (key != null) syncs[key] = s;
|
|
1171
|
+
}
|
|
1172
|
+
return s;
|
|
1173
|
+
}
|
|
1174
|
+
var BAND_CLIP_FILL = 1;
|
|
1175
|
+
var BAND_CLIP_STROKE = 2;
|
|
1176
|
+
function orient(u, seriesIdx, cb) {
|
|
1177
|
+
const mode = u.mode;
|
|
1178
|
+
const series = u.series[seriesIdx];
|
|
1179
|
+
const data = mode == 2 ? u._data[seriesIdx] : u._data;
|
|
1180
|
+
const scales = u.scales;
|
|
1181
|
+
const bbox = u.bbox;
|
|
1182
|
+
let dx = data[0], dy = mode == 2 ? data[1] : data[seriesIdx], sx = mode == 2 ? scales[series.facets[0].scale] : scales[u.series[0].scale], sy = mode == 2 ? scales[series.facets[1].scale] : scales[series.scale], l = bbox.left, t = bbox.top, w = bbox.width, h = bbox.height, H = u.valToPosH, V = u.valToPosV;
|
|
1183
|
+
return sx.ori == 0 ? cb(series, dx, dy, sx, sy, H, V, l, t, w, h, moveToH, lineToH, rectH, arcH, bezierCurveToH) : cb(series, dx, dy, sx, sy, V, H, t, l, h, w, moveToV, lineToV, rectV, arcV, bezierCurveToV);
|
|
1184
|
+
}
|
|
1185
|
+
function bandFillClipDirs(self, seriesIdx) {
|
|
1186
|
+
let fillDir = 0;
|
|
1187
|
+
let clipDirs = 0;
|
|
1188
|
+
let bands = ifNull(self.bands, EMPTY_ARR);
|
|
1189
|
+
for (let i = 0; i < bands.length; i++) {
|
|
1190
|
+
let b = bands[i];
|
|
1191
|
+
if (b.series[0] == seriesIdx) fillDir = b.dir;
|
|
1192
|
+
else if (b.series[1] == seriesIdx) if (b.dir == 1) clipDirs |= 1;
|
|
1193
|
+
else clipDirs |= 2;
|
|
1194
|
+
}
|
|
1195
|
+
return [fillDir, clipDirs == 1 ? -1 : clipDirs == 2 ? 1 : clipDirs == 3 ? 2 : 0];
|
|
1196
|
+
}
|
|
1197
|
+
function seriesFillTo(self, seriesIdx, dataMin, dataMax, bandFillDir) {
|
|
1198
|
+
let mode = self.mode;
|
|
1199
|
+
let series = self.series[seriesIdx];
|
|
1200
|
+
let scaleKey = mode == 2 ? series.facets[1].scale : series.scale;
|
|
1201
|
+
let scale = self.scales[scaleKey];
|
|
1202
|
+
return bandFillDir == -1 ? scale.min : bandFillDir == 1 ? scale.max : scale.distr == 3 ? scale.dir == 1 ? scale.min : scale.max : 0;
|
|
1203
|
+
}
|
|
1204
|
+
function clipBandLine(self, seriesIdx, idx0, idx1, strokePath, clipDir) {
|
|
1205
|
+
return orient(self, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
|
|
1206
|
+
let pxRound = series.pxRound;
|
|
1207
|
+
const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1);
|
|
1208
|
+
const lineTo = scaleX.ori == 0 ? lineToH : lineToV;
|
|
1209
|
+
let frIdx, toIdx;
|
|
1210
|
+
if (dir == 1) {
|
|
1211
|
+
frIdx = idx0;
|
|
1212
|
+
toIdx = idx1;
|
|
1213
|
+
} else {
|
|
1214
|
+
frIdx = idx1;
|
|
1215
|
+
toIdx = idx0;
|
|
1216
|
+
}
|
|
1217
|
+
let x0 = pxRound(valToPosX(dataX[frIdx], scaleX, xDim, xOff));
|
|
1218
|
+
let y0 = pxRound(valToPosY(dataY[frIdx], scaleY, yDim, yOff));
|
|
1219
|
+
let x1 = pxRound(valToPosX(dataX[toIdx], scaleX, xDim, xOff));
|
|
1220
|
+
let yLimit = pxRound(valToPosY(clipDir == 1 ? scaleY.max : scaleY.min, scaleY, yDim, yOff));
|
|
1221
|
+
let clip = new Path2D(strokePath);
|
|
1222
|
+
lineTo(clip, x1, yLimit);
|
|
1223
|
+
lineTo(clip, x0, yLimit);
|
|
1224
|
+
lineTo(clip, x0, y0);
|
|
1225
|
+
return clip;
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
1228
|
+
function clipGaps(gaps, ori, plotLft, plotTop, plotWid, plotHgt) {
|
|
1229
|
+
let clip = null;
|
|
1230
|
+
if (gaps.length > 0) {
|
|
1231
|
+
clip = new Path2D();
|
|
1232
|
+
const rect = ori == 0 ? rectH : rectV;
|
|
1233
|
+
let prevGapEnd = plotLft;
|
|
1234
|
+
for (let i = 0; i < gaps.length; i++) {
|
|
1235
|
+
let g = gaps[i];
|
|
1236
|
+
if (g[1] > g[0]) {
|
|
1237
|
+
let w = g[0] - prevGapEnd;
|
|
1238
|
+
w > 0 && rect(clip, prevGapEnd, plotTop, w, plotTop + plotHgt);
|
|
1239
|
+
prevGapEnd = g[1];
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
let w = plotLft + plotWid - prevGapEnd;
|
|
1243
|
+
let maxStrokeWidth = 10;
|
|
1244
|
+
w > 0 && rect(clip, prevGapEnd, plotTop - maxStrokeWidth / 2, w, plotTop + plotHgt + maxStrokeWidth);
|
|
1245
|
+
}
|
|
1246
|
+
return clip;
|
|
1247
|
+
}
|
|
1248
|
+
function addGap(gaps, fromX, toX) {
|
|
1249
|
+
let prevGap = gaps[gaps.length - 1];
|
|
1250
|
+
if (prevGap && prevGap[0] == fromX) prevGap[1] = toX;
|
|
1251
|
+
else gaps.push([fromX, toX]);
|
|
1252
|
+
}
|
|
1253
|
+
function findGaps(xs, ys, idx0, idx1, dir, pixelForX, align) {
|
|
1254
|
+
let gaps = [];
|
|
1255
|
+
let len = xs.length;
|
|
1256
|
+
for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) if (ys[i] === null) {
|
|
1257
|
+
let fr = i, to = i;
|
|
1258
|
+
if (dir == 1) while (++i <= idx1 && ys[i] === null) to = i;
|
|
1259
|
+
else while (--i >= idx0 && ys[i] === null) to = i;
|
|
1260
|
+
let frPx = pixelForX(xs[fr]);
|
|
1261
|
+
let toPx = to == fr ? frPx : pixelForX(xs[to]);
|
|
1262
|
+
let fri2 = fr - dir;
|
|
1263
|
+
frPx = align <= 0 && fri2 >= 0 && fri2 < len ? pixelForX(xs[fri2]) : frPx;
|
|
1264
|
+
let toi2 = to + dir;
|
|
1265
|
+
toPx = align >= 0 && toi2 >= 0 && toi2 < len ? pixelForX(xs[toi2]) : toPx;
|
|
1266
|
+
if (toPx >= frPx) gaps.push([frPx, toPx]);
|
|
1267
|
+
}
|
|
1268
|
+
return gaps;
|
|
1269
|
+
}
|
|
1270
|
+
function pxRoundGen(pxAlign) {
|
|
1271
|
+
return pxAlign == 0 ? retArg0 : pxAlign == 1 ? round : (v) => incrRound(v, pxAlign);
|
|
1272
|
+
}
|
|
1273
|
+
function rect(ori) {
|
|
1274
|
+
let moveTo = ori == 0 ? moveToH : moveToV;
|
|
1275
|
+
let arcTo = ori == 0 ? (p, x1, y1, x2, y2, r) => {
|
|
1276
|
+
p.arcTo(x1, y1, x2, y2, r);
|
|
1277
|
+
} : (p, y1, x1, y2, x2, r) => {
|
|
1278
|
+
p.arcTo(x1, y1, x2, y2, r);
|
|
1279
|
+
};
|
|
1280
|
+
let rect = ori == 0 ? (p, x, y, w, h) => {
|
|
1281
|
+
p.rect(x, y, w, h);
|
|
1282
|
+
} : (p, y, x, h, w) => {
|
|
1283
|
+
p.rect(x, y, w, h);
|
|
1284
|
+
};
|
|
1285
|
+
return (p, x, y, w, h, endRad = 0, baseRad = 0) => {
|
|
1286
|
+
if (endRad == 0 && baseRad == 0) rect(p, x, y, w, h);
|
|
1287
|
+
else {
|
|
1288
|
+
endRad = min(endRad, w / 2, h / 2);
|
|
1289
|
+
baseRad = min(baseRad, w / 2, h / 2);
|
|
1290
|
+
moveTo(p, x + endRad, y);
|
|
1291
|
+
arcTo(p, x + w, y, x + w, y + h, endRad);
|
|
1292
|
+
arcTo(p, x + w, y + h, x, y + h, baseRad);
|
|
1293
|
+
arcTo(p, x, y + h, x, y, baseRad);
|
|
1294
|
+
arcTo(p, x, y, x + w, y, endRad);
|
|
1295
|
+
p.closePath();
|
|
1296
|
+
}
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
var moveToH = (p, x, y) => {
|
|
1300
|
+
p.moveTo(x, y);
|
|
1301
|
+
};
|
|
1302
|
+
var moveToV = (p, y, x) => {
|
|
1303
|
+
p.moveTo(x, y);
|
|
1304
|
+
};
|
|
1305
|
+
var lineToH = (p, x, y) => {
|
|
1306
|
+
p.lineTo(x, y);
|
|
1307
|
+
};
|
|
1308
|
+
var lineToV = (p, y, x) => {
|
|
1309
|
+
p.lineTo(x, y);
|
|
1310
|
+
};
|
|
1311
|
+
var rectH = rect(0);
|
|
1312
|
+
var rectV = rect(1);
|
|
1313
|
+
var arcH = (p, x, y, r, startAngle, endAngle) => {
|
|
1314
|
+
p.arc(x, y, r, startAngle, endAngle);
|
|
1315
|
+
};
|
|
1316
|
+
var arcV = (p, y, x, r, startAngle, endAngle) => {
|
|
1317
|
+
p.arc(x, y, r, startAngle, endAngle);
|
|
1318
|
+
};
|
|
1319
|
+
var bezierCurveToH = (p, bp1x, bp1y, bp2x, bp2y, p2x, p2y) => {
|
|
1320
|
+
p.bezierCurveTo(bp1x, bp1y, bp2x, bp2y, p2x, p2y);
|
|
1321
|
+
};
|
|
1322
|
+
var bezierCurveToV = (p, bp1y, bp1x, bp2y, bp2x, p2y, p2x) => {
|
|
1323
|
+
p.bezierCurveTo(bp1x, bp1y, bp2x, bp2y, p2x, p2y);
|
|
1324
|
+
};
|
|
1325
|
+
function points(opts) {
|
|
1326
|
+
return (u, seriesIdx, idx0, idx1, filtIdxs) => {
|
|
1327
|
+
return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
|
|
1328
|
+
let { pxRound, points } = series;
|
|
1329
|
+
let moveTo, arc;
|
|
1330
|
+
if (scaleX.ori == 0) {
|
|
1331
|
+
moveTo = moveToH;
|
|
1332
|
+
arc = arcH;
|
|
1333
|
+
} else {
|
|
1334
|
+
moveTo = moveToV;
|
|
1335
|
+
arc = arcV;
|
|
1336
|
+
}
|
|
1337
|
+
const width = roundDec(points.width * pxRatio, 3);
|
|
1338
|
+
let rad = (points.size - points.width) / 2 * pxRatio;
|
|
1339
|
+
let dia = roundDec(rad * 2, 3);
|
|
1340
|
+
let fill = new Path2D();
|
|
1341
|
+
let clip = new Path2D();
|
|
1342
|
+
let { left: lft, top, width: wid, height: hgt } = u.bbox;
|
|
1343
|
+
rectH(clip, lft - dia, top - dia, wid + dia * 2, hgt + dia * 2);
|
|
1344
|
+
const drawPoint = (pi) => {
|
|
1345
|
+
if (dataY[pi] != null) {
|
|
1346
|
+
let x = pxRound(valToPosX(dataX[pi], scaleX, xDim, xOff));
|
|
1347
|
+
let y = pxRound(valToPosY(dataY[pi], scaleY, yDim, yOff));
|
|
1348
|
+
moveTo(fill, x + rad, y);
|
|
1349
|
+
arc(fill, x, y, rad, 0, PI * 2);
|
|
1350
|
+
}
|
|
1351
|
+
};
|
|
1352
|
+
if (filtIdxs) filtIdxs.forEach(drawPoint);
|
|
1353
|
+
else for (let pi = idx0; pi <= idx1; pi++) drawPoint(pi);
|
|
1354
|
+
return {
|
|
1355
|
+
stroke: width > 0 ? fill : null,
|
|
1356
|
+
fill,
|
|
1357
|
+
clip,
|
|
1358
|
+
flags: 3
|
|
1359
|
+
};
|
|
1360
|
+
});
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
function _drawAcc(lineTo) {
|
|
1364
|
+
return (stroke, accX, minY, maxY, inY, outY) => {
|
|
1365
|
+
if (minY != maxY) {
|
|
1366
|
+
if (inY != minY && outY != minY) lineTo(stroke, accX, minY);
|
|
1367
|
+
if (inY != maxY && outY != maxY) lineTo(stroke, accX, maxY);
|
|
1368
|
+
lineTo(stroke, accX, outY);
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
var drawAccH = _drawAcc(lineToH);
|
|
1373
|
+
var drawAccV = _drawAcc(lineToV);
|
|
1374
|
+
function linear(opts) {
|
|
1375
|
+
const alignGaps = ifNull(opts?.alignGaps, 0);
|
|
1376
|
+
return (u, seriesIdx, idx0, idx1) => {
|
|
1377
|
+
return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
|
|
1378
|
+
[idx0, idx1] = nonNullIdxs(dataY, idx0, idx1);
|
|
1379
|
+
let pxRound = series.pxRound;
|
|
1380
|
+
let pixelForX = (val) => pxRound(valToPosX(val, scaleX, xDim, xOff));
|
|
1381
|
+
let pixelForY = (val) => pxRound(valToPosY(val, scaleY, yDim, yOff));
|
|
1382
|
+
let lineTo, drawAcc;
|
|
1383
|
+
if (scaleX.ori == 0) {
|
|
1384
|
+
lineTo = lineToH;
|
|
1385
|
+
drawAcc = drawAccH;
|
|
1386
|
+
} else {
|
|
1387
|
+
lineTo = lineToV;
|
|
1388
|
+
drawAcc = drawAccV;
|
|
1389
|
+
}
|
|
1390
|
+
const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1);
|
|
1391
|
+
const _paths = {
|
|
1392
|
+
stroke: new Path2D(),
|
|
1393
|
+
fill: null,
|
|
1394
|
+
clip: null,
|
|
1395
|
+
band: null,
|
|
1396
|
+
gaps: null,
|
|
1397
|
+
flags: BAND_CLIP_FILL
|
|
1398
|
+
};
|
|
1399
|
+
const stroke = _paths.stroke;
|
|
1400
|
+
let hasGap = false;
|
|
1401
|
+
if (idx1 - idx0 >= xDim * 4) {
|
|
1402
|
+
let xForPixel = (pos) => u.posToVal(pos, scaleX.key, true);
|
|
1403
|
+
let minY = null, maxY = null, inY, outY, drawnAtX;
|
|
1404
|
+
let accX = pixelForX(dataX[dir == 1 ? idx0 : idx1]);
|
|
1405
|
+
let idx0px = pixelForX(dataX[idx0]);
|
|
1406
|
+
let idx1px = pixelForX(dataX[idx1]);
|
|
1407
|
+
let nextAccXVal = xForPixel(dir == 1 ? idx0px + 1 : idx1px - 1);
|
|
1408
|
+
for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) {
|
|
1409
|
+
let xVal = dataX[i];
|
|
1410
|
+
let x = (dir == 1 ? xVal < nextAccXVal : xVal > nextAccXVal) ? accX : pixelForX(xVal);
|
|
1411
|
+
let yVal = dataY[i];
|
|
1412
|
+
if (x == accX) {
|
|
1413
|
+
if (yVal != null) {
|
|
1414
|
+
outY = yVal;
|
|
1415
|
+
if (minY == null) {
|
|
1416
|
+
lineTo(stroke, x, pixelForY(outY));
|
|
1417
|
+
inY = minY = maxY = outY;
|
|
1418
|
+
} else if (outY < minY) minY = outY;
|
|
1419
|
+
else if (outY > maxY) maxY = outY;
|
|
1420
|
+
} else if (yVal === null) hasGap = true;
|
|
1421
|
+
} else {
|
|
1422
|
+
if (minY != null) drawAcc(stroke, accX, pixelForY(minY), pixelForY(maxY), pixelForY(inY), pixelForY(outY));
|
|
1423
|
+
if (yVal != null) {
|
|
1424
|
+
outY = yVal;
|
|
1425
|
+
lineTo(stroke, x, pixelForY(outY));
|
|
1426
|
+
minY = maxY = inY = outY;
|
|
1427
|
+
} else {
|
|
1428
|
+
minY = maxY = null;
|
|
1429
|
+
if (yVal === null) hasGap = true;
|
|
1430
|
+
}
|
|
1431
|
+
accX = x;
|
|
1432
|
+
nextAccXVal = xForPixel(accX + dir);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
if (minY != null && minY != maxY && drawnAtX != accX) drawAcc(stroke, accX, pixelForY(minY), pixelForY(maxY), pixelForY(inY), pixelForY(outY));
|
|
1436
|
+
} else for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) {
|
|
1437
|
+
let yVal = dataY[i];
|
|
1438
|
+
if (yVal === null) hasGap = true;
|
|
1439
|
+
else if (yVal != null) lineTo(stroke, pixelForX(dataX[i]), pixelForY(yVal));
|
|
1440
|
+
}
|
|
1441
|
+
let [bandFillDir, bandClipDir] = bandFillClipDirs(u, seriesIdx);
|
|
1442
|
+
if (series.fill != null || bandFillDir != 0) {
|
|
1443
|
+
let fill = _paths.fill = new Path2D(stroke);
|
|
1444
|
+
let fillToY = pixelForY(series.fillTo(u, seriesIdx, series.min, series.max, bandFillDir));
|
|
1445
|
+
let frX = pixelForX(dataX[idx0]);
|
|
1446
|
+
let toX = pixelForX(dataX[idx1]);
|
|
1447
|
+
if (dir == -1) [toX, frX] = [frX, toX];
|
|
1448
|
+
lineTo(fill, toX, fillToY);
|
|
1449
|
+
lineTo(fill, frX, fillToY);
|
|
1450
|
+
}
|
|
1451
|
+
if (!series.spanGaps) {
|
|
1452
|
+
let gaps = [];
|
|
1453
|
+
hasGap && gaps.push(...findGaps(dataX, dataY, idx0, idx1, dir, pixelForX, alignGaps));
|
|
1454
|
+
_paths.gaps = gaps = series.gaps(u, seriesIdx, idx0, idx1, gaps);
|
|
1455
|
+
_paths.clip = clipGaps(gaps, scaleX.ori, xOff, yOff, xDim, yDim);
|
|
1456
|
+
}
|
|
1457
|
+
if (bandClipDir != 0) _paths.band = bandClipDir == 2 ? [clipBandLine(u, seriesIdx, idx0, idx1, stroke, -1), clipBandLine(u, seriesIdx, idx0, idx1, stroke, 1)] : clipBandLine(u, seriesIdx, idx0, idx1, stroke, bandClipDir);
|
|
1458
|
+
return _paths;
|
|
1459
|
+
});
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function stepped(opts) {
|
|
1463
|
+
const align = ifNull(opts.align, 1);
|
|
1464
|
+
const ascDesc = ifNull(opts.ascDesc, false);
|
|
1465
|
+
const alignGaps = ifNull(opts.alignGaps, 0);
|
|
1466
|
+
const extend = ifNull(opts.extend, false);
|
|
1467
|
+
return (u, seriesIdx, idx0, idx1) => {
|
|
1468
|
+
return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
|
|
1469
|
+
[idx0, idx1] = nonNullIdxs(dataY, idx0, idx1);
|
|
1470
|
+
let pxRound = series.pxRound;
|
|
1471
|
+
let { left, width } = u.bbox;
|
|
1472
|
+
let pixelForX = (val) => pxRound(valToPosX(val, scaleX, xDim, xOff));
|
|
1473
|
+
let pixelForY = (val) => pxRound(valToPosY(val, scaleY, yDim, yOff));
|
|
1474
|
+
let lineTo = scaleX.ori == 0 ? lineToH : lineToV;
|
|
1475
|
+
const _paths = {
|
|
1476
|
+
stroke: new Path2D(),
|
|
1477
|
+
fill: null,
|
|
1478
|
+
clip: null,
|
|
1479
|
+
band: null,
|
|
1480
|
+
gaps: null,
|
|
1481
|
+
flags: BAND_CLIP_FILL
|
|
1482
|
+
};
|
|
1483
|
+
const stroke = _paths.stroke;
|
|
1484
|
+
const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1);
|
|
1485
|
+
let prevYPos = pixelForY(dataY[dir == 1 ? idx0 : idx1]);
|
|
1486
|
+
let firstXPos = pixelForX(dataX[dir == 1 ? idx0 : idx1]);
|
|
1487
|
+
let prevXPos = firstXPos;
|
|
1488
|
+
let firstXPosExt = firstXPos;
|
|
1489
|
+
if (extend && align == -1) {
|
|
1490
|
+
firstXPosExt = left;
|
|
1491
|
+
lineTo(stroke, firstXPosExt, prevYPos);
|
|
1492
|
+
}
|
|
1493
|
+
lineTo(stroke, firstXPos, prevYPos);
|
|
1494
|
+
for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) {
|
|
1495
|
+
let yVal1 = dataY[i];
|
|
1496
|
+
if (yVal1 == null) continue;
|
|
1497
|
+
let x1 = pixelForX(dataX[i]);
|
|
1498
|
+
let y1 = pixelForY(yVal1);
|
|
1499
|
+
if (align == 1) lineTo(stroke, x1, prevYPos);
|
|
1500
|
+
else lineTo(stroke, prevXPos, y1);
|
|
1501
|
+
lineTo(stroke, x1, y1);
|
|
1502
|
+
prevYPos = y1;
|
|
1503
|
+
prevXPos = x1;
|
|
1504
|
+
}
|
|
1505
|
+
let prevXPosExt = prevXPos;
|
|
1506
|
+
if (extend && align == 1) {
|
|
1507
|
+
prevXPosExt = left + width;
|
|
1508
|
+
lineTo(stroke, prevXPosExt, prevYPos);
|
|
1509
|
+
}
|
|
1510
|
+
let [bandFillDir, bandClipDir] = bandFillClipDirs(u, seriesIdx);
|
|
1511
|
+
if (series.fill != null || bandFillDir != 0) {
|
|
1512
|
+
let fill = _paths.fill = new Path2D(stroke);
|
|
1513
|
+
let fillToY = pixelForY(series.fillTo(u, seriesIdx, series.min, series.max, bandFillDir));
|
|
1514
|
+
lineTo(fill, prevXPosExt, fillToY);
|
|
1515
|
+
lineTo(fill, firstXPosExt, fillToY);
|
|
1516
|
+
}
|
|
1517
|
+
if (!series.spanGaps) {
|
|
1518
|
+
let gaps = [];
|
|
1519
|
+
gaps.push(...findGaps(dataX, dataY, idx0, idx1, dir, pixelForX, alignGaps));
|
|
1520
|
+
let halfStroke = series.width * pxRatio / 2;
|
|
1521
|
+
let startsOffset = ascDesc || align == 1 ? halfStroke : -halfStroke;
|
|
1522
|
+
let endsOffset = ascDesc || align == -1 ? -halfStroke : halfStroke;
|
|
1523
|
+
gaps.forEach((g) => {
|
|
1524
|
+
g[0] += startsOffset;
|
|
1525
|
+
g[1] += endsOffset;
|
|
1526
|
+
});
|
|
1527
|
+
_paths.gaps = gaps = series.gaps(u, seriesIdx, idx0, idx1, gaps);
|
|
1528
|
+
_paths.clip = clipGaps(gaps, scaleX.ori, xOff, yOff, xDim, yDim);
|
|
1529
|
+
}
|
|
1530
|
+
if (bandClipDir != 0) _paths.band = bandClipDir == 2 ? [clipBandLine(u, seriesIdx, idx0, idx1, stroke, -1), clipBandLine(u, seriesIdx, idx0, idx1, stroke, 1)] : clipBandLine(u, seriesIdx, idx0, idx1, stroke, bandClipDir);
|
|
1531
|
+
return _paths;
|
|
1532
|
+
});
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
function findColWidth(dataX, dataY, valToPosX, scaleX, xDim, xOff, colWid = inf) {
|
|
1536
|
+
if (dataX.length > 1) {
|
|
1537
|
+
let prevIdx = null;
|
|
1538
|
+
for (let i = 0, minDelta = Infinity; i < dataX.length; i++) if (dataY[i] !== void 0) {
|
|
1539
|
+
if (prevIdx != null) {
|
|
1540
|
+
let delta = abs(dataX[i] - dataX[prevIdx]);
|
|
1541
|
+
if (delta < minDelta) {
|
|
1542
|
+
minDelta = delta;
|
|
1543
|
+
colWid = abs(valToPosX(dataX[i], scaleX, xDim, xOff) - valToPosX(dataX[prevIdx], scaleX, xDim, xOff));
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
prevIdx = i;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
return colWid;
|
|
1550
|
+
}
|
|
1551
|
+
function bars(opts) {
|
|
1552
|
+
opts = opts || EMPTY_OBJ;
|
|
1553
|
+
const size = ifNull(opts.size, [
|
|
1554
|
+
.6,
|
|
1555
|
+
inf,
|
|
1556
|
+
1
|
|
1557
|
+
]);
|
|
1558
|
+
const align = opts.align || 0;
|
|
1559
|
+
const _extraGap = opts.gap || 0;
|
|
1560
|
+
let ro = opts.radius;
|
|
1561
|
+
ro = ro == null ? [0, 0] : typeof ro == "number" ? [ro, 0] : ro;
|
|
1562
|
+
const radiusFn = fnOrSelf(ro);
|
|
1563
|
+
const gapFactor = 1 - size[0];
|
|
1564
|
+
const _maxWidth = ifNull(size[1], inf);
|
|
1565
|
+
const _minWidth = ifNull(size[2], 1);
|
|
1566
|
+
const disp = ifNull(opts.disp, EMPTY_OBJ);
|
|
1567
|
+
const _each = ifNull(opts.each, (_) => {});
|
|
1568
|
+
const { fill: dispFills, stroke: dispStrokes } = disp;
|
|
1569
|
+
return (u, seriesIdx, idx0, idx1) => {
|
|
1570
|
+
return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
|
|
1571
|
+
let pxRound = series.pxRound;
|
|
1572
|
+
let _align = align;
|
|
1573
|
+
let extraGap = _extraGap * pxRatio;
|
|
1574
|
+
let maxWidth = _maxWidth * pxRatio;
|
|
1575
|
+
let minWidth = _minWidth * pxRatio;
|
|
1576
|
+
let valRadius, baseRadius;
|
|
1577
|
+
if (scaleX.ori == 0) [valRadius, baseRadius] = radiusFn(u, seriesIdx);
|
|
1578
|
+
else [baseRadius, valRadius] = radiusFn(u, seriesIdx);
|
|
1579
|
+
const _dirX = scaleX.dir * (scaleX.ori == 0 ? 1 : -1);
|
|
1580
|
+
let rect = scaleX.ori == 0 ? rectH : rectV;
|
|
1581
|
+
let each = scaleX.ori == 0 ? _each : (u, seriesIdx, i, top, lft, hgt, wid) => {
|
|
1582
|
+
_each(u, seriesIdx, i, lft, top, wid, hgt);
|
|
1583
|
+
};
|
|
1584
|
+
let band = ifNull(u.bands, EMPTY_ARR).find((b) => b.series[0] == seriesIdx);
|
|
1585
|
+
let fillDir = band != null ? band.dir : 0;
|
|
1586
|
+
let fillTo = series.fillTo(u, seriesIdx, series.min, series.max, fillDir);
|
|
1587
|
+
let fillToY = pxRound(valToPosY(fillTo, scaleY, yDim, yOff));
|
|
1588
|
+
let xShift, barWid, fullGap, colWid = xDim;
|
|
1589
|
+
let strokeWidth = pxRound(series.width * pxRatio);
|
|
1590
|
+
let multiPath = false;
|
|
1591
|
+
let fillColors = null;
|
|
1592
|
+
let fillPaths = null;
|
|
1593
|
+
let strokeColors = null;
|
|
1594
|
+
let strokePaths = null;
|
|
1595
|
+
if (dispFills != null && (strokeWidth == 0 || dispStrokes != null)) {
|
|
1596
|
+
multiPath = true;
|
|
1597
|
+
fillColors = dispFills.values(u, seriesIdx, idx0, idx1);
|
|
1598
|
+
fillPaths = /* @__PURE__ */ new Map();
|
|
1599
|
+
new Set(fillColors).forEach((color) => {
|
|
1600
|
+
if (color != null) fillPaths.set(color, new Path2D());
|
|
1601
|
+
});
|
|
1602
|
+
if (strokeWidth > 0) {
|
|
1603
|
+
strokeColors = dispStrokes.values(u, seriesIdx, idx0, idx1);
|
|
1604
|
+
strokePaths = /* @__PURE__ */ new Map();
|
|
1605
|
+
new Set(strokeColors).forEach((color) => {
|
|
1606
|
+
if (color != null) strokePaths.set(color, new Path2D());
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
let { x0, size } = disp;
|
|
1611
|
+
if (x0 != null && size != null) {
|
|
1612
|
+
_align = 1;
|
|
1613
|
+
dataX = x0.values(u, seriesIdx, idx0, idx1);
|
|
1614
|
+
if (x0.unit == 2) dataX = dataX.map((pct) => u.posToVal(xOff + pct * xDim, scaleX.key, true));
|
|
1615
|
+
let sizes = size.values(u, seriesIdx, idx0, idx1);
|
|
1616
|
+
if (size.unit == 2) barWid = sizes[0] * xDim;
|
|
1617
|
+
else barWid = valToPosX(sizes[0], scaleX, xDim, xOff) - valToPosX(0, scaleX, xDim, xOff);
|
|
1618
|
+
colWid = findColWidth(dataX, dataY, valToPosX, scaleX, xDim, xOff, colWid);
|
|
1619
|
+
fullGap = colWid - barWid + extraGap;
|
|
1620
|
+
} else {
|
|
1621
|
+
colWid = findColWidth(dataX, dataY, valToPosX, scaleX, xDim, xOff, colWid);
|
|
1622
|
+
fullGap = colWid * gapFactor + extraGap;
|
|
1623
|
+
barWid = colWid - fullGap;
|
|
1624
|
+
}
|
|
1625
|
+
if (fullGap < 1) fullGap = 0;
|
|
1626
|
+
if (strokeWidth >= barWid / 2) strokeWidth = 0;
|
|
1627
|
+
if (fullGap < 5) pxRound = retArg0;
|
|
1628
|
+
let insetStroke = fullGap > 0;
|
|
1629
|
+
let rawBarWid = colWid - fullGap - (insetStroke ? strokeWidth : 0);
|
|
1630
|
+
barWid = pxRound(clamp(rawBarWid, minWidth, maxWidth));
|
|
1631
|
+
xShift = (_align == 0 ? barWid / 2 : _align == _dirX ? 0 : barWid) - _align * _dirX * ((_align == 0 ? extraGap / 2 : 0) + (insetStroke ? strokeWidth / 2 : 0));
|
|
1632
|
+
const _paths = {
|
|
1633
|
+
stroke: null,
|
|
1634
|
+
fill: null,
|
|
1635
|
+
clip: null,
|
|
1636
|
+
band: null,
|
|
1637
|
+
gaps: null,
|
|
1638
|
+
flags: 0
|
|
1639
|
+
};
|
|
1640
|
+
const stroke = multiPath ? null : new Path2D();
|
|
1641
|
+
let dataY0 = null;
|
|
1642
|
+
if (band != null) dataY0 = u.data[band.series[1]];
|
|
1643
|
+
else {
|
|
1644
|
+
let { y0, y1 } = disp;
|
|
1645
|
+
if (y0 != null && y1 != null) {
|
|
1646
|
+
dataY = y1.values(u, seriesIdx, idx0, idx1);
|
|
1647
|
+
dataY0 = y0.values(u, seriesIdx, idx0, idx1);
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
let radVal = valRadius * barWid;
|
|
1651
|
+
let radBase = baseRadius * barWid;
|
|
1652
|
+
for (let i = _dirX == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += _dirX) {
|
|
1653
|
+
let yVal = dataY[i];
|
|
1654
|
+
if (yVal == null) continue;
|
|
1655
|
+
if (dataY0 != null) {
|
|
1656
|
+
let yVal0 = dataY0[i] ?? 0;
|
|
1657
|
+
if (yVal - yVal0 == 0) continue;
|
|
1658
|
+
fillToY = valToPosY(yVal0, scaleY, yDim, yOff);
|
|
1659
|
+
}
|
|
1660
|
+
let xPos = valToPosX(scaleX.distr != 2 || disp != null ? dataX[i] : i, scaleX, xDim, xOff);
|
|
1661
|
+
let yPos = valToPosY(ifNull(yVal, fillTo), scaleY, yDim, yOff);
|
|
1662
|
+
let lft = pxRound(xPos - xShift);
|
|
1663
|
+
let btm = pxRound(max(yPos, fillToY));
|
|
1664
|
+
let top = pxRound(min(yPos, fillToY));
|
|
1665
|
+
let barHgt = btm - top;
|
|
1666
|
+
if (yVal != null) {
|
|
1667
|
+
let rv = yVal < 0 ? radBase : radVal;
|
|
1668
|
+
let rb = yVal < 0 ? radVal : radBase;
|
|
1669
|
+
if (multiPath) {
|
|
1670
|
+
if (strokeWidth > 0 && strokeColors[i] != null) rect(strokePaths.get(strokeColors[i]), lft, top + floor(strokeWidth / 2), barWid, max(0, barHgt - strokeWidth), rv, rb);
|
|
1671
|
+
if (fillColors[i] != null) rect(fillPaths.get(fillColors[i]), lft, top + floor(strokeWidth / 2), barWid, max(0, barHgt - strokeWidth), rv, rb);
|
|
1672
|
+
} else rect(stroke, lft, top + floor(strokeWidth / 2), barWid, max(0, barHgt - strokeWidth), rv, rb);
|
|
1673
|
+
each(u, seriesIdx, i, lft - strokeWidth / 2, top, barWid + strokeWidth, barHgt);
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
if (strokeWidth > 0) _paths.stroke = multiPath ? strokePaths : stroke;
|
|
1677
|
+
else if (!multiPath) {
|
|
1678
|
+
_paths._fill = series.width == 0 ? series._fill : series._stroke ?? series._fill;
|
|
1679
|
+
_paths.width = 0;
|
|
1680
|
+
}
|
|
1681
|
+
_paths.fill = multiPath ? fillPaths : stroke;
|
|
1682
|
+
return _paths;
|
|
1683
|
+
});
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
function splineInterp(interp, opts) {
|
|
1687
|
+
const alignGaps = ifNull(opts?.alignGaps, 0);
|
|
1688
|
+
return (u, seriesIdx, idx0, idx1) => {
|
|
1689
|
+
return orient(u, seriesIdx, (series, dataX, dataY, scaleX, scaleY, valToPosX, valToPosY, xOff, yOff, xDim, yDim) => {
|
|
1690
|
+
[idx0, idx1] = nonNullIdxs(dataY, idx0, idx1);
|
|
1691
|
+
let pxRound = series.pxRound;
|
|
1692
|
+
let pixelForX = (val) => pxRound(valToPosX(val, scaleX, xDim, xOff));
|
|
1693
|
+
let pixelForY = (val) => pxRound(valToPosY(val, scaleY, yDim, yOff));
|
|
1694
|
+
let moveTo, bezierCurveTo, lineTo;
|
|
1695
|
+
if (scaleX.ori == 0) {
|
|
1696
|
+
moveTo = moveToH;
|
|
1697
|
+
lineTo = lineToH;
|
|
1698
|
+
bezierCurveTo = bezierCurveToH;
|
|
1699
|
+
} else {
|
|
1700
|
+
moveTo = moveToV;
|
|
1701
|
+
lineTo = lineToV;
|
|
1702
|
+
bezierCurveTo = bezierCurveToV;
|
|
1703
|
+
}
|
|
1704
|
+
const dir = scaleX.dir * (scaleX.ori == 0 ? 1 : -1);
|
|
1705
|
+
let firstXPos = pixelForX(dataX[dir == 1 ? idx0 : idx1]);
|
|
1706
|
+
let prevXPos = firstXPos;
|
|
1707
|
+
let xCoords = [];
|
|
1708
|
+
let yCoords = [];
|
|
1709
|
+
for (let i = dir == 1 ? idx0 : idx1; i >= idx0 && i <= idx1; i += dir) if (dataY[i] != null) {
|
|
1710
|
+
let xVal = dataX[i];
|
|
1711
|
+
let xPos = pixelForX(xVal);
|
|
1712
|
+
xCoords.push(prevXPos = xPos);
|
|
1713
|
+
yCoords.push(pixelForY(dataY[i]));
|
|
1714
|
+
}
|
|
1715
|
+
const _paths = {
|
|
1716
|
+
stroke: interp(xCoords, yCoords, moveTo, lineTo, bezierCurveTo, pxRound),
|
|
1717
|
+
fill: null,
|
|
1718
|
+
clip: null,
|
|
1719
|
+
band: null,
|
|
1720
|
+
gaps: null,
|
|
1721
|
+
flags: BAND_CLIP_FILL
|
|
1722
|
+
};
|
|
1723
|
+
const stroke = _paths.stroke;
|
|
1724
|
+
let [bandFillDir, bandClipDir] = bandFillClipDirs(u, seriesIdx);
|
|
1725
|
+
if (series.fill != null || bandFillDir != 0) {
|
|
1726
|
+
let fill = _paths.fill = new Path2D(stroke);
|
|
1727
|
+
let fillToY = pixelForY(series.fillTo(u, seriesIdx, series.min, series.max, bandFillDir));
|
|
1728
|
+
lineTo(fill, prevXPos, fillToY);
|
|
1729
|
+
lineTo(fill, firstXPos, fillToY);
|
|
1730
|
+
}
|
|
1731
|
+
if (!series.spanGaps) {
|
|
1732
|
+
let gaps = [];
|
|
1733
|
+
gaps.push(...findGaps(dataX, dataY, idx0, idx1, dir, pixelForX, alignGaps));
|
|
1734
|
+
_paths.gaps = gaps = series.gaps(u, seriesIdx, idx0, idx1, gaps);
|
|
1735
|
+
_paths.clip = clipGaps(gaps, scaleX.ori, xOff, yOff, xDim, yDim);
|
|
1736
|
+
}
|
|
1737
|
+
if (bandClipDir != 0) _paths.band = bandClipDir == 2 ? [clipBandLine(u, seriesIdx, idx0, idx1, stroke, -1), clipBandLine(u, seriesIdx, idx0, idx1, stroke, 1)] : clipBandLine(u, seriesIdx, idx0, idx1, stroke, bandClipDir);
|
|
1738
|
+
return _paths;
|
|
1739
|
+
});
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
function monotoneCubic(opts) {
|
|
1743
|
+
return splineInterp(_monotoneCubic, opts);
|
|
1744
|
+
}
|
|
1745
|
+
function _monotoneCubic(xs, ys, moveTo, lineTo, bezierCurveTo, pxRound) {
|
|
1746
|
+
const n = xs.length;
|
|
1747
|
+
if (n < 2) return null;
|
|
1748
|
+
const path = new Path2D();
|
|
1749
|
+
moveTo(path, xs[0], ys[0]);
|
|
1750
|
+
if (n == 2) lineTo(path, xs[1], ys[1]);
|
|
1751
|
+
else {
|
|
1752
|
+
let ms = Array(n), ds = Array(n - 1), dys = Array(n - 1), dxs = Array(n - 1);
|
|
1753
|
+
for (let i = 0; i < n - 1; i++) {
|
|
1754
|
+
dys[i] = ys[i + 1] - ys[i];
|
|
1755
|
+
dxs[i] = xs[i + 1] - xs[i];
|
|
1756
|
+
ds[i] = dys[i] / dxs[i];
|
|
1757
|
+
}
|
|
1758
|
+
ms[0] = ds[0];
|
|
1759
|
+
for (let i = 1; i < n - 1; i++) if (ds[i] === 0 || ds[i - 1] === 0 || ds[i - 1] > 0 !== ds[i] > 0) ms[i] = 0;
|
|
1760
|
+
else {
|
|
1761
|
+
ms[i] = 3 * (dxs[i - 1] + dxs[i]) / ((2 * dxs[i] + dxs[i - 1]) / ds[i - 1] + (dxs[i] + 2 * dxs[i - 1]) / ds[i]);
|
|
1762
|
+
if (!isFinite(ms[i])) ms[i] = 0;
|
|
1763
|
+
}
|
|
1764
|
+
ms[n - 1] = ds[n - 2];
|
|
1765
|
+
for (let i = 0; i < n - 1; i++) bezierCurveTo(path, xs[i] + dxs[i] / 3, ys[i] + ms[i] * dxs[i] / 3, xs[i + 1] - dxs[i] / 3, ys[i + 1] - ms[i + 1] * dxs[i] / 3, xs[i + 1], ys[i + 1]);
|
|
1766
|
+
}
|
|
1767
|
+
return path;
|
|
1768
|
+
}
|
|
1769
|
+
var cursorPlots = /* @__PURE__ */ new Set();
|
|
1770
|
+
function invalidateRects() {
|
|
1771
|
+
for (let u of cursorPlots) u.syncRect(true);
|
|
1772
|
+
}
|
|
1773
|
+
if (domEnv) {
|
|
1774
|
+
on(resize, win, invalidateRects);
|
|
1775
|
+
on(scroll, win, invalidateRects, true);
|
|
1776
|
+
on(dppxchange, win, () => {
|
|
1777
|
+
uPlot.pxRatio = pxRatio;
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
var linearPath = linear();
|
|
1781
|
+
var pointsPath = points();
|
|
1782
|
+
function setDefaults(d, xo, yo, initY) {
|
|
1783
|
+
return (initY ? [d[0], d[1]].concat(d.slice(2)) : [d[0]].concat(d.slice(1))).map((o, i) => setDefault(o, i, xo, yo));
|
|
1784
|
+
}
|
|
1785
|
+
function setDefaults2(d, xyo) {
|
|
1786
|
+
return d.map((o, i) => i == 0 ? {} : assign({}, xyo, o));
|
|
1787
|
+
}
|
|
1788
|
+
function setDefault(o, i, xo, yo) {
|
|
1789
|
+
return assign({}, i == 0 ? xo : yo, o);
|
|
1790
|
+
}
|
|
1791
|
+
function snapNumX(self, dataMin, dataMax) {
|
|
1792
|
+
return dataMin == null ? nullNullTuple : [dataMin, dataMax];
|
|
1793
|
+
}
|
|
1794
|
+
var snapTimeX = snapNumX;
|
|
1795
|
+
function snapNumY(self, dataMin, dataMax) {
|
|
1796
|
+
return dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, rangePad, true);
|
|
1797
|
+
}
|
|
1798
|
+
function snapLogY(self, dataMin, dataMax, scale) {
|
|
1799
|
+
return dataMin == null ? nullNullTuple : rangeLog(dataMin, dataMax, self.scales[scale].log, false);
|
|
1800
|
+
}
|
|
1801
|
+
var snapLogX = snapLogY;
|
|
1802
|
+
function snapAsinhY(self, dataMin, dataMax, scale) {
|
|
1803
|
+
return dataMin == null ? nullNullTuple : rangeAsinh(dataMin, dataMax, self.scales[scale].log, false);
|
|
1804
|
+
}
|
|
1805
|
+
var snapAsinhX = snapAsinhY;
|
|
1806
|
+
function findIncr(minVal, maxVal, incrs, dim, minSpace) {
|
|
1807
|
+
let intDigits = max(numIntDigits(minVal), numIntDigits(maxVal));
|
|
1808
|
+
let delta = maxVal - minVal;
|
|
1809
|
+
let incrIdx = closestIdx(minSpace / dim * delta, incrs);
|
|
1810
|
+
do {
|
|
1811
|
+
let foundIncr = incrs[incrIdx];
|
|
1812
|
+
let foundSpace = dim * foundIncr / delta;
|
|
1813
|
+
if (foundSpace >= minSpace && intDigits + (foundIncr < 5 ? fixedDec.get(foundIncr) : 0) <= 17) return [foundIncr, foundSpace];
|
|
1814
|
+
} while (++incrIdx < incrs.length);
|
|
1815
|
+
return [0, 0];
|
|
1816
|
+
}
|
|
1817
|
+
function pxRatioFont(font) {
|
|
1818
|
+
let fontSize, fontSizeCss;
|
|
1819
|
+
font = font.replace(/(\d+)px/, (m, p1) => (fontSize = round((fontSizeCss = +p1) * pxRatio)) + "px");
|
|
1820
|
+
return [
|
|
1821
|
+
font,
|
|
1822
|
+
fontSize,
|
|
1823
|
+
fontSizeCss
|
|
1824
|
+
];
|
|
1825
|
+
}
|
|
1826
|
+
function syncFontSize(axis) {
|
|
1827
|
+
if (axis.show) [axis.font, axis.labelFont].forEach((f) => {
|
|
1828
|
+
let size = roundDec(f[2] * pxRatio, 1);
|
|
1829
|
+
f[0] = f[0].replace(/[0-9.]+px/, size + "px");
|
|
1830
|
+
f[1] = size;
|
|
1831
|
+
});
|
|
1832
|
+
}
|
|
1833
|
+
function uPlot(opts, data, then) {
|
|
1834
|
+
const self = { mode: ifNull(opts.mode, 1) };
|
|
1835
|
+
const mode = self.mode;
|
|
1836
|
+
function getHPos(val, scale, dim, off) {
|
|
1837
|
+
let pct = scale.valToPct(val);
|
|
1838
|
+
return off + dim * (scale.dir == -1 ? 1 - pct : pct);
|
|
1839
|
+
}
|
|
1840
|
+
function getVPos(val, scale, dim, off) {
|
|
1841
|
+
let pct = scale.valToPct(val);
|
|
1842
|
+
return off + dim * (scale.dir == -1 ? pct : 1 - pct);
|
|
1843
|
+
}
|
|
1844
|
+
function getPos(val, scale, dim, off) {
|
|
1845
|
+
return scale.ori == 0 ? getHPos(val, scale, dim, off) : getVPos(val, scale, dim, off);
|
|
1846
|
+
}
|
|
1847
|
+
self.valToPosH = getHPos;
|
|
1848
|
+
self.valToPosV = getVPos;
|
|
1849
|
+
let ready = false;
|
|
1850
|
+
self.status = 0;
|
|
1851
|
+
const root = self.root = placeDiv(UPLOT);
|
|
1852
|
+
if (opts.id != null) root.id = opts.id;
|
|
1853
|
+
addClass(root, opts.class);
|
|
1854
|
+
if (opts.title) {
|
|
1855
|
+
let title = placeDiv(TITLE, root);
|
|
1856
|
+
title.textContent = opts.title;
|
|
1857
|
+
}
|
|
1858
|
+
const can = placeTag("canvas");
|
|
1859
|
+
const ctx = self.ctx = can.getContext("2d");
|
|
1860
|
+
const wrap = placeDiv(WRAP, root);
|
|
1861
|
+
on("click", wrap, (e) => {
|
|
1862
|
+
if (e.target === over) (mouseLeft1 != mouseLeft0 || mouseTop1 != mouseTop0) && drag.click(self, e);
|
|
1863
|
+
}, true);
|
|
1864
|
+
const under = self.under = placeDiv(UNDER, wrap);
|
|
1865
|
+
wrap.appendChild(can);
|
|
1866
|
+
const over = self.over = placeDiv(OVER, wrap);
|
|
1867
|
+
opts = copy(opts);
|
|
1868
|
+
const pxAlign = +ifNull(opts.pxAlign, 1);
|
|
1869
|
+
const pxRound = pxRoundGen(pxAlign);
|
|
1870
|
+
(opts.plugins || []).forEach((p) => {
|
|
1871
|
+
if (p.opts) opts = p.opts(self, opts) || opts;
|
|
1872
|
+
});
|
|
1873
|
+
const ms = opts.ms || .001;
|
|
1874
|
+
const series = self.series = mode == 1 ? setDefaults(opts.series || [], xSeriesOpts, ySeriesOpts, false) : setDefaults2(opts.series || [null], xySeriesOpts);
|
|
1875
|
+
const axes = self.axes = setDefaults(opts.axes || [], xAxisOpts, yAxisOpts, true);
|
|
1876
|
+
const scales = self.scales = {};
|
|
1877
|
+
const bands = self.bands = opts.bands || [];
|
|
1878
|
+
bands.forEach((b) => {
|
|
1879
|
+
b.fill = fnOrSelf(b.fill || null);
|
|
1880
|
+
b.dir = ifNull(b.dir, -1);
|
|
1881
|
+
});
|
|
1882
|
+
const xScaleKey = mode == 2 ? series[1].facets[0].scale : series[0].scale;
|
|
1883
|
+
const drawOrderMap = {
|
|
1884
|
+
axes: drawAxesGrid,
|
|
1885
|
+
series: drawSeries
|
|
1886
|
+
};
|
|
1887
|
+
const drawOrder = (opts.drawOrder || ["axes", "series"]).map((key) => drawOrderMap[key]);
|
|
1888
|
+
function initValToPct(sc) {
|
|
1889
|
+
const getVal = sc.distr == 3 ? (val) => log10(val > 0 ? val : sc.clamp(self, val, sc.min, sc.max, sc.key)) : sc.distr == 4 ? (val) => asinh(val, sc.asinh) : sc.distr == 100 ? (val) => sc.fwd(val) : (val) => val;
|
|
1890
|
+
return (val) => {
|
|
1891
|
+
let _val = getVal(val);
|
|
1892
|
+
let { _min, _max } = sc;
|
|
1893
|
+
let delta = _max - _min;
|
|
1894
|
+
return (_val - _min) / delta;
|
|
1895
|
+
};
|
|
1896
|
+
}
|
|
1897
|
+
function initScale(scaleKey) {
|
|
1898
|
+
let sc = scales[scaleKey];
|
|
1899
|
+
if (sc == null) {
|
|
1900
|
+
let scaleOpts = (opts.scales || EMPTY_OBJ)[scaleKey] || EMPTY_OBJ;
|
|
1901
|
+
if (scaleOpts.from != null) {
|
|
1902
|
+
initScale(scaleOpts.from);
|
|
1903
|
+
let sc = assign({}, scales[scaleOpts.from], scaleOpts, { key: scaleKey });
|
|
1904
|
+
sc.valToPct = initValToPct(sc);
|
|
1905
|
+
scales[scaleKey] = sc;
|
|
1906
|
+
} else {
|
|
1907
|
+
sc = scales[scaleKey] = assign({}, scaleKey == xScaleKey ? xScaleOpts : yScaleOpts, scaleOpts);
|
|
1908
|
+
sc.key = scaleKey;
|
|
1909
|
+
let isTime = sc.time;
|
|
1910
|
+
let rn = sc.range;
|
|
1911
|
+
let rangeIsArr = isArr(rn);
|
|
1912
|
+
if (scaleKey != xScaleKey || mode == 2 && !isTime) {
|
|
1913
|
+
if (rangeIsArr && (rn[0] == null || rn[1] == null)) {
|
|
1914
|
+
rn = {
|
|
1915
|
+
min: rn[0] == null ? autoRangePart : {
|
|
1916
|
+
mode: 1,
|
|
1917
|
+
hard: rn[0],
|
|
1918
|
+
soft: rn[0]
|
|
1919
|
+
},
|
|
1920
|
+
max: rn[1] == null ? autoRangePart : {
|
|
1921
|
+
mode: 1,
|
|
1922
|
+
hard: rn[1],
|
|
1923
|
+
soft: rn[1]
|
|
1924
|
+
}
|
|
1925
|
+
};
|
|
1926
|
+
rangeIsArr = false;
|
|
1927
|
+
}
|
|
1928
|
+
if (!rangeIsArr && isObj(rn)) {
|
|
1929
|
+
let cfg = rn;
|
|
1930
|
+
rn = (self, dataMin, dataMax) => dataMin == null ? nullNullTuple : rangeNum(dataMin, dataMax, cfg);
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
sc.range = fnOrSelf(rn || (isTime ? snapTimeX : scaleKey == xScaleKey ? sc.distr == 3 ? snapLogX : sc.distr == 4 ? snapAsinhX : snapNumX : sc.distr == 3 ? snapLogY : sc.distr == 4 ? snapAsinhY : snapNumY));
|
|
1934
|
+
sc.auto = fnOrSelf(rangeIsArr ? false : sc.auto);
|
|
1935
|
+
sc.clamp = fnOrSelf(sc.clamp || clampScale);
|
|
1936
|
+
sc._min = sc._max = null;
|
|
1937
|
+
sc.valToPct = initValToPct(sc);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
initScale("x");
|
|
1942
|
+
initScale("y");
|
|
1943
|
+
if (mode == 1) series.forEach((s) => {
|
|
1944
|
+
initScale(s.scale);
|
|
1945
|
+
});
|
|
1946
|
+
axes.forEach((a) => {
|
|
1947
|
+
initScale(a.scale);
|
|
1948
|
+
});
|
|
1949
|
+
for (let k in opts.scales) initScale(k);
|
|
1950
|
+
const scaleX = scales[xScaleKey];
|
|
1951
|
+
const xScaleDistr = scaleX.distr;
|
|
1952
|
+
let valToPosX, valToPosY;
|
|
1953
|
+
if (scaleX.ori == 0) {
|
|
1954
|
+
addClass(root, ORI_HZ);
|
|
1955
|
+
valToPosX = getHPos;
|
|
1956
|
+
valToPosY = getVPos;
|
|
1957
|
+
} else {
|
|
1958
|
+
addClass(root, ORI_VT);
|
|
1959
|
+
valToPosX = getVPos;
|
|
1960
|
+
valToPosY = getHPos;
|
|
1961
|
+
}
|
|
1962
|
+
const pendScales = {};
|
|
1963
|
+
for (let k in scales) {
|
|
1964
|
+
let sc = scales[k];
|
|
1965
|
+
if (sc.min != null || sc.max != null) {
|
|
1966
|
+
pendScales[k] = {
|
|
1967
|
+
min: sc.min,
|
|
1968
|
+
max: sc.max
|
|
1969
|
+
};
|
|
1970
|
+
sc.min = sc.max = null;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
const _tzDate = opts.tzDate || ((ts) => new Date(round(ts / ms)));
|
|
1974
|
+
const _fmtDate = opts.fmtDate || fmtDate;
|
|
1975
|
+
const _timeAxisSplits = ms == 1 ? timeAxisSplitsMs(_tzDate) : timeAxisSplitsS(_tzDate);
|
|
1976
|
+
const _timeAxisVals = timeAxisVals(_tzDate, timeAxisStamps(ms == 1 ? _timeAxisStampsMs : _timeAxisStampsS, _fmtDate));
|
|
1977
|
+
const _timeSeriesVal = timeSeriesVal(_tzDate, timeSeriesStamp(_timeSeriesStamp, _fmtDate));
|
|
1978
|
+
const activeIdxs = [];
|
|
1979
|
+
const legend = self.legend = assign({}, legendOpts, opts.legend);
|
|
1980
|
+
const cursor = self.cursor = assign({}, cursorOpts, { drag: { y: mode == 2 } }, opts.cursor);
|
|
1981
|
+
const showLegend = legend.show;
|
|
1982
|
+
const showCursor = cursor.show;
|
|
1983
|
+
const markers = legend.markers;
|
|
1984
|
+
legend.idxs = activeIdxs;
|
|
1985
|
+
markers.width = fnOrSelf(markers.width);
|
|
1986
|
+
markers.dash = fnOrSelf(markers.dash);
|
|
1987
|
+
markers.stroke = fnOrSelf(markers.stroke);
|
|
1988
|
+
markers.fill = fnOrSelf(markers.fill);
|
|
1989
|
+
let legendTable;
|
|
1990
|
+
let legendHead;
|
|
1991
|
+
let legendBody;
|
|
1992
|
+
let legendRows = [];
|
|
1993
|
+
let legendCells = [];
|
|
1994
|
+
let legendCols;
|
|
1995
|
+
let multiValLegend = false;
|
|
1996
|
+
let NULL_LEGEND_VALUES = {};
|
|
1997
|
+
if (legend.live) {
|
|
1998
|
+
const getMultiVals = series[1] ? series[1].values : null;
|
|
1999
|
+
multiValLegend = getMultiVals != null;
|
|
2000
|
+
legendCols = multiValLegend ? getMultiVals(self, 1, 0) : { _: 0 };
|
|
2001
|
+
for (let k in legendCols) NULL_LEGEND_VALUES[k] = LEGEND_DISP;
|
|
2002
|
+
}
|
|
2003
|
+
if (showLegend) {
|
|
2004
|
+
legendTable = placeTag("table", LEGEND, root);
|
|
2005
|
+
legendBody = placeTag("tbody", null, legendTable);
|
|
2006
|
+
legend.mount(self, legendTable);
|
|
2007
|
+
if (multiValLegend) {
|
|
2008
|
+
legendHead = placeTag("thead", null, legendTable, legendBody);
|
|
2009
|
+
let head = placeTag("tr", null, legendHead);
|
|
2010
|
+
placeTag("th", null, head);
|
|
2011
|
+
for (var key in legendCols) placeTag("th", LEGEND_LABEL, head).textContent = key;
|
|
2012
|
+
} else {
|
|
2013
|
+
addClass(legendTable, LEGEND_INLINE);
|
|
2014
|
+
legend.live && addClass(legendTable, LEGEND_LIVE);
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
const son = { show: true };
|
|
2018
|
+
const soff = { show: false };
|
|
2019
|
+
function initLegendRow(s, i) {
|
|
2020
|
+
if (i == 0 && (multiValLegend || !legend.live || mode == 2)) return nullNullTuple;
|
|
2021
|
+
let cells = [];
|
|
2022
|
+
let row = placeTag("tr", LEGEND_SERIES, legendBody, legendBody.childNodes[i]);
|
|
2023
|
+
addClass(row, s.class);
|
|
2024
|
+
if (!s.show) addClass(row, OFF);
|
|
2025
|
+
let label = placeTag("th", null, row);
|
|
2026
|
+
if (markers.show) {
|
|
2027
|
+
let indic = placeDiv(LEGEND_MARKER, label);
|
|
2028
|
+
if (i > 0) {
|
|
2029
|
+
let width = markers.width(self, i);
|
|
2030
|
+
if (width) indic.style.border = width + "px " + markers.dash(self, i) + " " + markers.stroke(self, i);
|
|
2031
|
+
indic.style.background = markers.fill(self, i);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
let text = placeDiv(LEGEND_LABEL, label);
|
|
2035
|
+
if (s.label instanceof HTMLElement) text.appendChild(s.label);
|
|
2036
|
+
else text.textContent = s.label;
|
|
2037
|
+
if (i > 0) {
|
|
2038
|
+
if (!markers.show) text.style.color = s.width > 0 ? markers.stroke(self, i) : markers.fill(self, i);
|
|
2039
|
+
onMouse("click", label, (e) => {
|
|
2040
|
+
if (cursor._lock) return;
|
|
2041
|
+
setCursorEvent(e);
|
|
2042
|
+
let seriesIdx = series.indexOf(s);
|
|
2043
|
+
if ((e.ctrlKey || e.metaKey) != legend.isolate) {
|
|
2044
|
+
let isolate = series.some((s, i) => i > 0 && i != seriesIdx && s.show);
|
|
2045
|
+
series.forEach((s, i) => {
|
|
2046
|
+
i > 0 && setSeries(i, isolate ? i == seriesIdx ? son : soff : son, true, syncOpts.setSeries);
|
|
2047
|
+
});
|
|
2048
|
+
} else setSeries(seriesIdx, { show: !s.show }, true, syncOpts.setSeries);
|
|
2049
|
+
}, false);
|
|
2050
|
+
if (cursorFocus) onMouse(mouseenter, label, (e) => {
|
|
2051
|
+
if (cursor._lock) return;
|
|
2052
|
+
setCursorEvent(e);
|
|
2053
|
+
setSeries(series.indexOf(s), FOCUS_TRUE, true, syncOpts.setSeries);
|
|
2054
|
+
}, false);
|
|
2055
|
+
}
|
|
2056
|
+
for (var key in legendCols) {
|
|
2057
|
+
let v = placeTag("td", LEGEND_VALUE, row);
|
|
2058
|
+
v.textContent = "--";
|
|
2059
|
+
cells.push(v);
|
|
2060
|
+
}
|
|
2061
|
+
return [row, cells];
|
|
2062
|
+
}
|
|
2063
|
+
const mouseListeners = /* @__PURE__ */ new Map();
|
|
2064
|
+
function onMouse(ev, targ, fn, onlyTarg = true) {
|
|
2065
|
+
const targListeners = mouseListeners.get(targ) || {};
|
|
2066
|
+
const listener = cursor.bind[ev](self, targ, fn, onlyTarg);
|
|
2067
|
+
if (listener) {
|
|
2068
|
+
on(ev, targ, targListeners[ev] = listener);
|
|
2069
|
+
mouseListeners.set(targ, targListeners);
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
function offMouse(ev, targ, fn) {
|
|
2073
|
+
const targListeners = mouseListeners.get(targ) || {};
|
|
2074
|
+
for (let k in targListeners) if (ev == null || k == ev) {
|
|
2075
|
+
off(k, targ, targListeners[k]);
|
|
2076
|
+
delete targListeners[k];
|
|
2077
|
+
}
|
|
2078
|
+
if (ev == null) mouseListeners.delete(targ);
|
|
2079
|
+
}
|
|
2080
|
+
let fullWidCss = 0;
|
|
2081
|
+
let fullHgtCss = 0;
|
|
2082
|
+
let plotWidCss = 0;
|
|
2083
|
+
let plotHgtCss = 0;
|
|
2084
|
+
let plotLftCss = 0;
|
|
2085
|
+
let plotTopCss = 0;
|
|
2086
|
+
let _plotLftCss = plotLftCss;
|
|
2087
|
+
let _plotTopCss = plotTopCss;
|
|
2088
|
+
let _plotWidCss = plotWidCss;
|
|
2089
|
+
let _plotHgtCss = plotHgtCss;
|
|
2090
|
+
let plotLft = 0;
|
|
2091
|
+
let plotTop = 0;
|
|
2092
|
+
let plotWid = 0;
|
|
2093
|
+
let plotHgt = 0;
|
|
2094
|
+
self.bbox = {};
|
|
2095
|
+
let shouldSetScales = false;
|
|
2096
|
+
let shouldSetSize = false;
|
|
2097
|
+
let shouldConvergeSize = false;
|
|
2098
|
+
let shouldSetCursor = false;
|
|
2099
|
+
let shouldSetSelect = false;
|
|
2100
|
+
let shouldSetLegend = false;
|
|
2101
|
+
function _setSize(width, height, force) {
|
|
2102
|
+
if (force || width != self.width || height != self.height) calcSize(width, height);
|
|
2103
|
+
resetYSeries(false);
|
|
2104
|
+
shouldConvergeSize = true;
|
|
2105
|
+
shouldSetSize = true;
|
|
2106
|
+
commit();
|
|
2107
|
+
}
|
|
2108
|
+
function calcSize(width, height) {
|
|
2109
|
+
self.width = fullWidCss = plotWidCss = width;
|
|
2110
|
+
self.height = fullHgtCss = plotHgtCss = height;
|
|
2111
|
+
plotLftCss = plotTopCss = 0;
|
|
2112
|
+
calcPlotRect();
|
|
2113
|
+
calcAxesRects();
|
|
2114
|
+
let bb = self.bbox;
|
|
2115
|
+
plotLft = bb.left = incrRound(plotLftCss * pxRatio, .5);
|
|
2116
|
+
plotTop = bb.top = incrRound(plotTopCss * pxRatio, .5);
|
|
2117
|
+
plotWid = bb.width = incrRound(plotWidCss * pxRatio, .5);
|
|
2118
|
+
plotHgt = bb.height = incrRound(plotHgtCss * pxRatio, .5);
|
|
2119
|
+
}
|
|
2120
|
+
const CYCLE_LIMIT = 3;
|
|
2121
|
+
function convergeSize() {
|
|
2122
|
+
let converged = false;
|
|
2123
|
+
let cycleNum = 0;
|
|
2124
|
+
while (!converged) {
|
|
2125
|
+
cycleNum++;
|
|
2126
|
+
let axesConverged = axesCalc(cycleNum);
|
|
2127
|
+
let paddingConverged = paddingCalc(cycleNum);
|
|
2128
|
+
converged = cycleNum == CYCLE_LIMIT || axesConverged && paddingConverged;
|
|
2129
|
+
if (!converged) {
|
|
2130
|
+
calcSize(self.width, self.height);
|
|
2131
|
+
shouldSetSize = true;
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
function setSize({ width, height }) {
|
|
2136
|
+
_setSize(width, height);
|
|
2137
|
+
}
|
|
2138
|
+
self.setSize = setSize;
|
|
2139
|
+
function calcPlotRect() {
|
|
2140
|
+
let hasTopAxis = false;
|
|
2141
|
+
let hasBtmAxis = false;
|
|
2142
|
+
let hasRgtAxis = false;
|
|
2143
|
+
let hasLftAxis = false;
|
|
2144
|
+
axes.forEach((axis, i) => {
|
|
2145
|
+
if (axis.show && axis._show) {
|
|
2146
|
+
let { side, _size } = axis;
|
|
2147
|
+
let isVt = side % 2;
|
|
2148
|
+
let fullSize = _size + (axis.label != null ? axis.labelSize : 0);
|
|
2149
|
+
if (fullSize > 0) if (isVt) {
|
|
2150
|
+
plotWidCss -= fullSize;
|
|
2151
|
+
if (side == 3) {
|
|
2152
|
+
plotLftCss += fullSize;
|
|
2153
|
+
hasLftAxis = true;
|
|
2154
|
+
} else hasRgtAxis = true;
|
|
2155
|
+
} else {
|
|
2156
|
+
plotHgtCss -= fullSize;
|
|
2157
|
+
if (side == 0) {
|
|
2158
|
+
plotTopCss += fullSize;
|
|
2159
|
+
hasTopAxis = true;
|
|
2160
|
+
} else hasBtmAxis = true;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
});
|
|
2164
|
+
sidesWithAxes[0] = hasTopAxis;
|
|
2165
|
+
sidesWithAxes[1] = hasRgtAxis;
|
|
2166
|
+
sidesWithAxes[2] = hasBtmAxis;
|
|
2167
|
+
sidesWithAxes[3] = hasLftAxis;
|
|
2168
|
+
plotWidCss -= _padding[1] + _padding[3];
|
|
2169
|
+
plotLftCss += _padding[3];
|
|
2170
|
+
plotHgtCss -= _padding[2] + _padding[0];
|
|
2171
|
+
plotTopCss += _padding[0];
|
|
2172
|
+
}
|
|
2173
|
+
function calcAxesRects() {
|
|
2174
|
+
let off1 = plotLftCss + plotWidCss;
|
|
2175
|
+
let off2 = plotTopCss + plotHgtCss;
|
|
2176
|
+
let off3 = plotLftCss;
|
|
2177
|
+
let off0 = plotTopCss;
|
|
2178
|
+
function incrOffset(side, size) {
|
|
2179
|
+
switch (side) {
|
|
2180
|
+
case 1:
|
|
2181
|
+
off1 += size;
|
|
2182
|
+
return off1 - size;
|
|
2183
|
+
case 2:
|
|
2184
|
+
off2 += size;
|
|
2185
|
+
return off2 - size;
|
|
2186
|
+
case 3:
|
|
2187
|
+
off3 -= size;
|
|
2188
|
+
return off3 + size;
|
|
2189
|
+
case 0:
|
|
2190
|
+
off0 -= size;
|
|
2191
|
+
return off0 + size;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
axes.forEach((axis, i) => {
|
|
2195
|
+
if (axis.show && axis._show) {
|
|
2196
|
+
let side = axis.side;
|
|
2197
|
+
axis._pos = incrOffset(side, axis._size);
|
|
2198
|
+
if (axis.label != null) axis._lpos = incrOffset(side, axis.labelSize);
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
if (cursor.dataIdx == null) {
|
|
2203
|
+
let hov = cursor.hover;
|
|
2204
|
+
let skip = hov.skip = new Set(hov.skip ?? []);
|
|
2205
|
+
skip.add(void 0);
|
|
2206
|
+
let prox = hov.prox = fnOrSelf(hov.prox);
|
|
2207
|
+
let bias = hov.bias ??= 0;
|
|
2208
|
+
cursor.dataIdx = (self, seriesIdx, cursorIdx, valAtPosX) => {
|
|
2209
|
+
if (seriesIdx == 0) return cursorIdx;
|
|
2210
|
+
let idx2 = cursorIdx;
|
|
2211
|
+
let _prox = prox(self, seriesIdx, cursorIdx, valAtPosX) ?? inf;
|
|
2212
|
+
let withProx = _prox >= 0 && _prox < inf;
|
|
2213
|
+
let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss;
|
|
2214
|
+
let cursorLft = cursor.left;
|
|
2215
|
+
let xValues = data[0];
|
|
2216
|
+
let yValues = data[seriesIdx];
|
|
2217
|
+
if (skip.has(yValues[cursorIdx])) {
|
|
2218
|
+
idx2 = null;
|
|
2219
|
+
let nonNullLft = null, nonNullRgt = null, j;
|
|
2220
|
+
if (bias == 0 || bias == -1) {
|
|
2221
|
+
j = cursorIdx;
|
|
2222
|
+
while (nonNullLft == null && j-- > 0) if (!skip.has(yValues[j])) nonNullLft = j;
|
|
2223
|
+
}
|
|
2224
|
+
if (bias == 0 || bias == 1) {
|
|
2225
|
+
j = cursorIdx;
|
|
2226
|
+
while (nonNullRgt == null && j++ < yValues.length) if (!skip.has(yValues[j])) nonNullRgt = j;
|
|
2227
|
+
}
|
|
2228
|
+
if (nonNullLft != null || nonNullRgt != null) if (withProx) {
|
|
2229
|
+
let lftPos = nonNullLft == null ? -Infinity : valToPosX(xValues[nonNullLft], scaleX, xDim, 0);
|
|
2230
|
+
let rgtPos = nonNullRgt == null ? Infinity : valToPosX(xValues[nonNullRgt], scaleX, xDim, 0);
|
|
2231
|
+
let lftDelta = cursorLft - lftPos;
|
|
2232
|
+
let rgtDelta = rgtPos - cursorLft;
|
|
2233
|
+
if (lftDelta <= rgtDelta) {
|
|
2234
|
+
if (lftDelta <= _prox) idx2 = nonNullLft;
|
|
2235
|
+
} else if (rgtDelta <= _prox) idx2 = nonNullRgt;
|
|
2236
|
+
} else idx2 = nonNullRgt == null ? nonNullLft : nonNullLft == null ? nonNullRgt : cursorIdx - nonNullLft <= nonNullRgt - cursorIdx ? nonNullLft : nonNullRgt;
|
|
2237
|
+
} else if (withProx) {
|
|
2238
|
+
if (abs(cursorLft - valToPosX(xValues[cursorIdx], scaleX, xDim, 0)) > _prox) idx2 = null;
|
|
2239
|
+
}
|
|
2240
|
+
return idx2;
|
|
2241
|
+
};
|
|
2242
|
+
}
|
|
2243
|
+
const setCursorEvent = (e) => {
|
|
2244
|
+
cursor.event = e;
|
|
2245
|
+
};
|
|
2246
|
+
cursor.idxs = activeIdxs;
|
|
2247
|
+
cursor._lock = false;
|
|
2248
|
+
let points = cursor.points;
|
|
2249
|
+
points.show = fnOrSelf(points.show);
|
|
2250
|
+
points.size = fnOrSelf(points.size);
|
|
2251
|
+
points.stroke = fnOrSelf(points.stroke);
|
|
2252
|
+
points.width = fnOrSelf(points.width);
|
|
2253
|
+
points.fill = fnOrSelf(points.fill);
|
|
2254
|
+
const focus = self.focus = assign({}, opts.focus || { alpha: .3 }, cursor.focus);
|
|
2255
|
+
const cursorFocus = focus.prox >= 0;
|
|
2256
|
+
const cursorOnePt = cursorFocus && points.one;
|
|
2257
|
+
let cursorPts = [];
|
|
2258
|
+
let cursorPtsLft = [];
|
|
2259
|
+
let cursorPtsTop = [];
|
|
2260
|
+
function initCursorPt(s, si) {
|
|
2261
|
+
let pt = points.show(self, si);
|
|
2262
|
+
if (pt instanceof HTMLElement) {
|
|
2263
|
+
addClass(pt, CURSOR_PT);
|
|
2264
|
+
addClass(pt, s.class);
|
|
2265
|
+
elTrans(pt, -10, -10, plotWidCss, plotHgtCss);
|
|
2266
|
+
over.insertBefore(pt, cursorPts[si]);
|
|
2267
|
+
return pt;
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
function initSeries(s, i) {
|
|
2271
|
+
if (mode == 1 || i > 0) {
|
|
2272
|
+
let isTime = mode == 1 && scales[s.scale].time;
|
|
2273
|
+
let sv = s.value;
|
|
2274
|
+
s.value = isTime ? isStr(sv) ? timeSeriesVal(_tzDate, timeSeriesStamp(sv, _fmtDate)) : sv || _timeSeriesVal : sv || numSeriesVal;
|
|
2275
|
+
s.label = s.label || (isTime ? timeSeriesLabel : numSeriesLabel);
|
|
2276
|
+
}
|
|
2277
|
+
if (cursorOnePt || i > 0) {
|
|
2278
|
+
s.width = s.width == null ? 1 : s.width;
|
|
2279
|
+
s.paths = s.paths || linearPath || retNull;
|
|
2280
|
+
s.fillTo = fnOrSelf(s.fillTo || seriesFillTo);
|
|
2281
|
+
s.pxAlign = +ifNull(s.pxAlign, pxAlign);
|
|
2282
|
+
s.pxRound = pxRoundGen(s.pxAlign);
|
|
2283
|
+
s.stroke = fnOrSelf(s.stroke || null);
|
|
2284
|
+
s.fill = fnOrSelf(s.fill || null);
|
|
2285
|
+
s._stroke = s._fill = s._paths = s._focus = null;
|
|
2286
|
+
let _ptDia = ptDia(max(1, s.width), 1);
|
|
2287
|
+
let points = s.points = assign({}, {
|
|
2288
|
+
size: _ptDia,
|
|
2289
|
+
width: max(1, _ptDia * .2),
|
|
2290
|
+
stroke: s.stroke,
|
|
2291
|
+
space: _ptDia * 2,
|
|
2292
|
+
paths: pointsPath,
|
|
2293
|
+
_stroke: null,
|
|
2294
|
+
_fill: null
|
|
2295
|
+
}, s.points);
|
|
2296
|
+
points.show = fnOrSelf(points.show);
|
|
2297
|
+
points.filter = fnOrSelf(points.filter);
|
|
2298
|
+
points.fill = fnOrSelf(points.fill);
|
|
2299
|
+
points.stroke = fnOrSelf(points.stroke);
|
|
2300
|
+
points.paths = fnOrSelf(points.paths);
|
|
2301
|
+
points.pxAlign = s.pxAlign;
|
|
2302
|
+
}
|
|
2303
|
+
if (showLegend) {
|
|
2304
|
+
let rowCells = initLegendRow(s, i);
|
|
2305
|
+
legendRows.splice(i, 0, rowCells[0]);
|
|
2306
|
+
legendCells.splice(i, 0, rowCells[1]);
|
|
2307
|
+
legend.values.push(null);
|
|
2308
|
+
}
|
|
2309
|
+
if (showCursor) {
|
|
2310
|
+
activeIdxs.splice(i, 0, null);
|
|
2311
|
+
let pt = null;
|
|
2312
|
+
if (cursorOnePt) {
|
|
2313
|
+
if (i == 0) pt = initCursorPt(s, i);
|
|
2314
|
+
} else if (i > 0) pt = initCursorPt(s, i);
|
|
2315
|
+
cursorPts.splice(i, 0, pt);
|
|
2316
|
+
cursorPtsLft.splice(i, 0, 0);
|
|
2317
|
+
cursorPtsTop.splice(i, 0, 0);
|
|
2318
|
+
}
|
|
2319
|
+
fire("addSeries", i);
|
|
2320
|
+
}
|
|
2321
|
+
function addSeries(opts, si) {
|
|
2322
|
+
si = si == null ? series.length : si;
|
|
2323
|
+
opts = mode == 1 ? setDefault(opts, si, xSeriesOpts, ySeriesOpts) : setDefault(opts, si, {}, xySeriesOpts);
|
|
2324
|
+
series.splice(si, 0, opts);
|
|
2325
|
+
initSeries(series[si], si);
|
|
2326
|
+
}
|
|
2327
|
+
self.addSeries = addSeries;
|
|
2328
|
+
function delSeries(i) {
|
|
2329
|
+
series.splice(i, 1);
|
|
2330
|
+
if (showLegend) {
|
|
2331
|
+
legend.values.splice(i, 1);
|
|
2332
|
+
legendCells.splice(i, 1);
|
|
2333
|
+
let tr = legendRows.splice(i, 1)[0];
|
|
2334
|
+
offMouse(null, tr.firstChild);
|
|
2335
|
+
tr.remove();
|
|
2336
|
+
}
|
|
2337
|
+
if (showCursor) {
|
|
2338
|
+
activeIdxs.splice(i, 1);
|
|
2339
|
+
cursorPts.splice(i, 1)[0].remove();
|
|
2340
|
+
cursorPtsLft.splice(i, 1);
|
|
2341
|
+
cursorPtsTop.splice(i, 1);
|
|
2342
|
+
}
|
|
2343
|
+
fire("delSeries", i);
|
|
2344
|
+
}
|
|
2345
|
+
self.delSeries = delSeries;
|
|
2346
|
+
const sidesWithAxes = [
|
|
2347
|
+
false,
|
|
2348
|
+
false,
|
|
2349
|
+
false,
|
|
2350
|
+
false
|
|
2351
|
+
];
|
|
2352
|
+
function initAxis(axis, i) {
|
|
2353
|
+
axis._show = axis.show;
|
|
2354
|
+
if (axis.show) {
|
|
2355
|
+
let isVt = axis.side % 2;
|
|
2356
|
+
let sc = scales[axis.scale];
|
|
2357
|
+
if (sc == null) {
|
|
2358
|
+
axis.scale = isVt ? series[1].scale : xScaleKey;
|
|
2359
|
+
sc = scales[axis.scale];
|
|
2360
|
+
}
|
|
2361
|
+
let isTime = sc.time;
|
|
2362
|
+
axis.size = fnOrSelf(axis.size);
|
|
2363
|
+
axis.space = fnOrSelf(axis.space);
|
|
2364
|
+
axis.rotate = fnOrSelf(axis.rotate);
|
|
2365
|
+
if (isArr(axis.incrs)) axis.incrs.forEach((incr) => {
|
|
2366
|
+
!fixedDec.has(incr) && fixedDec.set(incr, guessDec(incr));
|
|
2367
|
+
});
|
|
2368
|
+
axis.incrs = fnOrSelf(axis.incrs || (sc.distr == 2 ? wholeIncrs : isTime ? ms == 1 ? timeIncrsMs : timeIncrsS : numIncrs));
|
|
2369
|
+
axis.splits = fnOrSelf(axis.splits || (isTime && sc.distr == 1 ? _timeAxisSplits : sc.distr == 3 ? logAxisSplits : sc.distr == 4 ? asinhAxisSplits : numAxisSplits));
|
|
2370
|
+
axis.stroke = fnOrSelf(axis.stroke);
|
|
2371
|
+
axis.grid.stroke = fnOrSelf(axis.grid.stroke);
|
|
2372
|
+
axis.ticks.stroke = fnOrSelf(axis.ticks.stroke);
|
|
2373
|
+
axis.border.stroke = fnOrSelf(axis.border.stroke);
|
|
2374
|
+
let av = axis.values;
|
|
2375
|
+
axis.values = isArr(av) && !isArr(av[0]) ? fnOrSelf(av) : isTime ? isArr(av) ? timeAxisVals(_tzDate, timeAxisStamps(av, _fmtDate)) : isStr(av) ? timeAxisVal(_tzDate, av) : av || _timeAxisVals : av || numAxisVals;
|
|
2376
|
+
axis.filter = fnOrSelf(axis.filter || (sc.distr >= 3 && sc.log == 10 ? log10AxisValsFilt : sc.distr == 3 && sc.log == 2 ? log2AxisValsFilt : retArg1));
|
|
2377
|
+
axis.font = pxRatioFont(axis.font);
|
|
2378
|
+
axis.labelFont = pxRatioFont(axis.labelFont);
|
|
2379
|
+
axis._size = axis.size(self, null, i, 0);
|
|
2380
|
+
axis._space = axis._rotate = axis._incrs = axis._found = axis._splits = axis._values = null;
|
|
2381
|
+
if (axis._size > 0) {
|
|
2382
|
+
sidesWithAxes[i] = true;
|
|
2383
|
+
axis._el = placeDiv(AXIS, wrap);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
function autoPadSide(self, side, sidesWithAxes, cycleNum) {
|
|
2388
|
+
let [hasTopAxis, hasRgtAxis, hasBtmAxis, hasLftAxis] = sidesWithAxes;
|
|
2389
|
+
let ori = side % 2;
|
|
2390
|
+
let size = 0;
|
|
2391
|
+
if (ori == 0 && (hasLftAxis || hasRgtAxis)) size = side == 0 && !hasTopAxis || side == 2 && !hasBtmAxis ? round(xAxisOpts.size / 3) : 0;
|
|
2392
|
+
if (ori == 1 && (hasTopAxis || hasBtmAxis)) size = side == 1 && !hasRgtAxis || side == 3 && !hasLftAxis ? round(yAxisOpts.size / 2) : 0;
|
|
2393
|
+
return size;
|
|
2394
|
+
}
|
|
2395
|
+
const padding = self.padding = (opts.padding || [
|
|
2396
|
+
autoPadSide,
|
|
2397
|
+
autoPadSide,
|
|
2398
|
+
autoPadSide,
|
|
2399
|
+
autoPadSide
|
|
2400
|
+
]).map((p) => fnOrSelf(ifNull(p, autoPadSide)));
|
|
2401
|
+
const _padding = self._padding = padding.map((p, i) => p(self, i, sidesWithAxes, 0));
|
|
2402
|
+
let dataLen;
|
|
2403
|
+
let i0 = null;
|
|
2404
|
+
let i1 = null;
|
|
2405
|
+
const idxs = mode == 1 ? series[0].idxs : null;
|
|
2406
|
+
let data0 = null;
|
|
2407
|
+
let viaAutoScaleX = false;
|
|
2408
|
+
function setData(_data, _resetScales) {
|
|
2409
|
+
data = _data == null ? [] : _data;
|
|
2410
|
+
self.data = self._data = data;
|
|
2411
|
+
if (mode == 2) {
|
|
2412
|
+
dataLen = 0;
|
|
2413
|
+
for (let i = 1; i < series.length; i++) dataLen += data[i][0].length;
|
|
2414
|
+
} else {
|
|
2415
|
+
if (data.length == 0) self.data = self._data = data = [[]];
|
|
2416
|
+
data0 = data[0];
|
|
2417
|
+
dataLen = data0.length;
|
|
2418
|
+
let scaleData = data;
|
|
2419
|
+
if (xScaleDistr == 2) {
|
|
2420
|
+
scaleData = data.slice();
|
|
2421
|
+
let _data0 = scaleData[0] = Array(dataLen);
|
|
2422
|
+
for (let i = 0; i < dataLen; i++) _data0[i] = i;
|
|
2423
|
+
}
|
|
2424
|
+
self._data = data = scaleData;
|
|
2425
|
+
}
|
|
2426
|
+
resetYSeries(true);
|
|
2427
|
+
fire("setData");
|
|
2428
|
+
if (xScaleDistr == 2) shouldConvergeSize = true;
|
|
2429
|
+
if (_resetScales !== false) {
|
|
2430
|
+
let xsc = scaleX;
|
|
2431
|
+
if (xsc.auto(self, viaAutoScaleX)) autoScaleX();
|
|
2432
|
+
else _setScale(xScaleKey, xsc.min, xsc.max);
|
|
2433
|
+
shouldSetCursor = shouldSetCursor || cursor.left >= 0;
|
|
2434
|
+
shouldSetLegend = true;
|
|
2435
|
+
commit();
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
self.setData = setData;
|
|
2439
|
+
function autoScaleX() {
|
|
2440
|
+
viaAutoScaleX = true;
|
|
2441
|
+
let _min, _max;
|
|
2442
|
+
if (mode == 1) if (dataLen > 0) {
|
|
2443
|
+
i0 = idxs[0] = 0;
|
|
2444
|
+
i1 = idxs[1] = dataLen - 1;
|
|
2445
|
+
_min = data[0][i0];
|
|
2446
|
+
_max = data[0][i1];
|
|
2447
|
+
if (xScaleDistr == 2) {
|
|
2448
|
+
_min = i0;
|
|
2449
|
+
_max = i1;
|
|
2450
|
+
} else if (_min == _max) if (xScaleDistr == 3) [_min, _max] = rangeLog(_min, _min, scaleX.log, false);
|
|
2451
|
+
else if (xScaleDistr == 4) [_min, _max] = rangeAsinh(_min, _min, scaleX.log, false);
|
|
2452
|
+
else if (scaleX.time) _max = _min + round(86400 / ms);
|
|
2453
|
+
else [_min, _max] = rangeNum(_min, _max, rangePad, true);
|
|
2454
|
+
} else {
|
|
2455
|
+
i0 = idxs[0] = _min = null;
|
|
2456
|
+
i1 = idxs[1] = _max = null;
|
|
2457
|
+
}
|
|
2458
|
+
_setScale(xScaleKey, _min, _max);
|
|
2459
|
+
}
|
|
2460
|
+
let ctxStroke, ctxFill, ctxWidth, ctxDash, ctxJoin, ctxCap, ctxFont, ctxAlign, ctxBaseline;
|
|
2461
|
+
let ctxAlpha;
|
|
2462
|
+
function setCtxStyle(stroke, width, dash, cap, fill, join) {
|
|
2463
|
+
stroke ??= transparent;
|
|
2464
|
+
dash ??= EMPTY_ARR;
|
|
2465
|
+
cap ??= "butt";
|
|
2466
|
+
fill ??= transparent;
|
|
2467
|
+
join ??= "round";
|
|
2468
|
+
if (stroke != ctxStroke) ctx.strokeStyle = ctxStroke = stroke;
|
|
2469
|
+
if (fill != ctxFill) ctx.fillStyle = ctxFill = fill;
|
|
2470
|
+
if (width != ctxWidth) ctx.lineWidth = ctxWidth = width;
|
|
2471
|
+
if (join != ctxJoin) ctx.lineJoin = ctxJoin = join;
|
|
2472
|
+
if (cap != ctxCap) ctx.lineCap = ctxCap = cap;
|
|
2473
|
+
if (dash != ctxDash) ctx.setLineDash(ctxDash = dash);
|
|
2474
|
+
}
|
|
2475
|
+
function setFontStyle(font, fill, align, baseline) {
|
|
2476
|
+
if (fill != ctxFill) ctx.fillStyle = ctxFill = fill;
|
|
2477
|
+
if (font != ctxFont) ctx.font = ctxFont = font;
|
|
2478
|
+
if (align != ctxAlign) ctx.textAlign = ctxAlign = align;
|
|
2479
|
+
if (baseline != ctxBaseline) ctx.textBaseline = ctxBaseline = baseline;
|
|
2480
|
+
}
|
|
2481
|
+
function accScale(wsc, psc, facet, data, sorted = 0) {
|
|
2482
|
+
if (data.length > 0 && wsc.auto(self, viaAutoScaleX) && (psc == null || psc.min == null)) {
|
|
2483
|
+
let _i0 = ifNull(i0, 0);
|
|
2484
|
+
let _i1 = ifNull(i1, data.length - 1);
|
|
2485
|
+
let minMax = facet.min == null ? getMinMax(data, _i0, _i1, sorted, wsc.distr == 3) : [facet.min, facet.max];
|
|
2486
|
+
wsc.min = min(wsc.min, facet.min = minMax[0]);
|
|
2487
|
+
wsc.max = max(wsc.max, facet.max = minMax[1]);
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
const AUTOSCALE = {
|
|
2491
|
+
min: null,
|
|
2492
|
+
max: null
|
|
2493
|
+
};
|
|
2494
|
+
function setScales() {
|
|
2495
|
+
for (let k in scales) {
|
|
2496
|
+
let sc = scales[k];
|
|
2497
|
+
if (pendScales[k] == null && (sc.min == null || pendScales[xScaleKey] != null && sc.auto(self, viaAutoScaleX))) pendScales[k] = AUTOSCALE;
|
|
2498
|
+
}
|
|
2499
|
+
for (let k in scales) {
|
|
2500
|
+
let sc = scales[k];
|
|
2501
|
+
if (pendScales[k] == null && sc.from != null && pendScales[sc.from] != null) pendScales[k] = AUTOSCALE;
|
|
2502
|
+
}
|
|
2503
|
+
if (pendScales[xScaleKey] != null) resetYSeries(true);
|
|
2504
|
+
let wipScales = {};
|
|
2505
|
+
for (let k in pendScales) {
|
|
2506
|
+
let psc = pendScales[k];
|
|
2507
|
+
if (psc != null) {
|
|
2508
|
+
let wsc = wipScales[k] = copy(scales[k], fastIsObj);
|
|
2509
|
+
if (psc.min != null) assign(wsc, psc);
|
|
2510
|
+
else if (k != xScaleKey || mode == 2) if (dataLen == 0 && wsc.from == null) {
|
|
2511
|
+
let minMax = wsc.range(self, null, null, k);
|
|
2512
|
+
wsc.min = minMax[0];
|
|
2513
|
+
wsc.max = minMax[1];
|
|
2514
|
+
} else {
|
|
2515
|
+
wsc.min = inf;
|
|
2516
|
+
wsc.max = -Infinity;
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
if (dataLen > 0) {
|
|
2521
|
+
series.forEach((s, i) => {
|
|
2522
|
+
if (mode == 1) {
|
|
2523
|
+
let k = s.scale;
|
|
2524
|
+
let psc = pendScales[k];
|
|
2525
|
+
if (psc == null) return;
|
|
2526
|
+
let wsc = wipScales[k];
|
|
2527
|
+
if (i == 0) {
|
|
2528
|
+
let minMax = wsc.range(self, wsc.min, wsc.max, k);
|
|
2529
|
+
wsc.min = minMax[0];
|
|
2530
|
+
wsc.max = minMax[1];
|
|
2531
|
+
i0 = closestIdx(wsc.min, data[0]);
|
|
2532
|
+
i1 = closestIdx(wsc.max, data[0]);
|
|
2533
|
+
if (i1 - i0 > 1) {
|
|
2534
|
+
if (data[0][i0] < wsc.min) i0++;
|
|
2535
|
+
if (data[0][i1] > wsc.max) i1--;
|
|
2536
|
+
}
|
|
2537
|
+
s.min = data0[i0];
|
|
2538
|
+
s.max = data0[i1];
|
|
2539
|
+
} else if (s.show && s.auto) accScale(wsc, psc, s, data[i], s.sorted);
|
|
2540
|
+
s.idxs[0] = i0;
|
|
2541
|
+
s.idxs[1] = i1;
|
|
2542
|
+
} else if (i > 0) {
|
|
2543
|
+
if (s.show && s.auto) {
|
|
2544
|
+
let [xFacet, yFacet] = s.facets;
|
|
2545
|
+
let xScaleKey = xFacet.scale;
|
|
2546
|
+
let yScaleKey = yFacet.scale;
|
|
2547
|
+
let [xData, yData] = data[i];
|
|
2548
|
+
let wscx = wipScales[xScaleKey];
|
|
2549
|
+
let wscy = wipScales[yScaleKey];
|
|
2550
|
+
wscx != null && accScale(wscx, pendScales[xScaleKey], xFacet, xData, xFacet.sorted);
|
|
2551
|
+
wscy != null && accScale(wscy, pendScales[yScaleKey], yFacet, yData, yFacet.sorted);
|
|
2552
|
+
s.min = yFacet.min;
|
|
2553
|
+
s.max = yFacet.max;
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
});
|
|
2557
|
+
for (let k in wipScales) {
|
|
2558
|
+
let wsc = wipScales[k];
|
|
2559
|
+
let psc = pendScales[k];
|
|
2560
|
+
if (wsc.from == null && (psc == null || psc.min == null)) {
|
|
2561
|
+
let minMax = wsc.range(self, wsc.min == inf ? null : wsc.min, wsc.max == -Infinity ? null : wsc.max, k);
|
|
2562
|
+
wsc.min = minMax[0];
|
|
2563
|
+
wsc.max = minMax[1];
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
}
|
|
2567
|
+
for (let k in wipScales) {
|
|
2568
|
+
let wsc = wipScales[k];
|
|
2569
|
+
if (wsc.from != null) {
|
|
2570
|
+
let base = wipScales[wsc.from];
|
|
2571
|
+
if (base.min == null) wsc.min = wsc.max = null;
|
|
2572
|
+
else {
|
|
2573
|
+
let minMax = wsc.range(self, base.min, base.max, k);
|
|
2574
|
+
wsc.min = minMax[0];
|
|
2575
|
+
wsc.max = minMax[1];
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
let changed = {};
|
|
2580
|
+
let anyChanged = false;
|
|
2581
|
+
for (let k in wipScales) {
|
|
2582
|
+
let wsc = wipScales[k];
|
|
2583
|
+
let sc = scales[k];
|
|
2584
|
+
if (sc.min != wsc.min || sc.max != wsc.max) {
|
|
2585
|
+
sc.min = wsc.min;
|
|
2586
|
+
sc.max = wsc.max;
|
|
2587
|
+
let distr = sc.distr;
|
|
2588
|
+
sc._min = distr == 3 ? log10(sc.min) : distr == 4 ? asinh(sc.min, sc.asinh) : distr == 100 ? sc.fwd(sc.min) : sc.min;
|
|
2589
|
+
sc._max = distr == 3 ? log10(sc.max) : distr == 4 ? asinh(sc.max, sc.asinh) : distr == 100 ? sc.fwd(sc.max) : sc.max;
|
|
2590
|
+
changed[k] = anyChanged = true;
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
if (anyChanged) {
|
|
2594
|
+
series.forEach((s, i) => {
|
|
2595
|
+
if (mode == 2) {
|
|
2596
|
+
if (i > 0 && changed.y) s._paths = null;
|
|
2597
|
+
} else if (changed[s.scale]) s._paths = null;
|
|
2598
|
+
});
|
|
2599
|
+
for (let k in changed) {
|
|
2600
|
+
shouldConvergeSize = true;
|
|
2601
|
+
fire("setScale", k);
|
|
2602
|
+
}
|
|
2603
|
+
if (showCursor && cursor.left >= 0) shouldSetCursor = shouldSetLegend = true;
|
|
2604
|
+
}
|
|
2605
|
+
for (let k in pendScales) pendScales[k] = null;
|
|
2606
|
+
}
|
|
2607
|
+
function getOuterIdxs(ydata) {
|
|
2608
|
+
let _i0 = clamp(i0 - 1, 0, dataLen - 1);
|
|
2609
|
+
let _i1 = clamp(i1 + 1, 0, dataLen - 1);
|
|
2610
|
+
while (ydata[_i0] == null && _i0 > 0) _i0--;
|
|
2611
|
+
while (ydata[_i1] == null && _i1 < dataLen - 1) _i1++;
|
|
2612
|
+
return [_i0, _i1];
|
|
2613
|
+
}
|
|
2614
|
+
function drawSeries() {
|
|
2615
|
+
if (dataLen > 0) {
|
|
2616
|
+
let shouldAlpha = series.some((s) => s._focus) && ctxAlpha != focus.alpha;
|
|
2617
|
+
if (shouldAlpha) ctx.globalAlpha = ctxAlpha = focus.alpha;
|
|
2618
|
+
series.forEach((s, i) => {
|
|
2619
|
+
if (i > 0 && s.show) {
|
|
2620
|
+
cacheStrokeFill(i, false);
|
|
2621
|
+
cacheStrokeFill(i, true);
|
|
2622
|
+
if (s._paths == null) {
|
|
2623
|
+
let _ctxAlpha = ctxAlpha;
|
|
2624
|
+
if (ctxAlpha != s.alpha) ctx.globalAlpha = ctxAlpha = s.alpha;
|
|
2625
|
+
let _idxs = mode == 2 ? [0, data[i][0].length - 1] : getOuterIdxs(data[i]);
|
|
2626
|
+
s._paths = s.paths(self, i, _idxs[0], _idxs[1]);
|
|
2627
|
+
if (ctxAlpha != _ctxAlpha) ctx.globalAlpha = ctxAlpha = _ctxAlpha;
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
});
|
|
2631
|
+
series.forEach((s, i) => {
|
|
2632
|
+
if (i > 0 && s.show) {
|
|
2633
|
+
let _ctxAlpha = ctxAlpha;
|
|
2634
|
+
if (ctxAlpha != s.alpha) ctx.globalAlpha = ctxAlpha = s.alpha;
|
|
2635
|
+
s._paths != null && drawPath(i, false);
|
|
2636
|
+
{
|
|
2637
|
+
let _gaps = s._paths != null ? s._paths.gaps : null;
|
|
2638
|
+
let show = s.points.show(self, i, i0, i1, _gaps);
|
|
2639
|
+
let idxs = s.points.filter(self, i, show, _gaps);
|
|
2640
|
+
if (show || idxs) {
|
|
2641
|
+
s.points._paths = s.points.paths(self, i, i0, i1, idxs);
|
|
2642
|
+
drawPath(i, true);
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
if (ctxAlpha != _ctxAlpha) ctx.globalAlpha = ctxAlpha = _ctxAlpha;
|
|
2646
|
+
fire("drawSeries", i);
|
|
2647
|
+
}
|
|
2648
|
+
});
|
|
2649
|
+
if (shouldAlpha) ctx.globalAlpha = ctxAlpha = 1;
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
function cacheStrokeFill(si, _points) {
|
|
2653
|
+
let s = _points ? series[si].points : series[si];
|
|
2654
|
+
s._stroke = s.stroke(self, si);
|
|
2655
|
+
s._fill = s.fill(self, si);
|
|
2656
|
+
}
|
|
2657
|
+
function drawPath(si, _points) {
|
|
2658
|
+
let s = _points ? series[si].points : series[si];
|
|
2659
|
+
let { stroke, fill, clip: gapsClip, flags, _stroke: strokeStyle = s._stroke, _fill: fillStyle = s._fill, _width: width = s.width } = s._paths;
|
|
2660
|
+
width = roundDec(width * pxRatio, 3);
|
|
2661
|
+
let boundsClip = null;
|
|
2662
|
+
let offset = width % 2 / 2;
|
|
2663
|
+
if (_points && fillStyle == null) fillStyle = width > 0 ? "#fff" : strokeStyle;
|
|
2664
|
+
let _pxAlign = s.pxAlign == 1 && offset > 0;
|
|
2665
|
+
_pxAlign && ctx.translate(offset, offset);
|
|
2666
|
+
if (!_points) {
|
|
2667
|
+
let lft = plotLft - width / 2, top = plotTop - width / 2, wid = plotWid + width, hgt = plotHgt + width;
|
|
2668
|
+
boundsClip = new Path2D();
|
|
2669
|
+
boundsClip.rect(lft, top, wid, hgt);
|
|
2670
|
+
}
|
|
2671
|
+
if (_points) strokeFill(strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, gapsClip);
|
|
2672
|
+
else fillStroke(si, strokeStyle, width, s.dash, s.cap, fillStyle, stroke, fill, flags, boundsClip, gapsClip);
|
|
2673
|
+
_pxAlign && ctx.translate(-offset, -offset);
|
|
2674
|
+
}
|
|
2675
|
+
function fillStroke(si, strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip) {
|
|
2676
|
+
let didStrokeFill = false;
|
|
2677
|
+
flags != 0 && bands.forEach((b, bi) => {
|
|
2678
|
+
if (b.series[0] == si) {
|
|
2679
|
+
let lowerEdge = series[b.series[1]];
|
|
2680
|
+
let lowerData = data[b.series[1]];
|
|
2681
|
+
let bandClip = (lowerEdge._paths || EMPTY_OBJ).band;
|
|
2682
|
+
if (isArr(bandClip)) bandClip = b.dir == 1 ? bandClip[0] : bandClip[1];
|
|
2683
|
+
let gapsClip2;
|
|
2684
|
+
let _fillStyle = null;
|
|
2685
|
+
if (lowerEdge.show && bandClip && hasData(lowerData, i0, i1)) {
|
|
2686
|
+
_fillStyle = b.fill(self, bi) || fillStyle;
|
|
2687
|
+
gapsClip2 = lowerEdge._paths.clip;
|
|
2688
|
+
} else bandClip = null;
|
|
2689
|
+
strokeFill(strokeStyle, lineWidth, lineDash, lineCap, _fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip);
|
|
2690
|
+
didStrokeFill = true;
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
if (!didStrokeFill) strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip);
|
|
2694
|
+
}
|
|
2695
|
+
const CLIP_FILL_STROKE = 3;
|
|
2696
|
+
function strokeFill(strokeStyle, lineWidth, lineDash, lineCap, fillStyle, strokePath, fillPath, flags, boundsClip, gapsClip, gapsClip2, bandClip) {
|
|
2697
|
+
setCtxStyle(strokeStyle, lineWidth, lineDash, lineCap, fillStyle);
|
|
2698
|
+
if (boundsClip || gapsClip || bandClip) {
|
|
2699
|
+
ctx.save();
|
|
2700
|
+
boundsClip && ctx.clip(boundsClip);
|
|
2701
|
+
gapsClip && ctx.clip(gapsClip);
|
|
2702
|
+
}
|
|
2703
|
+
if (bandClip) {
|
|
2704
|
+
if ((flags & CLIP_FILL_STROKE) == CLIP_FILL_STROKE) {
|
|
2705
|
+
ctx.clip(bandClip);
|
|
2706
|
+
gapsClip2 && ctx.clip(gapsClip2);
|
|
2707
|
+
doFill(fillStyle, fillPath);
|
|
2708
|
+
doStroke(strokeStyle, strokePath, lineWidth);
|
|
2709
|
+
} else if (flags & BAND_CLIP_STROKE) {
|
|
2710
|
+
doFill(fillStyle, fillPath);
|
|
2711
|
+
ctx.clip(bandClip);
|
|
2712
|
+
doStroke(strokeStyle, strokePath, lineWidth);
|
|
2713
|
+
} else if (flags & BAND_CLIP_FILL) {
|
|
2714
|
+
ctx.save();
|
|
2715
|
+
ctx.clip(bandClip);
|
|
2716
|
+
gapsClip2 && ctx.clip(gapsClip2);
|
|
2717
|
+
doFill(fillStyle, fillPath);
|
|
2718
|
+
ctx.restore();
|
|
2719
|
+
doStroke(strokeStyle, strokePath, lineWidth);
|
|
2720
|
+
}
|
|
2721
|
+
} else {
|
|
2722
|
+
doFill(fillStyle, fillPath);
|
|
2723
|
+
doStroke(strokeStyle, strokePath, lineWidth);
|
|
2724
|
+
}
|
|
2725
|
+
if (boundsClip || gapsClip || bandClip) ctx.restore();
|
|
2726
|
+
}
|
|
2727
|
+
function doStroke(strokeStyle, strokePath, lineWidth) {
|
|
2728
|
+
if (lineWidth > 0) if (strokePath instanceof Map) strokePath.forEach((strokePath, strokeStyle) => {
|
|
2729
|
+
ctx.strokeStyle = ctxStroke = strokeStyle;
|
|
2730
|
+
ctx.stroke(strokePath);
|
|
2731
|
+
});
|
|
2732
|
+
else strokePath != null && strokeStyle && ctx.stroke(strokePath);
|
|
2733
|
+
}
|
|
2734
|
+
function doFill(fillStyle, fillPath) {
|
|
2735
|
+
if (fillPath instanceof Map) fillPath.forEach((fillPath, fillStyle) => {
|
|
2736
|
+
ctx.fillStyle = ctxFill = fillStyle;
|
|
2737
|
+
ctx.fill(fillPath);
|
|
2738
|
+
});
|
|
2739
|
+
else fillPath != null && fillStyle && ctx.fill(fillPath);
|
|
2740
|
+
}
|
|
2741
|
+
function getIncrSpace(axisIdx, min, max, fullDim) {
|
|
2742
|
+
let axis = axes[axisIdx];
|
|
2743
|
+
let incrSpace;
|
|
2744
|
+
if (fullDim <= 0) incrSpace = [0, 0];
|
|
2745
|
+
else {
|
|
2746
|
+
let minSpace = axis._space = axis.space(self, axisIdx, min, max, fullDim);
|
|
2747
|
+
incrSpace = findIncr(min, max, axis._incrs = axis.incrs(self, axisIdx, min, max, fullDim, minSpace), fullDim, minSpace);
|
|
2748
|
+
}
|
|
2749
|
+
return axis._found = incrSpace;
|
|
2750
|
+
}
|
|
2751
|
+
function drawOrthoLines(offs, filts, ori, side, pos0, len, width, stroke, dash, cap) {
|
|
2752
|
+
let offset = width % 2 / 2;
|
|
2753
|
+
pxAlign == 1 && ctx.translate(offset, offset);
|
|
2754
|
+
setCtxStyle(stroke, width, dash, cap, stroke);
|
|
2755
|
+
ctx.beginPath();
|
|
2756
|
+
let x0, y0, x1, y1, pos1 = pos0 + (side == 0 || side == 3 ? -len : len);
|
|
2757
|
+
if (ori == 0) {
|
|
2758
|
+
y0 = pos0;
|
|
2759
|
+
y1 = pos1;
|
|
2760
|
+
} else {
|
|
2761
|
+
x0 = pos0;
|
|
2762
|
+
x1 = pos1;
|
|
2763
|
+
}
|
|
2764
|
+
for (let i = 0; i < offs.length; i++) if (filts[i] != null) {
|
|
2765
|
+
if (ori == 0) x0 = x1 = offs[i];
|
|
2766
|
+
else y0 = y1 = offs[i];
|
|
2767
|
+
ctx.moveTo(x0, y0);
|
|
2768
|
+
ctx.lineTo(x1, y1);
|
|
2769
|
+
}
|
|
2770
|
+
ctx.stroke();
|
|
2771
|
+
pxAlign == 1 && ctx.translate(-offset, -offset);
|
|
2772
|
+
}
|
|
2773
|
+
function axesCalc(cycleNum) {
|
|
2774
|
+
let converged = true;
|
|
2775
|
+
axes.forEach((axis, i) => {
|
|
2776
|
+
if (!axis.show) return;
|
|
2777
|
+
let scale = scales[axis.scale];
|
|
2778
|
+
if (scale.min == null) {
|
|
2779
|
+
if (axis._show) {
|
|
2780
|
+
converged = false;
|
|
2781
|
+
axis._show = false;
|
|
2782
|
+
resetYSeries(false);
|
|
2783
|
+
}
|
|
2784
|
+
return;
|
|
2785
|
+
} else if (!axis._show) {
|
|
2786
|
+
converged = false;
|
|
2787
|
+
axis._show = true;
|
|
2788
|
+
resetYSeries(false);
|
|
2789
|
+
}
|
|
2790
|
+
let side = axis.side;
|
|
2791
|
+
let ori = side % 2;
|
|
2792
|
+
let { min, max } = scale;
|
|
2793
|
+
let [_incr, _space] = getIncrSpace(i, min, max, ori == 0 ? plotWidCss : plotHgtCss);
|
|
2794
|
+
if (_space == 0) return;
|
|
2795
|
+
let forceMin = scale.distr == 2;
|
|
2796
|
+
let _splits = axis._splits = axis.splits(self, i, min, max, _incr, _space, forceMin);
|
|
2797
|
+
let splits = scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits;
|
|
2798
|
+
let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr;
|
|
2799
|
+
let values = axis._values = axis.values(self, axis.filter(self, splits, i, _space, incr), i, _space, incr);
|
|
2800
|
+
axis._rotate = side == 2 ? axis.rotate(self, values, i, _space) : 0;
|
|
2801
|
+
let oldSize = axis._size;
|
|
2802
|
+
axis._size = ceil(axis.size(self, values, i, cycleNum));
|
|
2803
|
+
if (oldSize != null && axis._size != oldSize) converged = false;
|
|
2804
|
+
});
|
|
2805
|
+
return converged;
|
|
2806
|
+
}
|
|
2807
|
+
function paddingCalc(cycleNum) {
|
|
2808
|
+
let converged = true;
|
|
2809
|
+
padding.forEach((p, i) => {
|
|
2810
|
+
let _p = p(self, i, sidesWithAxes, cycleNum);
|
|
2811
|
+
if (_p != _padding[i]) converged = false;
|
|
2812
|
+
_padding[i] = _p;
|
|
2813
|
+
});
|
|
2814
|
+
return converged;
|
|
2815
|
+
}
|
|
2816
|
+
function drawAxesGrid() {
|
|
2817
|
+
for (let i = 0; i < axes.length; i++) {
|
|
2818
|
+
let axis = axes[i];
|
|
2819
|
+
if (!axis.show || !axis._show) continue;
|
|
2820
|
+
let side = axis.side;
|
|
2821
|
+
let ori = side % 2;
|
|
2822
|
+
let x, y;
|
|
2823
|
+
let fillStyle = axis.stroke(self, i);
|
|
2824
|
+
let shiftDir = side == 0 || side == 3 ? -1 : 1;
|
|
2825
|
+
let [_incr, _space] = axis._found;
|
|
2826
|
+
if (axis.label != null) {
|
|
2827
|
+
let shiftAmt = axis.labelGap * shiftDir;
|
|
2828
|
+
let baseLpos = round((axis._lpos + shiftAmt) * pxRatio);
|
|
2829
|
+
setFontStyle(axis.labelFont[0], fillStyle, "center", side == 2 ? TOP : BOTTOM);
|
|
2830
|
+
ctx.save();
|
|
2831
|
+
if (ori == 1) {
|
|
2832
|
+
x = y = 0;
|
|
2833
|
+
ctx.translate(baseLpos, round(plotTop + plotHgt / 2));
|
|
2834
|
+
ctx.rotate((side == 3 ? -PI : PI) / 2);
|
|
2835
|
+
} else {
|
|
2836
|
+
x = round(plotLft + plotWid / 2);
|
|
2837
|
+
y = baseLpos;
|
|
2838
|
+
}
|
|
2839
|
+
let _label = isFn(axis.label) ? axis.label(self, i, _incr, _space) : axis.label;
|
|
2840
|
+
ctx.fillText(_label, x, y);
|
|
2841
|
+
ctx.restore();
|
|
2842
|
+
}
|
|
2843
|
+
if (_space == 0) continue;
|
|
2844
|
+
let scale = scales[axis.scale];
|
|
2845
|
+
let plotDim = ori == 0 ? plotWid : plotHgt;
|
|
2846
|
+
let plotOff = ori == 0 ? plotLft : plotTop;
|
|
2847
|
+
let _splits = axis._splits;
|
|
2848
|
+
let splits = scale.distr == 2 ? _splits.map((i) => data0[i]) : _splits;
|
|
2849
|
+
let incr = scale.distr == 2 ? data0[_splits[1]] - data0[_splits[0]] : _incr;
|
|
2850
|
+
let ticks = axis.ticks;
|
|
2851
|
+
let border = axis.border;
|
|
2852
|
+
let _tickSize = ticks.show ? ticks.size : 0;
|
|
2853
|
+
let tickSize = round(_tickSize * pxRatio);
|
|
2854
|
+
let axisGap = round((axis.alignTo == 2 ? axis._size - _tickSize - axis.gap : axis.gap) * pxRatio);
|
|
2855
|
+
let angle = axis._rotate * -PI / 180;
|
|
2856
|
+
let basePos = pxRound(axis._pos * pxRatio);
|
|
2857
|
+
let finalPos = basePos + (tickSize + axisGap) * shiftDir;
|
|
2858
|
+
y = ori == 0 ? finalPos : 0;
|
|
2859
|
+
x = ori == 1 ? finalPos : 0;
|
|
2860
|
+
let font = axis.font[0];
|
|
2861
|
+
setFontStyle(font, fillStyle, axis.align == 1 ? LEFT : axis.align == 2 ? RIGHT : angle > 0 ? LEFT : angle < 0 ? RIGHT : ori == 0 ? "center" : side == 3 ? RIGHT : LEFT, angle || ori == 1 ? "middle" : side == 2 ? TOP : BOTTOM);
|
|
2862
|
+
let lineHeight = axis.font[1] * axis.lineGap;
|
|
2863
|
+
let canOffs = _splits.map((val) => pxRound(getPos(val, scale, plotDim, plotOff)));
|
|
2864
|
+
let _values = axis._values;
|
|
2865
|
+
for (let i = 0; i < _values.length; i++) {
|
|
2866
|
+
let val = _values[i];
|
|
2867
|
+
if (val != null) {
|
|
2868
|
+
if (ori == 0) x = canOffs[i];
|
|
2869
|
+
else y = canOffs[i];
|
|
2870
|
+
val = "" + val;
|
|
2871
|
+
let _parts = val.indexOf("\n") == -1 ? [val] : val.split(/\n/gm);
|
|
2872
|
+
for (let j = 0; j < _parts.length; j++) {
|
|
2873
|
+
let text = _parts[j];
|
|
2874
|
+
if (angle) {
|
|
2875
|
+
ctx.save();
|
|
2876
|
+
ctx.translate(x, y + j * lineHeight);
|
|
2877
|
+
ctx.rotate(angle);
|
|
2878
|
+
ctx.fillText(text, 0, 0);
|
|
2879
|
+
ctx.restore();
|
|
2880
|
+
} else ctx.fillText(text, x, y + j * lineHeight);
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
if (ticks.show) drawOrthoLines(canOffs, ticks.filter(self, splits, i, _space, incr), ori, side, basePos, tickSize, roundDec(ticks.width * pxRatio, 3), ticks.stroke(self, i), ticks.dash, ticks.cap);
|
|
2885
|
+
let grid = axis.grid;
|
|
2886
|
+
if (grid.show) drawOrthoLines(canOffs, grid.filter(self, splits, i, _space, incr), ori, ori == 0 ? 2 : 1, ori == 0 ? plotTop : plotLft, ori == 0 ? plotHgt : plotWid, roundDec(grid.width * pxRatio, 3), grid.stroke(self, i), grid.dash, grid.cap);
|
|
2887
|
+
if (border.show) drawOrthoLines([basePos], [1], ori == 0 ? 1 : 0, ori == 0 ? 1 : 2, ori == 1 ? plotTop : plotLft, ori == 1 ? plotHgt : plotWid, roundDec(border.width * pxRatio, 3), border.stroke(self, i), border.dash, border.cap);
|
|
2888
|
+
}
|
|
2889
|
+
fire("drawAxes");
|
|
2890
|
+
}
|
|
2891
|
+
function resetYSeries(minMax) {
|
|
2892
|
+
series.forEach((s, i) => {
|
|
2893
|
+
if (i > 0) {
|
|
2894
|
+
s._paths = null;
|
|
2895
|
+
if (minMax) if (mode == 1) {
|
|
2896
|
+
s.min = null;
|
|
2897
|
+
s.max = null;
|
|
2898
|
+
} else s.facets.forEach((f) => {
|
|
2899
|
+
f.min = null;
|
|
2900
|
+
f.max = null;
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
});
|
|
2904
|
+
}
|
|
2905
|
+
let queuedCommit = false;
|
|
2906
|
+
let deferHooks = false;
|
|
2907
|
+
let hooksQueue = [];
|
|
2908
|
+
function flushHooks() {
|
|
2909
|
+
deferHooks = false;
|
|
2910
|
+
for (let i = 0; i < hooksQueue.length; i++) fire(...hooksQueue[i]);
|
|
2911
|
+
hooksQueue.length = 0;
|
|
2912
|
+
}
|
|
2913
|
+
function commit() {
|
|
2914
|
+
if (!queuedCommit) {
|
|
2915
|
+
microTask(_commit);
|
|
2916
|
+
queuedCommit = true;
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
function batch(fn, _deferHooks = false) {
|
|
2920
|
+
queuedCommit = true;
|
|
2921
|
+
deferHooks = _deferHooks;
|
|
2922
|
+
fn(self);
|
|
2923
|
+
_commit();
|
|
2924
|
+
if (_deferHooks && hooksQueue.length > 0) queueMicrotask(flushHooks);
|
|
2925
|
+
}
|
|
2926
|
+
self.batch = batch;
|
|
2927
|
+
function _commit() {
|
|
2928
|
+
if (shouldSetScales) {
|
|
2929
|
+
setScales();
|
|
2930
|
+
shouldSetScales = false;
|
|
2931
|
+
}
|
|
2932
|
+
if (shouldConvergeSize) {
|
|
2933
|
+
convergeSize();
|
|
2934
|
+
shouldConvergeSize = false;
|
|
2935
|
+
}
|
|
2936
|
+
if (shouldSetSize) {
|
|
2937
|
+
setStylePx(under, LEFT, plotLftCss);
|
|
2938
|
+
setStylePx(under, TOP, plotTopCss);
|
|
2939
|
+
setStylePx(under, WIDTH, plotWidCss);
|
|
2940
|
+
setStylePx(under, HEIGHT, plotHgtCss);
|
|
2941
|
+
setStylePx(over, LEFT, plotLftCss);
|
|
2942
|
+
setStylePx(over, TOP, plotTopCss);
|
|
2943
|
+
setStylePx(over, WIDTH, plotWidCss);
|
|
2944
|
+
setStylePx(over, HEIGHT, plotHgtCss);
|
|
2945
|
+
setStylePx(wrap, WIDTH, fullWidCss);
|
|
2946
|
+
setStylePx(wrap, HEIGHT, fullHgtCss);
|
|
2947
|
+
can.width = round(fullWidCss * pxRatio);
|
|
2948
|
+
can.height = round(fullHgtCss * pxRatio);
|
|
2949
|
+
axes.forEach(({ _el, _show, _size, _pos, side }) => {
|
|
2950
|
+
if (_el != null) if (_show) {
|
|
2951
|
+
let posOffset = side === 3 || side === 0 ? _size : 0;
|
|
2952
|
+
let isVt = side % 2 == 1;
|
|
2953
|
+
setStylePx(_el, isVt ? "left" : "top", _pos - posOffset);
|
|
2954
|
+
setStylePx(_el, isVt ? "width" : "height", _size);
|
|
2955
|
+
setStylePx(_el, isVt ? "top" : "left", isVt ? plotTopCss : plotLftCss);
|
|
2956
|
+
setStylePx(_el, isVt ? "height" : "width", isVt ? plotHgtCss : plotWidCss);
|
|
2957
|
+
remClass(_el, OFF);
|
|
2958
|
+
} else addClass(_el, OFF);
|
|
2959
|
+
});
|
|
2960
|
+
ctxStroke = ctxFill = ctxWidth = ctxJoin = ctxCap = ctxFont = ctxAlign = ctxBaseline = ctxDash = null;
|
|
2961
|
+
ctxAlpha = 1;
|
|
2962
|
+
syncRect(true);
|
|
2963
|
+
if (plotLftCss != _plotLftCss || plotTopCss != _plotTopCss || plotWidCss != _plotWidCss || plotHgtCss != _plotHgtCss) {
|
|
2964
|
+
resetYSeries(false);
|
|
2965
|
+
let pctWid = plotWidCss / _plotWidCss;
|
|
2966
|
+
let pctHgt = plotHgtCss / _plotHgtCss;
|
|
2967
|
+
if (showCursor && !shouldSetCursor && cursor.left >= 0) {
|
|
2968
|
+
cursor.left *= pctWid;
|
|
2969
|
+
cursor.top *= pctHgt;
|
|
2970
|
+
vCursor && elTrans(vCursor, round(cursor.left), 0, plotWidCss, plotHgtCss);
|
|
2971
|
+
hCursor && elTrans(hCursor, 0, round(cursor.top), plotWidCss, plotHgtCss);
|
|
2972
|
+
for (let i = 0; i < cursorPts.length; i++) {
|
|
2973
|
+
let pt = cursorPts[i];
|
|
2974
|
+
if (pt != null) {
|
|
2975
|
+
cursorPtsLft[i] *= pctWid;
|
|
2976
|
+
cursorPtsTop[i] *= pctHgt;
|
|
2977
|
+
elTrans(pt, ceil(cursorPtsLft[i]), ceil(cursorPtsTop[i]), plotWidCss, plotHgtCss);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
if (select.show && !shouldSetSelect && select.left >= 0 && select.width > 0) {
|
|
2982
|
+
select.left *= pctWid;
|
|
2983
|
+
select.width *= pctWid;
|
|
2984
|
+
select.top *= pctHgt;
|
|
2985
|
+
select.height *= pctHgt;
|
|
2986
|
+
for (let prop in _hideProps) setStylePx(selectDiv, prop, select[prop]);
|
|
2987
|
+
}
|
|
2988
|
+
_plotLftCss = plotLftCss;
|
|
2989
|
+
_plotTopCss = plotTopCss;
|
|
2990
|
+
_plotWidCss = plotWidCss;
|
|
2991
|
+
_plotHgtCss = plotHgtCss;
|
|
2992
|
+
}
|
|
2993
|
+
fire("setSize");
|
|
2994
|
+
shouldSetSize = false;
|
|
2995
|
+
}
|
|
2996
|
+
if (fullWidCss > 0 && fullHgtCss > 0) {
|
|
2997
|
+
ctx.clearRect(0, 0, can.width, can.height);
|
|
2998
|
+
fire("drawClear");
|
|
2999
|
+
drawOrder.forEach((fn) => fn());
|
|
3000
|
+
fire("draw");
|
|
3001
|
+
}
|
|
3002
|
+
if (select.show && shouldSetSelect) {
|
|
3003
|
+
setSelect(select);
|
|
3004
|
+
shouldSetSelect = false;
|
|
3005
|
+
}
|
|
3006
|
+
if (showCursor && shouldSetCursor) {
|
|
3007
|
+
updateCursor(null, true, false);
|
|
3008
|
+
shouldSetCursor = false;
|
|
3009
|
+
}
|
|
3010
|
+
if (legend.show && legend.live && shouldSetLegend) {
|
|
3011
|
+
setLegend();
|
|
3012
|
+
shouldSetLegend = false;
|
|
3013
|
+
}
|
|
3014
|
+
if (!ready) {
|
|
3015
|
+
ready = true;
|
|
3016
|
+
self.status = 1;
|
|
3017
|
+
fire("ready");
|
|
3018
|
+
}
|
|
3019
|
+
viaAutoScaleX = false;
|
|
3020
|
+
queuedCommit = false;
|
|
3021
|
+
}
|
|
3022
|
+
self.redraw = (rebuildPaths, recalcAxes) => {
|
|
3023
|
+
shouldConvergeSize = recalcAxes || false;
|
|
3024
|
+
if (rebuildPaths !== false) _setScale(xScaleKey, scaleX.min, scaleX.max);
|
|
3025
|
+
else commit();
|
|
3026
|
+
};
|
|
3027
|
+
function setScale(key, opts) {
|
|
3028
|
+
let sc = scales[key];
|
|
3029
|
+
if (sc.from == null) {
|
|
3030
|
+
if (dataLen == 0) {
|
|
3031
|
+
let minMax = sc.range(self, opts.min, opts.max, key);
|
|
3032
|
+
opts.min = minMax[0];
|
|
3033
|
+
opts.max = minMax[1];
|
|
3034
|
+
}
|
|
3035
|
+
if (opts.min > opts.max) {
|
|
3036
|
+
let _min = opts.min;
|
|
3037
|
+
opts.min = opts.max;
|
|
3038
|
+
opts.max = _min;
|
|
3039
|
+
}
|
|
3040
|
+
if (dataLen > 1 && opts.min != null && opts.max != null && opts.max - opts.min < 1e-16) return;
|
|
3041
|
+
if (key == xScaleKey) {
|
|
3042
|
+
if (sc.distr == 2 && dataLen > 0) {
|
|
3043
|
+
opts.min = closestIdx(opts.min, data[0]);
|
|
3044
|
+
opts.max = closestIdx(opts.max, data[0]);
|
|
3045
|
+
if (opts.min == opts.max) opts.max++;
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
pendScales[key] = opts;
|
|
3049
|
+
shouldSetScales = true;
|
|
3050
|
+
commit();
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
self.setScale = setScale;
|
|
3054
|
+
let xCursor;
|
|
3055
|
+
let yCursor;
|
|
3056
|
+
let vCursor;
|
|
3057
|
+
let hCursor;
|
|
3058
|
+
let rawMouseLeft0;
|
|
3059
|
+
let rawMouseTop0;
|
|
3060
|
+
let mouseLeft0;
|
|
3061
|
+
let mouseTop0;
|
|
3062
|
+
let rawMouseLeft1;
|
|
3063
|
+
let rawMouseTop1;
|
|
3064
|
+
let mouseLeft1;
|
|
3065
|
+
let mouseTop1;
|
|
3066
|
+
let dragging = false;
|
|
3067
|
+
const drag = cursor.drag;
|
|
3068
|
+
let dragX = drag.x;
|
|
3069
|
+
let dragY = drag.y;
|
|
3070
|
+
if (showCursor) {
|
|
3071
|
+
if (cursor.x) xCursor = placeDiv(CURSOR_X, over);
|
|
3072
|
+
if (cursor.y) yCursor = placeDiv(CURSOR_Y, over);
|
|
3073
|
+
if (scaleX.ori == 0) {
|
|
3074
|
+
vCursor = xCursor;
|
|
3075
|
+
hCursor = yCursor;
|
|
3076
|
+
} else {
|
|
3077
|
+
vCursor = yCursor;
|
|
3078
|
+
hCursor = xCursor;
|
|
3079
|
+
}
|
|
3080
|
+
mouseLeft1 = cursor.left;
|
|
3081
|
+
mouseTop1 = cursor.top;
|
|
3082
|
+
}
|
|
3083
|
+
const select = self.select = assign({
|
|
3084
|
+
show: true,
|
|
3085
|
+
over: true,
|
|
3086
|
+
left: 0,
|
|
3087
|
+
width: 0,
|
|
3088
|
+
top: 0,
|
|
3089
|
+
height: 0
|
|
3090
|
+
}, opts.select);
|
|
3091
|
+
const selectDiv = select.show ? placeDiv(SELECT, select.over ? over : under) : null;
|
|
3092
|
+
function setSelect(opts, _fire) {
|
|
3093
|
+
if (select.show) {
|
|
3094
|
+
for (let prop in opts) {
|
|
3095
|
+
select[prop] = opts[prop];
|
|
3096
|
+
if (prop in _hideProps) setStylePx(selectDiv, prop, opts[prop]);
|
|
3097
|
+
}
|
|
3098
|
+
_fire !== false && fire("setSelect");
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
self.setSelect = setSelect;
|
|
3102
|
+
function toggleDOM(i) {
|
|
3103
|
+
if (series[i].show) showLegend && remClass(legendRows[i], OFF);
|
|
3104
|
+
else {
|
|
3105
|
+
showLegend && addClass(legendRows[i], OFF);
|
|
3106
|
+
if (showCursor) {
|
|
3107
|
+
let pt = cursorOnePt ? cursorPts[0] : cursorPts[i];
|
|
3108
|
+
pt != null && elTrans(pt, -10, -10, plotWidCss, plotHgtCss);
|
|
3109
|
+
}
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
function _setScale(key, min, max) {
|
|
3113
|
+
setScale(key, {
|
|
3114
|
+
min,
|
|
3115
|
+
max
|
|
3116
|
+
});
|
|
3117
|
+
}
|
|
3118
|
+
function setSeries(i, opts, _fire, _pub) {
|
|
3119
|
+
if (opts.focus != null) setFocus(i);
|
|
3120
|
+
if (opts.show != null) series.forEach((s, si) => {
|
|
3121
|
+
if (si > 0 && (i == si || i == null)) {
|
|
3122
|
+
s.show = opts.show;
|
|
3123
|
+
toggleDOM(si);
|
|
3124
|
+
if (mode == 2) {
|
|
3125
|
+
_setScale(s.facets[0].scale, null, null);
|
|
3126
|
+
_setScale(s.facets[1].scale, null, null);
|
|
3127
|
+
} else _setScale(s.scale, null, null);
|
|
3128
|
+
commit();
|
|
3129
|
+
}
|
|
3130
|
+
});
|
|
3131
|
+
_fire !== false && fire("setSeries", i, opts);
|
|
3132
|
+
_pub && pubSync("setSeries", self, i, opts);
|
|
3133
|
+
}
|
|
3134
|
+
self.setSeries = setSeries;
|
|
3135
|
+
function setBand(bi, opts) {
|
|
3136
|
+
assign(bands[bi], opts);
|
|
3137
|
+
}
|
|
3138
|
+
function addBand(opts, bi) {
|
|
3139
|
+
opts.fill = fnOrSelf(opts.fill || null);
|
|
3140
|
+
opts.dir = ifNull(opts.dir, -1);
|
|
3141
|
+
bi = bi == null ? bands.length : bi;
|
|
3142
|
+
bands.splice(bi, 0, opts);
|
|
3143
|
+
}
|
|
3144
|
+
function delBand(bi) {
|
|
3145
|
+
if (bi == null) bands.length = 0;
|
|
3146
|
+
else bands.splice(bi, 1);
|
|
3147
|
+
}
|
|
3148
|
+
self.addBand = addBand;
|
|
3149
|
+
self.setBand = setBand;
|
|
3150
|
+
self.delBand = delBand;
|
|
3151
|
+
function setAlpha(i, value) {
|
|
3152
|
+
series[i].alpha = value;
|
|
3153
|
+
if (showCursor && cursorPts[i] != null) cursorPts[i].style.opacity = value;
|
|
3154
|
+
if (showLegend && legendRows[i]) legendRows[i].style.opacity = value;
|
|
3155
|
+
}
|
|
3156
|
+
let closestDist;
|
|
3157
|
+
let closestSeries;
|
|
3158
|
+
let focusedSeries;
|
|
3159
|
+
const FOCUS_TRUE = { focus: true };
|
|
3160
|
+
function setFocus(i) {
|
|
3161
|
+
if (i != focusedSeries) {
|
|
3162
|
+
let allFocused = i == null;
|
|
3163
|
+
let _setAlpha = focus.alpha != 1;
|
|
3164
|
+
series.forEach((s, i2) => {
|
|
3165
|
+
if (mode == 1 || i2 > 0) {
|
|
3166
|
+
let isFocused = allFocused || i2 == 0 || i2 == i;
|
|
3167
|
+
s._focus = allFocused ? null : isFocused;
|
|
3168
|
+
_setAlpha && setAlpha(i2, isFocused ? 1 : focus.alpha);
|
|
3169
|
+
}
|
|
3170
|
+
});
|
|
3171
|
+
focusedSeries = i;
|
|
3172
|
+
_setAlpha && commit();
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
if (showLegend && cursorFocus) onMouse(mouseleave, legendTable, (e) => {
|
|
3176
|
+
if (cursor._lock) return;
|
|
3177
|
+
setCursorEvent(e);
|
|
3178
|
+
if (focusedSeries != null) setSeries(null, FOCUS_TRUE, true, syncOpts.setSeries);
|
|
3179
|
+
});
|
|
3180
|
+
function posToVal(pos, scale, can) {
|
|
3181
|
+
let sc = scales[scale];
|
|
3182
|
+
if (can) pos = pos / pxRatio - (sc.ori == 1 ? plotTopCss : plotLftCss);
|
|
3183
|
+
let dim = plotWidCss;
|
|
3184
|
+
if (sc.ori == 1) {
|
|
3185
|
+
dim = plotHgtCss;
|
|
3186
|
+
pos = dim - pos;
|
|
3187
|
+
}
|
|
3188
|
+
if (sc.dir == -1) pos = dim - pos;
|
|
3189
|
+
let _min = sc._min, _max = sc._max, pct = pos / dim;
|
|
3190
|
+
let sv = _min + (_max - _min) * pct;
|
|
3191
|
+
let distr = sc.distr;
|
|
3192
|
+
return distr == 3 ? pow(10, sv) : distr == 4 ? sinh(sv, sc.asinh) : distr == 100 ? sc.bwd(sv) : sv;
|
|
3193
|
+
}
|
|
3194
|
+
function closestIdxFromXpos(pos, can) {
|
|
3195
|
+
return closestIdx(posToVal(pos, xScaleKey, can), data[0], i0, i1);
|
|
3196
|
+
}
|
|
3197
|
+
self.valToIdx = (val) => closestIdx(val, data[0]);
|
|
3198
|
+
self.posToIdx = closestIdxFromXpos;
|
|
3199
|
+
self.posToVal = posToVal;
|
|
3200
|
+
self.valToPos = (val, scale, can) => scales[scale].ori == 0 ? getHPos(val, scales[scale], can ? plotWid : plotWidCss, can ? plotLft : 0) : getVPos(val, scales[scale], can ? plotHgt : plotHgtCss, can ? plotTop : 0);
|
|
3201
|
+
self.setCursor = (opts, _fire, _pub) => {
|
|
3202
|
+
mouseLeft1 = opts.left;
|
|
3203
|
+
mouseTop1 = opts.top;
|
|
3204
|
+
updateCursor(null, _fire, _pub);
|
|
3205
|
+
};
|
|
3206
|
+
function setSelH(off, dim) {
|
|
3207
|
+
setStylePx(selectDiv, LEFT, select.left = off);
|
|
3208
|
+
setStylePx(selectDiv, WIDTH, select.width = dim);
|
|
3209
|
+
}
|
|
3210
|
+
function setSelV(off, dim) {
|
|
3211
|
+
setStylePx(selectDiv, TOP, select.top = off);
|
|
3212
|
+
setStylePx(selectDiv, HEIGHT, select.height = dim);
|
|
3213
|
+
}
|
|
3214
|
+
let setSelX = scaleX.ori == 0 ? setSelH : setSelV;
|
|
3215
|
+
let setSelY = scaleX.ori == 1 ? setSelH : setSelV;
|
|
3216
|
+
function syncLegend() {
|
|
3217
|
+
if (showLegend && legend.live) for (let i = mode == 2 ? 1 : 0; i < series.length; i++) {
|
|
3218
|
+
if (i == 0 && multiValLegend) continue;
|
|
3219
|
+
let vals = legend.values[i];
|
|
3220
|
+
let j = 0;
|
|
3221
|
+
for (let k in vals) legendCells[i][j++].firstChild.nodeValue = vals[k];
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
function setLegend(opts, _fire) {
|
|
3225
|
+
if (opts != null) {
|
|
3226
|
+
if (opts.idxs) opts.idxs.forEach((didx, sidx) => {
|
|
3227
|
+
activeIdxs[sidx] = didx;
|
|
3228
|
+
});
|
|
3229
|
+
else if (!isUndef(opts.idx)) activeIdxs.fill(opts.idx);
|
|
3230
|
+
legend.idx = activeIdxs[0];
|
|
3231
|
+
}
|
|
3232
|
+
if (showLegend && legend.live) {
|
|
3233
|
+
for (let sidx = 0; sidx < series.length; sidx++) if (sidx > 0 || mode == 1 && !multiValLegend) setLegendValues(sidx, activeIdxs[sidx]);
|
|
3234
|
+
syncLegend();
|
|
3235
|
+
}
|
|
3236
|
+
shouldSetLegend = false;
|
|
3237
|
+
_fire !== false && fire("setLegend");
|
|
3238
|
+
}
|
|
3239
|
+
self.setLegend = setLegend;
|
|
3240
|
+
function setLegendValues(sidx, idx) {
|
|
3241
|
+
let s = series[sidx];
|
|
3242
|
+
let src = sidx == 0 && xScaleDistr == 2 ? data0 : data[sidx];
|
|
3243
|
+
let val;
|
|
3244
|
+
if (multiValLegend) val = s.values(self, sidx, idx) ?? NULL_LEGEND_VALUES;
|
|
3245
|
+
else {
|
|
3246
|
+
val = s.value(self, idx == null ? null : src[idx], sidx, idx);
|
|
3247
|
+
val = val == null ? NULL_LEGEND_VALUES : { _: val };
|
|
3248
|
+
}
|
|
3249
|
+
legend.values[sidx] = val;
|
|
3250
|
+
}
|
|
3251
|
+
function updateCursor(src, _fire, _pub) {
|
|
3252
|
+
rawMouseLeft1 = mouseLeft1;
|
|
3253
|
+
rawMouseTop1 = mouseTop1;
|
|
3254
|
+
[mouseLeft1, mouseTop1] = cursor.move(self, mouseLeft1, mouseTop1);
|
|
3255
|
+
cursor.left = mouseLeft1;
|
|
3256
|
+
cursor.top = mouseTop1;
|
|
3257
|
+
if (showCursor) {
|
|
3258
|
+
vCursor && elTrans(vCursor, round(mouseLeft1), 0, plotWidCss, plotHgtCss);
|
|
3259
|
+
hCursor && elTrans(hCursor, 0, round(mouseTop1), plotWidCss, plotHgtCss);
|
|
3260
|
+
}
|
|
3261
|
+
let idx;
|
|
3262
|
+
let noDataInRange = i0 > i1;
|
|
3263
|
+
closestDist = inf;
|
|
3264
|
+
closestSeries = null;
|
|
3265
|
+
let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss;
|
|
3266
|
+
let yDim = scaleX.ori == 1 ? plotWidCss : plotHgtCss;
|
|
3267
|
+
if (mouseLeft1 < 0 || dataLen == 0 || noDataInRange) {
|
|
3268
|
+
idx = cursor.idx = null;
|
|
3269
|
+
for (let i = 0; i < series.length; i++) {
|
|
3270
|
+
let pt = cursorPts[i];
|
|
3271
|
+
pt != null && elTrans(pt, -10, -10, plotWidCss, plotHgtCss);
|
|
3272
|
+
}
|
|
3273
|
+
if (cursorFocus) setSeries(null, FOCUS_TRUE, true, src == null && syncOpts.setSeries);
|
|
3274
|
+
if (legend.live) {
|
|
3275
|
+
activeIdxs.fill(idx);
|
|
3276
|
+
shouldSetLegend = true;
|
|
3277
|
+
}
|
|
3278
|
+
} else {
|
|
3279
|
+
let mouseXPos, valAtPosX, xPos;
|
|
3280
|
+
if (mode == 1) {
|
|
3281
|
+
mouseXPos = scaleX.ori == 0 ? mouseLeft1 : mouseTop1;
|
|
3282
|
+
valAtPosX = posToVal(mouseXPos, xScaleKey);
|
|
3283
|
+
idx = cursor.idx = closestIdx(valAtPosX, data[0], i0, i1);
|
|
3284
|
+
xPos = valToPosX(data[0][idx], scaleX, xDim, 0);
|
|
3285
|
+
}
|
|
3286
|
+
let _ptLft = -10;
|
|
3287
|
+
let _ptTop = -10;
|
|
3288
|
+
let _ptWid = 0;
|
|
3289
|
+
let _ptHgt = 0;
|
|
3290
|
+
let _centered = true;
|
|
3291
|
+
let _ptFill = "";
|
|
3292
|
+
let _ptStroke = "";
|
|
3293
|
+
for (let i = mode == 2 ? 1 : 0; i < series.length; i++) {
|
|
3294
|
+
let s = series[i];
|
|
3295
|
+
let idx1 = activeIdxs[i];
|
|
3296
|
+
let yVal1 = idx1 == null ? null : mode == 1 ? data[i][idx1] : data[i][1][idx1];
|
|
3297
|
+
let idx2 = cursor.dataIdx(self, i, idx, valAtPosX);
|
|
3298
|
+
let yVal2 = idx2 == null ? null : mode == 1 ? data[i][idx2] : data[i][1][idx2];
|
|
3299
|
+
shouldSetLegend = shouldSetLegend || yVal2 != yVal1 || idx2 != idx1;
|
|
3300
|
+
activeIdxs[i] = idx2;
|
|
3301
|
+
if (i > 0 && s.show) {
|
|
3302
|
+
let xPos2 = idx2 == null ? -10 : idx2 == idx ? xPos : valToPosX(mode == 1 ? data[0][idx2] : data[i][0][idx2], scaleX, xDim, 0);
|
|
3303
|
+
let yPos = yVal2 == null ? -10 : valToPosY(yVal2, mode == 1 ? scales[s.scale] : scales[s.facets[1].scale], yDim, 0);
|
|
3304
|
+
if (cursorFocus && yVal2 != null) {
|
|
3305
|
+
let mouseYPos = scaleX.ori == 1 ? mouseLeft1 : mouseTop1;
|
|
3306
|
+
let dist = abs(focus.dist(self, i, idx2, yPos, mouseYPos));
|
|
3307
|
+
if (dist < closestDist) {
|
|
3308
|
+
let bias = focus.bias;
|
|
3309
|
+
if (bias != 0) {
|
|
3310
|
+
let mouseYVal = posToVal(mouseYPos, s.scale);
|
|
3311
|
+
let seriesYValSign = yVal2 >= 0 ? 1 : -1;
|
|
3312
|
+
let mouseYValSign = mouseYVal >= 0 ? 1 : -1;
|
|
3313
|
+
if (mouseYValSign == seriesYValSign && (mouseYValSign == 1 ? bias == 1 ? yVal2 >= mouseYVal : yVal2 <= mouseYVal : bias == 1 ? yVal2 <= mouseYVal : yVal2 >= mouseYVal)) {
|
|
3314
|
+
closestDist = dist;
|
|
3315
|
+
closestSeries = i;
|
|
3316
|
+
}
|
|
3317
|
+
} else {
|
|
3318
|
+
closestDist = dist;
|
|
3319
|
+
closestSeries = i;
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
if (shouldSetLegend || cursorOnePt) {
|
|
3324
|
+
let hPos, vPos;
|
|
3325
|
+
if (scaleX.ori == 0) {
|
|
3326
|
+
hPos = xPos2;
|
|
3327
|
+
vPos = yPos;
|
|
3328
|
+
} else {
|
|
3329
|
+
hPos = yPos;
|
|
3330
|
+
vPos = xPos2;
|
|
3331
|
+
}
|
|
3332
|
+
let ptWid, ptHgt, ptLft, ptTop, ptStroke, ptFill, centered = true, getBBox = points.bbox;
|
|
3333
|
+
if (getBBox != null) {
|
|
3334
|
+
centered = false;
|
|
3335
|
+
let bbox = getBBox(self, i);
|
|
3336
|
+
ptLft = bbox.left;
|
|
3337
|
+
ptTop = bbox.top;
|
|
3338
|
+
ptWid = bbox.width;
|
|
3339
|
+
ptHgt = bbox.height;
|
|
3340
|
+
} else {
|
|
3341
|
+
ptLft = hPos;
|
|
3342
|
+
ptTop = vPos;
|
|
3343
|
+
ptWid = ptHgt = points.size(self, i);
|
|
3344
|
+
}
|
|
3345
|
+
ptFill = points.fill(self, i);
|
|
3346
|
+
ptStroke = points.stroke(self, i);
|
|
3347
|
+
if (cursorOnePt) {
|
|
3348
|
+
if (i == closestSeries && closestDist <= focus.prox) {
|
|
3349
|
+
_ptLft = ptLft;
|
|
3350
|
+
_ptTop = ptTop;
|
|
3351
|
+
_ptWid = ptWid;
|
|
3352
|
+
_ptHgt = ptHgt;
|
|
3353
|
+
_centered = centered;
|
|
3354
|
+
_ptFill = ptFill;
|
|
3355
|
+
_ptStroke = ptStroke;
|
|
3356
|
+
}
|
|
3357
|
+
} else {
|
|
3358
|
+
let pt = cursorPts[i];
|
|
3359
|
+
if (pt != null) {
|
|
3360
|
+
cursorPtsLft[i] = ptLft;
|
|
3361
|
+
cursorPtsTop[i] = ptTop;
|
|
3362
|
+
elSize(pt, ptWid, ptHgt, centered);
|
|
3363
|
+
elColor(pt, ptFill, ptStroke);
|
|
3364
|
+
elTrans(pt, ceil(ptLft), ceil(ptTop), plotWidCss, plotHgtCss);
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
if (cursorOnePt) {
|
|
3371
|
+
let p = focus.prox;
|
|
3372
|
+
if (shouldSetLegend || (focusedSeries == null ? closestDist <= p : closestDist > p || closestSeries != focusedSeries)) {
|
|
3373
|
+
let pt = cursorPts[0];
|
|
3374
|
+
if (pt != null) {
|
|
3375
|
+
cursorPtsLft[0] = _ptLft;
|
|
3376
|
+
cursorPtsTop[0] = _ptTop;
|
|
3377
|
+
elSize(pt, _ptWid, _ptHgt, _centered);
|
|
3378
|
+
elColor(pt, _ptFill, _ptStroke);
|
|
3379
|
+
elTrans(pt, ceil(_ptLft), ceil(_ptTop), plotWidCss, plotHgtCss);
|
|
3380
|
+
}
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
if (select.show && dragging) if (src != null) {
|
|
3385
|
+
let [xKey, yKey] = syncOpts.scales;
|
|
3386
|
+
let [matchXKeys, matchYKeys] = syncOpts.match;
|
|
3387
|
+
let [xKeySrc, yKeySrc] = src.cursor.sync.scales;
|
|
3388
|
+
let sdrag = src.cursor.drag;
|
|
3389
|
+
dragX = sdrag._x;
|
|
3390
|
+
dragY = sdrag._y;
|
|
3391
|
+
if (dragX || dragY) {
|
|
3392
|
+
let { left, top, width, height } = src.select;
|
|
3393
|
+
let sori = src.scales[xKeySrc].ori;
|
|
3394
|
+
let sPosToVal = src.posToVal;
|
|
3395
|
+
let sOff, sDim, sc, a, b;
|
|
3396
|
+
let matchingX = xKey != null && matchXKeys(xKey, xKeySrc);
|
|
3397
|
+
let matchingY = yKey != null && matchYKeys(yKey, yKeySrc);
|
|
3398
|
+
if (matchingX && dragX) {
|
|
3399
|
+
if (sori == 0) {
|
|
3400
|
+
sOff = left;
|
|
3401
|
+
sDim = width;
|
|
3402
|
+
} else {
|
|
3403
|
+
sOff = top;
|
|
3404
|
+
sDim = height;
|
|
3405
|
+
}
|
|
3406
|
+
sc = scales[xKey];
|
|
3407
|
+
a = valToPosX(sPosToVal(sOff, xKeySrc), sc, xDim, 0);
|
|
3408
|
+
b = valToPosX(sPosToVal(sOff + sDim, xKeySrc), sc, xDim, 0);
|
|
3409
|
+
setSelX(min(a, b), abs(b - a));
|
|
3410
|
+
} else setSelX(0, xDim);
|
|
3411
|
+
if (matchingY && dragY) {
|
|
3412
|
+
if (sori == 1) {
|
|
3413
|
+
sOff = left;
|
|
3414
|
+
sDim = width;
|
|
3415
|
+
} else {
|
|
3416
|
+
sOff = top;
|
|
3417
|
+
sDim = height;
|
|
3418
|
+
}
|
|
3419
|
+
sc = scales[yKey];
|
|
3420
|
+
a = valToPosY(sPosToVal(sOff, yKeySrc), sc, yDim, 0);
|
|
3421
|
+
b = valToPosY(sPosToVal(sOff + sDim, yKeySrc), sc, yDim, 0);
|
|
3422
|
+
setSelY(min(a, b), abs(b - a));
|
|
3423
|
+
} else setSelY(0, yDim);
|
|
3424
|
+
} else hideSelect();
|
|
3425
|
+
} else {
|
|
3426
|
+
let rawDX = abs(rawMouseLeft1 - rawMouseLeft0);
|
|
3427
|
+
let rawDY = abs(rawMouseTop1 - rawMouseTop0);
|
|
3428
|
+
if (scaleX.ori == 1) {
|
|
3429
|
+
let _rawDX = rawDX;
|
|
3430
|
+
rawDX = rawDY;
|
|
3431
|
+
rawDY = _rawDX;
|
|
3432
|
+
}
|
|
3433
|
+
dragX = drag.x && rawDX >= drag.dist;
|
|
3434
|
+
dragY = drag.y && rawDY >= drag.dist;
|
|
3435
|
+
let uni = drag.uni;
|
|
3436
|
+
if (uni != null) {
|
|
3437
|
+
if (dragX && dragY) {
|
|
3438
|
+
dragX = rawDX >= uni;
|
|
3439
|
+
dragY = rawDY >= uni;
|
|
3440
|
+
if (!dragX && !dragY) if (rawDY > rawDX) dragY = true;
|
|
3441
|
+
else dragX = true;
|
|
3442
|
+
}
|
|
3443
|
+
} else if (drag.x && drag.y && (dragX || dragY)) dragX = dragY = true;
|
|
3444
|
+
let p0, p1;
|
|
3445
|
+
if (dragX) {
|
|
3446
|
+
if (scaleX.ori == 0) {
|
|
3447
|
+
p0 = mouseLeft0;
|
|
3448
|
+
p1 = mouseLeft1;
|
|
3449
|
+
} else {
|
|
3450
|
+
p0 = mouseTop0;
|
|
3451
|
+
p1 = mouseTop1;
|
|
3452
|
+
}
|
|
3453
|
+
setSelX(min(p0, p1), abs(p1 - p0));
|
|
3454
|
+
if (!dragY) setSelY(0, yDim);
|
|
3455
|
+
}
|
|
3456
|
+
if (dragY) {
|
|
3457
|
+
if (scaleX.ori == 1) {
|
|
3458
|
+
p0 = mouseLeft0;
|
|
3459
|
+
p1 = mouseLeft1;
|
|
3460
|
+
} else {
|
|
3461
|
+
p0 = mouseTop0;
|
|
3462
|
+
p1 = mouseTop1;
|
|
3463
|
+
}
|
|
3464
|
+
setSelY(min(p0, p1), abs(p1 - p0));
|
|
3465
|
+
if (!dragX) setSelX(0, xDim);
|
|
3466
|
+
}
|
|
3467
|
+
if (!dragX && !dragY) {
|
|
3468
|
+
setSelX(0, 0);
|
|
3469
|
+
setSelY(0, 0);
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
drag._x = dragX;
|
|
3473
|
+
drag._y = dragY;
|
|
3474
|
+
if (src == null) {
|
|
3475
|
+
if (_pub) {
|
|
3476
|
+
if (syncKey != null) {
|
|
3477
|
+
let [xSyncKey, ySyncKey] = syncOpts.scales;
|
|
3478
|
+
syncOpts.values[0] = xSyncKey != null ? posToVal(scaleX.ori == 0 ? mouseLeft1 : mouseTop1, xSyncKey) : null;
|
|
3479
|
+
syncOpts.values[1] = ySyncKey != null ? posToVal(scaleX.ori == 1 ? mouseLeft1 : mouseTop1, ySyncKey) : null;
|
|
3480
|
+
}
|
|
3481
|
+
pubSync(mousemove, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, idx);
|
|
3482
|
+
}
|
|
3483
|
+
if (cursorFocus) {
|
|
3484
|
+
let shouldPub = _pub && syncOpts.setSeries;
|
|
3485
|
+
let p = focus.prox;
|
|
3486
|
+
if (focusedSeries == null) {
|
|
3487
|
+
if (closestDist <= p) setSeries(closestSeries, FOCUS_TRUE, true, shouldPub);
|
|
3488
|
+
} else if (closestDist > p) setSeries(null, FOCUS_TRUE, true, shouldPub);
|
|
3489
|
+
else if (closestSeries != focusedSeries) setSeries(closestSeries, FOCUS_TRUE, true, shouldPub);
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
if (shouldSetLegend) {
|
|
3493
|
+
legend.idx = idx;
|
|
3494
|
+
setLegend();
|
|
3495
|
+
}
|
|
3496
|
+
_fire !== false && fire("setCursor");
|
|
3497
|
+
}
|
|
3498
|
+
let rect = null;
|
|
3499
|
+
Object.defineProperty(self, "rect", { get() {
|
|
3500
|
+
if (rect == null) syncRect(false);
|
|
3501
|
+
return rect;
|
|
3502
|
+
} });
|
|
3503
|
+
function syncRect(defer = false) {
|
|
3504
|
+
if (defer) rect = null;
|
|
3505
|
+
else {
|
|
3506
|
+
rect = over.getBoundingClientRect();
|
|
3507
|
+
fire("syncRect", rect);
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
function mouseMove(e, src, _l, _t, _w, _h, _i) {
|
|
3511
|
+
if (cursor._lock) return;
|
|
3512
|
+
if (dragging && e != null && e.movementX == 0 && e.movementY == 0) return;
|
|
3513
|
+
cacheMouse(e, src, _l, _t, _w, _h, _i, false, e != null);
|
|
3514
|
+
if (e != null) updateCursor(null, true, true);
|
|
3515
|
+
else updateCursor(src, true, false);
|
|
3516
|
+
}
|
|
3517
|
+
function cacheMouse(e, src, _l, _t, _w, _h, _i, initial, snap) {
|
|
3518
|
+
if (rect == null) syncRect(false);
|
|
3519
|
+
setCursorEvent(e);
|
|
3520
|
+
if (e != null) {
|
|
3521
|
+
_l = e.clientX - rect.left;
|
|
3522
|
+
_t = e.clientY - rect.top;
|
|
3523
|
+
} else {
|
|
3524
|
+
if (_l < 0 || _t < 0) {
|
|
3525
|
+
mouseLeft1 = -10;
|
|
3526
|
+
mouseTop1 = -10;
|
|
3527
|
+
return;
|
|
3528
|
+
}
|
|
3529
|
+
let [xKey, yKey] = syncOpts.scales;
|
|
3530
|
+
let syncOptsSrc = src.cursor.sync;
|
|
3531
|
+
let [xValSrc, yValSrc] = syncOptsSrc.values;
|
|
3532
|
+
let [xKeySrc, yKeySrc] = syncOptsSrc.scales;
|
|
3533
|
+
let [matchXKeys, matchYKeys] = syncOpts.match;
|
|
3534
|
+
let rotSrc = src.axes[0].side % 2 == 1;
|
|
3535
|
+
let xDim = scaleX.ori == 0 ? plotWidCss : plotHgtCss, yDim = scaleX.ori == 1 ? plotWidCss : plotHgtCss, _xDim = rotSrc ? _h : _w, _yDim = rotSrc ? _w : _h, _xPos = rotSrc ? _t : _l, _yPos = rotSrc ? _l : _t;
|
|
3536
|
+
if (xKeySrc != null) _l = matchXKeys(xKey, xKeySrc) ? getPos(xValSrc, scales[xKey], xDim, 0) : -10;
|
|
3537
|
+
else _l = xDim * (_xPos / _xDim);
|
|
3538
|
+
if (yKeySrc != null) _t = matchYKeys(yKey, yKeySrc) ? getPos(yValSrc, scales[yKey], yDim, 0) : -10;
|
|
3539
|
+
else _t = yDim * (_yPos / _yDim);
|
|
3540
|
+
if (scaleX.ori == 1) {
|
|
3541
|
+
let __l = _l;
|
|
3542
|
+
_l = _t;
|
|
3543
|
+
_t = __l;
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
if (snap && (src == null || src.cursor.event.type == mousemove)) {
|
|
3547
|
+
if (_l <= 1 || _l >= plotWidCss - 1) _l = incrRound(_l, plotWidCss);
|
|
3548
|
+
if (_t <= 1 || _t >= plotHgtCss - 1) _t = incrRound(_t, plotHgtCss);
|
|
3549
|
+
}
|
|
3550
|
+
if (initial) {
|
|
3551
|
+
rawMouseLeft0 = _l;
|
|
3552
|
+
rawMouseTop0 = _t;
|
|
3553
|
+
[mouseLeft0, mouseTop0] = cursor.move(self, _l, _t);
|
|
3554
|
+
} else {
|
|
3555
|
+
mouseLeft1 = _l;
|
|
3556
|
+
mouseTop1 = _t;
|
|
3557
|
+
}
|
|
3558
|
+
}
|
|
3559
|
+
const _hideProps = {
|
|
3560
|
+
width: 0,
|
|
3561
|
+
height: 0,
|
|
3562
|
+
left: 0,
|
|
3563
|
+
top: 0
|
|
3564
|
+
};
|
|
3565
|
+
function hideSelect() {
|
|
3566
|
+
setSelect(_hideProps, false);
|
|
3567
|
+
}
|
|
3568
|
+
let downSelectLeft;
|
|
3569
|
+
let downSelectTop;
|
|
3570
|
+
let downSelectWidth;
|
|
3571
|
+
let downSelectHeight;
|
|
3572
|
+
function mouseDown(e, src, _l, _t, _w, _h, _i) {
|
|
3573
|
+
dragging = true;
|
|
3574
|
+
dragX = dragY = drag._x = drag._y = false;
|
|
3575
|
+
cacheMouse(e, src, _l, _t, _w, _h, _i, true, false);
|
|
3576
|
+
if (e != null) {
|
|
3577
|
+
onMouse(mouseup, doc, mouseUp, false);
|
|
3578
|
+
pubSync(mousedown, self, mouseLeft0, mouseTop0, plotWidCss, plotHgtCss, null);
|
|
3579
|
+
}
|
|
3580
|
+
let { left, top, width, height } = select;
|
|
3581
|
+
downSelectLeft = left;
|
|
3582
|
+
downSelectTop = top;
|
|
3583
|
+
downSelectWidth = width;
|
|
3584
|
+
downSelectHeight = height;
|
|
3585
|
+
}
|
|
3586
|
+
function mouseUp(e, src, _l, _t, _w, _h, _i) {
|
|
3587
|
+
dragging = drag._x = drag._y = false;
|
|
3588
|
+
cacheMouse(e, src, _l, _t, _w, _h, _i, false, true);
|
|
3589
|
+
let { left, top, width, height } = select;
|
|
3590
|
+
let hasSelect = width > 0 || height > 0;
|
|
3591
|
+
let chgSelect = downSelectLeft != left || downSelectTop != top || downSelectWidth != width || downSelectHeight != height;
|
|
3592
|
+
hasSelect && chgSelect && setSelect(select);
|
|
3593
|
+
if (drag.setScale && hasSelect && chgSelect) {
|
|
3594
|
+
let xOff = left, xDim = width, yOff = top, yDim = height;
|
|
3595
|
+
if (scaleX.ori == 1) xOff = top, xDim = height, yOff = left, yDim = width;
|
|
3596
|
+
if (dragX) _setScale(xScaleKey, posToVal(xOff, xScaleKey), posToVal(xOff + xDim, xScaleKey));
|
|
3597
|
+
if (dragY) for (let k in scales) {
|
|
3598
|
+
let sc = scales[k];
|
|
3599
|
+
if (k != xScaleKey && sc.from == null && sc.min != inf) _setScale(k, posToVal(yOff + yDim, k), posToVal(yOff, k));
|
|
3600
|
+
}
|
|
3601
|
+
hideSelect();
|
|
3602
|
+
} else if (cursor.lock) {
|
|
3603
|
+
cursor._lock = !cursor._lock;
|
|
3604
|
+
updateCursor(src, true, e != null);
|
|
3605
|
+
}
|
|
3606
|
+
if (e != null) {
|
|
3607
|
+
offMouse(mouseup, doc);
|
|
3608
|
+
pubSync(mouseup, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null);
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
function mouseLeave(e, src, _l, _t, _w, _h, _i) {
|
|
3612
|
+
if (cursor._lock) return;
|
|
3613
|
+
setCursorEvent(e);
|
|
3614
|
+
let _dragging = dragging;
|
|
3615
|
+
if (dragging) {
|
|
3616
|
+
let snapH = true;
|
|
3617
|
+
let snapV = true;
|
|
3618
|
+
let snapProx = 10;
|
|
3619
|
+
let dragH, dragV;
|
|
3620
|
+
if (scaleX.ori == 0) {
|
|
3621
|
+
dragH = dragX;
|
|
3622
|
+
dragV = dragY;
|
|
3623
|
+
} else {
|
|
3624
|
+
dragH = dragY;
|
|
3625
|
+
dragV = dragX;
|
|
3626
|
+
}
|
|
3627
|
+
if (dragH && dragV) {
|
|
3628
|
+
snapH = mouseLeft1 <= snapProx || mouseLeft1 >= plotWidCss - snapProx;
|
|
3629
|
+
snapV = mouseTop1 <= snapProx || mouseTop1 >= plotHgtCss - snapProx;
|
|
3630
|
+
}
|
|
3631
|
+
if (dragH && snapH) mouseLeft1 = mouseLeft1 < mouseLeft0 ? 0 : plotWidCss;
|
|
3632
|
+
if (dragV && snapV) mouseTop1 = mouseTop1 < mouseTop0 ? 0 : plotHgtCss;
|
|
3633
|
+
updateCursor(null, true, true);
|
|
3634
|
+
dragging = false;
|
|
3635
|
+
}
|
|
3636
|
+
mouseLeft1 = -10;
|
|
3637
|
+
mouseTop1 = -10;
|
|
3638
|
+
activeIdxs.fill(null);
|
|
3639
|
+
updateCursor(null, true, true);
|
|
3640
|
+
if (_dragging) dragging = _dragging;
|
|
3641
|
+
}
|
|
3642
|
+
function dblClick(e, src, _l, _t, _w, _h, _i) {
|
|
3643
|
+
if (cursor._lock) return;
|
|
3644
|
+
setCursorEvent(e);
|
|
3645
|
+
autoScaleX();
|
|
3646
|
+
hideSelect();
|
|
3647
|
+
if (e != null) pubSync(dblclick, self, mouseLeft1, mouseTop1, plotWidCss, plotHgtCss, null);
|
|
3648
|
+
}
|
|
3649
|
+
function syncPxRatio() {
|
|
3650
|
+
axes.forEach(syncFontSize);
|
|
3651
|
+
_setSize(self.width, self.height, true);
|
|
3652
|
+
}
|
|
3653
|
+
on(dppxchange, win, syncPxRatio);
|
|
3654
|
+
const events = {};
|
|
3655
|
+
events.mousedown = mouseDown;
|
|
3656
|
+
events.mousemove = mouseMove;
|
|
3657
|
+
events.mouseup = mouseUp;
|
|
3658
|
+
events.dblclick = dblClick;
|
|
3659
|
+
events["setSeries"] = (e, src, idx, opts) => {
|
|
3660
|
+
let seriesIdxMatcher = syncOpts.match[2];
|
|
3661
|
+
idx = seriesIdxMatcher(self, src, idx);
|
|
3662
|
+
idx != -1 && setSeries(idx, opts, true, false);
|
|
3663
|
+
};
|
|
3664
|
+
if (showCursor) {
|
|
3665
|
+
onMouse(mousedown, over, mouseDown);
|
|
3666
|
+
onMouse(mousemove, over, mouseMove);
|
|
3667
|
+
onMouse(mouseenter, over, (e) => {
|
|
3668
|
+
setCursorEvent(e);
|
|
3669
|
+
syncRect(false);
|
|
3670
|
+
});
|
|
3671
|
+
onMouse(mouseleave, over, mouseLeave);
|
|
3672
|
+
onMouse(dblclick, over, dblClick);
|
|
3673
|
+
cursorPlots.add(self);
|
|
3674
|
+
self.syncRect = syncRect;
|
|
3675
|
+
}
|
|
3676
|
+
const hooks = self.hooks = opts.hooks || {};
|
|
3677
|
+
function fire(evName, a1, a2) {
|
|
3678
|
+
if (deferHooks) hooksQueue.push([
|
|
3679
|
+
evName,
|
|
3680
|
+
a1,
|
|
3681
|
+
a2
|
|
3682
|
+
]);
|
|
3683
|
+
else if (evName in hooks) hooks[evName].forEach((fn) => {
|
|
3684
|
+
fn.call(null, self, a1, a2);
|
|
3685
|
+
});
|
|
3686
|
+
}
|
|
3687
|
+
(opts.plugins || []).forEach((p) => {
|
|
3688
|
+
for (let evName in p.hooks) hooks[evName] = (hooks[evName] || []).concat(p.hooks[evName]);
|
|
3689
|
+
});
|
|
3690
|
+
const seriesIdxMatcher = (self, src, srcSeriesIdx) => srcSeriesIdx;
|
|
3691
|
+
const syncOpts = assign({
|
|
3692
|
+
key: null,
|
|
3693
|
+
setSeries: false,
|
|
3694
|
+
filters: {
|
|
3695
|
+
pub: retTrue,
|
|
3696
|
+
sub: retTrue
|
|
3697
|
+
},
|
|
3698
|
+
scales: [xScaleKey, series[1] ? series[1].scale : null],
|
|
3699
|
+
match: [
|
|
3700
|
+
retEq,
|
|
3701
|
+
retEq,
|
|
3702
|
+
seriesIdxMatcher
|
|
3703
|
+
],
|
|
3704
|
+
values: [null, null]
|
|
3705
|
+
}, cursor.sync);
|
|
3706
|
+
if (syncOpts.match.length == 2) syncOpts.match.push(seriesIdxMatcher);
|
|
3707
|
+
cursor.sync = syncOpts;
|
|
3708
|
+
const syncKey = syncOpts.key;
|
|
3709
|
+
const sync = _sync(syncKey);
|
|
3710
|
+
function pubSync(type, src, x, y, w, h, i) {
|
|
3711
|
+
if (syncOpts.filters.pub(type, src, x, y, w, h, i)) sync.pub(type, src, x, y, w, h, i);
|
|
3712
|
+
}
|
|
3713
|
+
sync.sub(self);
|
|
3714
|
+
function pub(type, src, x, y, w, h, i) {
|
|
3715
|
+
if (syncOpts.filters.sub(type, src, x, y, w, h, i)) events[type](null, src, x, y, w, h, i);
|
|
3716
|
+
}
|
|
3717
|
+
self.pub = pub;
|
|
3718
|
+
function destroy() {
|
|
3719
|
+
sync.unsub(self);
|
|
3720
|
+
cursorPlots.delete(self);
|
|
3721
|
+
mouseListeners.clear();
|
|
3722
|
+
off(dppxchange, win, syncPxRatio);
|
|
3723
|
+
root.remove();
|
|
3724
|
+
legendTable?.remove();
|
|
3725
|
+
fire("destroy");
|
|
3726
|
+
}
|
|
3727
|
+
self.destroy = destroy;
|
|
3728
|
+
function _init() {
|
|
3729
|
+
fire("init", opts, data);
|
|
3730
|
+
setData(data || opts.data, false);
|
|
3731
|
+
if (pendScales[xScaleKey]) setScale(xScaleKey, pendScales[xScaleKey]);
|
|
3732
|
+
else autoScaleX();
|
|
3733
|
+
shouldSetSelect = select.show && (select.width > 0 || select.height > 0);
|
|
3734
|
+
shouldSetCursor = shouldSetLegend = true;
|
|
3735
|
+
_setSize(opts.width, opts.height);
|
|
3736
|
+
}
|
|
3737
|
+
series.forEach(initSeries);
|
|
3738
|
+
axes.forEach(initAxis);
|
|
3739
|
+
if (then) if (then instanceof HTMLElement) {
|
|
3740
|
+
then.appendChild(root);
|
|
3741
|
+
_init();
|
|
3742
|
+
} else then(self, _init);
|
|
3743
|
+
else _init();
|
|
3744
|
+
return self;
|
|
3745
|
+
}
|
|
3746
|
+
uPlot.assign = assign;
|
|
3747
|
+
uPlot.fmtNum = fmtNum;
|
|
3748
|
+
uPlot.rangeNum = rangeNum;
|
|
3749
|
+
uPlot.rangeLog = rangeLog;
|
|
3750
|
+
uPlot.rangeAsinh = rangeAsinh;
|
|
3751
|
+
uPlot.orient = orient;
|
|
3752
|
+
uPlot.pxRatio = pxRatio;
|
|
3753
|
+
uPlot.join = join;
|
|
3754
|
+
uPlot.fmtDate = fmtDate;
|
|
3755
|
+
uPlot.tzDate = tzDate;
|
|
3756
|
+
uPlot.sync = _sync;
|
|
3757
|
+
{
|
|
3758
|
+
uPlot.addGap = addGap;
|
|
3759
|
+
uPlot.clipGaps = clipGaps;
|
|
3760
|
+
let paths = uPlot.paths = { points };
|
|
3761
|
+
paths.linear = linear;
|
|
3762
|
+
paths.stepped = stepped;
|
|
3763
|
+
paths.bars = bars;
|
|
3764
|
+
paths.spline = monotoneCubic;
|
|
3765
|
+
}
|
|
3766
|
+
//#endregion
|
|
3767
|
+
export { uPlot as default };
|