@wick-charts/vue 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -3
- package/dist/BarSeries.vue.js +26 -20
- package/dist/CandlestickSeries.vue.js +30 -24
- package/dist/ChartContainer.vue.js +88 -65
- package/dist/HeatmapSeries.vue.js +40 -0
- package/dist/HeatmapSeries.vue2.js +4 -0
- package/dist/LineSeries.vue.js +26 -20
- package/dist/PieSeries.vue.js +24 -18
- package/dist/core/dist/animation/animator.js +21 -21
- package/dist/core/dist/animation/config.js +114 -87
- package/dist/core/dist/animation/easing.js +3 -1
- package/dist/core/dist/animation/intro-wave.js +68 -0
- package/dist/core/dist/axis/dom-labels.js +13 -14
- package/dist/core/dist/chart/badge-animator.js +56 -0
- package/dist/core/dist/chart/edge-indicators.js +28 -13
- package/dist/core/dist/chart/last-value.js +18 -17
- package/dist/core/dist/chart/y-target.js +13 -12
- package/dist/core/dist/chart.js +679 -452
- package/dist/core/dist/components/annotation-chip.js +28 -0
- package/dist/core/dist/components/edge-indicator.js +58 -26
- package/dist/core/dist/components/loading-indicator.js +46 -0
- package/dist/core/dist/components/marker.js +49 -31
- package/dist/core/dist/components/reference-line.js +27 -36
- package/dist/core/dist/components/time-region.js +30 -28
- package/dist/core/dist/data/store.js +38 -19
- package/dist/core/dist/data/sync.js +60 -38
- package/dist/core/dist/heatmap-tooltip.js +16 -0
- package/dist/core/dist/interactions/handler.js +67 -43
- package/dist/core/dist/perf/perf-hud.js +5 -5
- package/dist/core/dist/scales/x-scale.js +85 -37
- package/dist/core/dist/scales/y-scale.js +38 -27
- package/dist/core/dist/series/bar-intro.js +18 -0
- package/dist/core/dist/series/bar.js +337 -205
- package/dist/core/dist/series/base-multi-layer.js +224 -96
- package/dist/core/dist/series/candlestick-intro.js +57 -0
- package/dist/core/dist/series/candlestick.js +454 -276
- package/dist/core/dist/series/heatmap.js +387 -0
- package/dist/core/dist/series/line-intro.js +85 -0
- package/dist/core/dist/series/line.js +590 -282
- package/dist/core/dist/series/painters/builtins.js +2 -2
- package/dist/core/dist/series/pie.js +396 -259
- package/dist/core/dist/series/register-builtins.js +8 -7
- package/dist/core/dist/series/types.js +6 -0
- package/dist/core/dist/series/wave-intro.js +26 -0
- package/dist/core/dist/theme/create.js +69 -63
- package/dist/core/dist/theme/themes/mint-breeze.js +2 -2
- package/dist/core/dist/theme/themes/sand-dune.js +2 -2
- package/dist/core/dist/utils/color.js +109 -34
- package/dist/core/dist/utils/deep-equal.js +18 -0
- package/dist/core/dist/utils/time.js +25 -19
- package/dist/index.d.ts +1405 -123
- package/dist/index.js +177 -130
- package/dist/ui/Crosshair.vue.js +20 -21
- package/dist/ui/HeatmapTooltip.vue.js +96 -0
- package/dist/ui/HeatmapTooltip.vue2.js +4 -0
- package/dist/ui/InfoBar.vue.js +46 -47
- package/dist/ui/Legend.vue.js +80 -79
- package/dist/ui/PieLegend.vue.js +5 -5
- package/dist/ui/PieTooltip.vue.js +77 -67
- package/dist/ui/Tooltip.vue.js +60 -60
- package/dist/ui/YAxis.vue.js +2 -2
- package/dist/ui/YLabel.vue.js +94 -61
- package/package.json +2 -2
- package/src/BarSeries.vue +23 -7
- package/src/CandlestickSeries.vue +23 -7
- package/src/ChartContainer.vue +134 -12
- package/src/HeatmapSeries.vue +69 -0
- package/src/LineSeries.vue +23 -7
- package/src/PieSeries.vue +22 -6
- package/src/index.ts +84 -3
- package/src/ui/Crosshair.vue +1 -2
- package/src/ui/HeatmapTooltip.vue +144 -0
- package/src/ui/InfoBar.vue +1 -2
- package/src/ui/Legend.vue +13 -0
- package/src/ui/Marker.vue +1 -1
- package/src/ui/PieTooltip.vue +10 -0
- package/src/ui/ReferenceLine.vue +2 -2
- package/src/ui/TimeRegion.vue +2 -2
- package/src/ui/Tooltip.vue +2 -2
- package/src/ui/YLabel.vue +123 -8
|
@@ -1,60 +1,81 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { easeOutCubic as
|
|
3
|
-
import { decimateLineData as
|
|
4
|
-
import { hexToRgba as
|
|
5
|
-
import { lerp as
|
|
6
|
-
import { BaseMultiLayerSeries as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
1
|
+
import { DEFAULT_HISTORY_REVEAL as tt, DEFAULT_LINE_INTRO as et, DEFAULT_LINE_PULSE as it, DEFAULT_LINE_SMOOTH as ot, DEFAULT_LINE_ENTRY as st } from "../animation/config.js";
|
|
2
|
+
import { easeOutCubic as _ } from "../animation/easing.js";
|
|
3
|
+
import { decimateLineData as j } from "../data/decimation.js";
|
|
4
|
+
import { hexToRgba as C } from "../utils/color.js";
|
|
5
|
+
import { lerp as Y } from "../utils/math.js";
|
|
6
|
+
import { BaseMultiLayerSeries as rt } from "./base-multi-layer.js";
|
|
7
|
+
import { unfoldIntro as lt, backfillSweepIntro as at } from "./line-intro.js";
|
|
8
|
+
import { buildCurveSegments as q } from "./painters/canvas-path.js";
|
|
9
|
+
import { resolveLinePainter as ht } from "./painters/resolve.js";
|
|
10
|
+
const ct = {
|
|
10
11
|
colors: ["#2962FF"],
|
|
11
12
|
strokeWidth: 1,
|
|
12
13
|
area: { visible: !0 },
|
|
13
14
|
pulse: !0,
|
|
14
15
|
stacking: "off",
|
|
15
16
|
curve: "straight",
|
|
16
|
-
entryMs:
|
|
17
|
-
smoothMs:
|
|
18
|
-
pulseMs:
|
|
17
|
+
entryMs: st,
|
|
18
|
+
smoothMs: ot,
|
|
19
|
+
pulseMs: it,
|
|
20
|
+
introMs: et,
|
|
21
|
+
historyRevealMs: tt
|
|
19
22
|
};
|
|
20
|
-
function
|
|
23
|
+
function Q(v) {
|
|
21
24
|
const t = v.areaFill, e = t !== void 0 && v.area === void 0 ? { visible: !!t } : v.area;
|
|
22
25
|
return {
|
|
23
26
|
...v,
|
|
24
27
|
area: e,
|
|
25
|
-
entryMs: v.entryMs === !1 ? 0 : v.entryMs ??
|
|
26
|
-
smoothMs: v.smoothMs === !1 ? 0 : v.smoothMs ??
|
|
27
|
-
pulseMs: v.pulseMs === !1 ? 0 : v.pulseMs ??
|
|
28
|
+
entryMs: v.entryMs === !1 ? 0 : v.entryMs ?? st,
|
|
29
|
+
smoothMs: v.smoothMs === !1 ? 0 : v.smoothMs ?? ot,
|
|
30
|
+
pulseMs: v.pulseMs === !1 ? 0 : v.pulseMs ?? it,
|
|
31
|
+
introMs: v.introMs === !1 ? 0 : v.introMs ?? et,
|
|
32
|
+
historyRevealMs: v.historyRevealMs === !1 ? 0 : v.historyRevealMs ?? tt
|
|
28
33
|
};
|
|
29
34
|
}
|
|
30
|
-
function
|
|
35
|
+
function Z(v) {
|
|
31
36
|
return v.map(([t, e]) => ({ x: t, y: e }));
|
|
32
37
|
}
|
|
33
|
-
|
|
38
|
+
const $ = 0.15, ut = at();
|
|
39
|
+
function U(v, t, e) {
|
|
40
|
+
if (v.length === 0) return null;
|
|
41
|
+
if (t <= v[0].time) return Number.isFinite(v[0].value) ? e(v[0]) : null;
|
|
42
|
+
const i = v[v.length - 1];
|
|
43
|
+
if (t >= i.time) return Number.isFinite(i.value) ? e(i) : null;
|
|
44
|
+
let s = 0, o = v.length - 1;
|
|
45
|
+
for (; o - s > 1; ) {
|
|
46
|
+
const a = s + o >> 1;
|
|
47
|
+
v[a].time <= t ? s = a : o = a;
|
|
48
|
+
}
|
|
49
|
+
const n = v[s], r = v[o];
|
|
50
|
+
if (!Number.isFinite(n.value) || !Number.isFinite(r.value)) return null;
|
|
51
|
+
const l = r.time - n.time;
|
|
52
|
+
return l <= 0 ? e(n) : Y(e(n), e(r), (t - n.time) / l);
|
|
53
|
+
}
|
|
54
|
+
function K(v, t) {
|
|
34
55
|
for (const e of t)
|
|
35
56
|
e.kind === "line" ? v.lineTo(e.x, e.y) : v.bezierCurveTo(e.cp1x, e.cp1y, e.cp2x, e.cp2y, e.x, e.y);
|
|
36
57
|
}
|
|
37
|
-
function
|
|
38
|
-
for (let
|
|
39
|
-
const
|
|
40
|
-
|
|
58
|
+
function ft(v, t, e) {
|
|
59
|
+
for (let i = e.length - 1; i >= 0; i--) {
|
|
60
|
+
const s = e[i], o = i > 0 ? e[i - 1] : t[0];
|
|
61
|
+
s.kind === "line" ? v.lineTo(o.x, o.y) : v.bezierCurveTo(s.cp2x, s.cp2y, s.cp1x, s.cp1y, o.x, o.y);
|
|
41
62
|
}
|
|
42
63
|
}
|
|
43
|
-
class
|
|
64
|
+
class mt extends rt {
|
|
44
65
|
kind = "line";
|
|
45
66
|
areaGradientCache = /* @__PURE__ */ new Map();
|
|
46
67
|
constructor(t, e) {
|
|
47
|
-
super(t), this.options =
|
|
68
|
+
super(t), this.options = Q({ ...ct, ...e });
|
|
48
69
|
}
|
|
49
70
|
updateOptions(t) {
|
|
50
|
-
this.options =
|
|
71
|
+
this.options = Q({ ...this.options, ...t });
|
|
51
72
|
}
|
|
52
73
|
getStacking() {
|
|
53
74
|
return this.options.stacking;
|
|
54
75
|
}
|
|
55
76
|
applyTheme(t, e) {
|
|
56
|
-
const
|
|
57
|
-
this.updateOptions({ colors:
|
|
77
|
+
const i = this.stores.length === 1 ? [t.line.color] : t.seriesColors.slice(0, this.stores.length);
|
|
78
|
+
this.updateOptions({ colors: i }), this.options.strokeWidth === e.line.width && this.updateOptions({ strokeWidth: t.line.width });
|
|
58
79
|
}
|
|
59
80
|
isEntryEnabled() {
|
|
60
81
|
return (this.options.entryAnimation ?? "grow") !== "none";
|
|
@@ -66,15 +87,254 @@ class ht extends nt {
|
|
|
66
87
|
return this.hasPulse;
|
|
67
88
|
}
|
|
68
89
|
hasOverlayContentInRange(t, e) {
|
|
69
|
-
for (let
|
|
70
|
-
if (this.getLayerAlpha(
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
90
|
+
for (let i = 0; i < this.stores.length; i++) {
|
|
91
|
+
if (this.getLayerAlpha(i) <= 0) continue;
|
|
92
|
+
const s = this.stores[i].last();
|
|
93
|
+
if (s && s.time >= t) return !0;
|
|
73
94
|
}
|
|
74
95
|
return !1;
|
|
75
96
|
}
|
|
76
97
|
render(t) {
|
|
77
|
-
this.tickAnimations(performance.now())
|
|
98
|
+
this.tickAnimations(performance.now());
|
|
99
|
+
const { context: e } = t.scope;
|
|
100
|
+
this.historyDirectives = null;
|
|
101
|
+
const i = this.historyRange;
|
|
102
|
+
if (this.historyWave.active && i !== null) {
|
|
103
|
+
const r = this.options.historyReveal ?? ut;
|
|
104
|
+
r !== "none" && (this.historyDirectives = r(this.buildHistoryFrame(t, i)));
|
|
105
|
+
}
|
|
106
|
+
const s = this.historyDirectives, o = s?.ghostAlpha ?? 0;
|
|
107
|
+
o > 0 && (e.save(), e.globalAlpha *= o, this.introGhostPass = !0, this.renderBody(t), this.introGhostPass = !1, e.restore());
|
|
108
|
+
const n = this.applyHistoryClip(t, s, i);
|
|
109
|
+
this.introWave.active ? this.renderWithIntro(t) : (this.introDirectives = null, this.renderBody(t)), n && e.restore(), s?.heads !== void 0 && s.heads.length > 0 && this.drawIntroHeads(t, s.heads, this.historyWave.linear());
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Initial-load intro pass: the resolved LineIntroFn describes this frame
|
|
113
|
+
* declaratively (clip window / ghost pass / heads / value transform); the
|
|
114
|
+
* renderer executes the directives around the untouched body pass.
|
|
115
|
+
*/
|
|
116
|
+
renderWithIntro(t) {
|
|
117
|
+
const e = this.resolveIntro()(this.buildIntroFrame(t));
|
|
118
|
+
this.introDirectives = e;
|
|
119
|
+
const { context: i } = t.scope, { width: s, height: o } = t.scope.bitmapSize, n = e.ghostAlpha ?? 0;
|
|
120
|
+
n > 0 && (i.save(), i.globalAlpha *= n, this.introGhostPass = !0, this.renderBody(t), this.introGhostPass = !1, i.restore());
|
|
121
|
+
const r = e.clip, l = r !== void 0 && (r.fromX !== void 0 || r.toX !== void 0);
|
|
122
|
+
if (l) {
|
|
123
|
+
const a = r.fromX ?? 0, p = r.toX ?? s;
|
|
124
|
+
i.save(), i.beginPath(), i.rect(a, 0, Math.max(0, p - a), o), i.clip();
|
|
125
|
+
}
|
|
126
|
+
this.renderBody(t), l && i.restore(), e.heads !== void 0 && e.heads.length > 0 && this.drawIntroHeads(t, e.heads, this.introWave.linear());
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Apply the history reveal's clip directive, mapped from reveal space
|
|
130
|
+
* (`x = 0` at the data boundary, increasing into the prepended history)
|
|
131
|
+
* to bitmap space. Everything at or after the boundary always draws; a
|
|
132
|
+
* small pad keeps the stroke cap at the reveal front from being shaved.
|
|
133
|
+
*/
|
|
134
|
+
applyHistoryClip(t, e, i) {
|
|
135
|
+
const s = e?.clip;
|
|
136
|
+
if (s === void 0 || i === null || s.fromX === void 0 && s.toX === void 0) return !1;
|
|
137
|
+
const { context: o } = t.scope, { width: n, height: r } = t.scope.bitmapSize, l = t.timeScale.timeToBitmapX(i.to), a = Math.abs(l - t.timeScale.timeToBitmapX(i.from)), p = Math.max(2, (this.options.strokeWidth ?? 1) * t.scope.horizontalPixelRatio), f = s.fromX ?? 0, y = s.toX ?? a;
|
|
138
|
+
return o.save(), o.beginPath(), o.rect(l - y - p, 0, Math.max(0, y - f + p), r), o.rect(l, 0, Math.max(0, n - l), r), o.clip(), !0;
|
|
139
|
+
}
|
|
140
|
+
renderBody(t) {
|
|
141
|
+
this.options.stacking === "off" ? this.renderOff(t) : this.renderStacked(t, this.options.stacking === "percent");
|
|
142
|
+
}
|
|
143
|
+
/** True while a ghost pre-pass is drawing — skips the area fill so the
|
|
144
|
+
* translucent pass shows only the stroke skeleton. */
|
|
145
|
+
introGhostPass = !1;
|
|
146
|
+
/**
|
|
147
|
+
* Directives produced for the current intro frame. Kept between passes so
|
|
148
|
+
* the overlay (pulse dot) applies the same value transform the main pass
|
|
149
|
+
* drew with; `null` once the wave settles.
|
|
150
|
+
*/
|
|
151
|
+
introDirectives = null;
|
|
152
|
+
/** Per-frame history-reveal directives; `null` when no reveal is in flight. */
|
|
153
|
+
historyDirectives = null;
|
|
154
|
+
/** Default intro, built lazily — one instance per renderer. */
|
|
155
|
+
defaultIntro = null;
|
|
156
|
+
resolveIntro() {
|
|
157
|
+
const t = this.options.introAnimation;
|
|
158
|
+
return t !== void 0 ? t : (this.defaultIntro === null && (this.defaultIntro = lt()), this.defaultIntro);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Frame context handed to the intro fn — progress plus memoized data
|
|
162
|
+
* accessors, so a directive-producing fn stays pure and cheap.
|
|
163
|
+
*/
|
|
164
|
+
buildIntroFrame(t) {
|
|
165
|
+
return this.buildFrame(t, {
|
|
166
|
+
progress: this.introWave.linear(),
|
|
167
|
+
range: t.timeScale.getRange(),
|
|
168
|
+
// Plot-area extent, not the canvas bitmap — the canvas also carries the
|
|
169
|
+
// axis strips, so `bitmapSize` would make `width / 2` land right of the
|
|
170
|
+
// data center and any width-based x→time mapping sample the wrong time.
|
|
171
|
+
width: t.timeScale.getMediaWidth() * t.scope.horizontalPixelRatio
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Localized frame for the history reveal fn: `range` is the prepended
|
|
176
|
+
* span (boundary at `range.to`), `width` its bitmap width, and the data
|
|
177
|
+
* accessors are scoped to that span — `layerMean` anchors an unfold to
|
|
178
|
+
* the new history, not the whole window.
|
|
179
|
+
*/
|
|
180
|
+
buildHistoryFrame(t, e) {
|
|
181
|
+
return this.buildFrame(t, {
|
|
182
|
+
progress: this.historyWave.linear(),
|
|
183
|
+
range: e,
|
|
184
|
+
width: Math.abs(t.timeScale.timeToBitmapX(e.to) - t.timeScale.timeToBitmapX(e.from))
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
buildFrame(t, e) {
|
|
188
|
+
const { timeScale: i, yScale: s, scope: o } = t, { progress: n, range: r, width: l } = e, a = new Array(this.stores.length), p = new Array(this.stores.length);
|
|
189
|
+
let f;
|
|
190
|
+
const y = (h) => {
|
|
191
|
+
let m = a[h];
|
|
192
|
+
return m === void 0 && (m = this.stores[h]?.getVisibleData(r.from, r.to) ?? [], a[h] = m), m;
|
|
193
|
+
};
|
|
194
|
+
return {
|
|
195
|
+
progress: n,
|
|
196
|
+
range: r,
|
|
197
|
+
width: l,
|
|
198
|
+
height: s.getMediaHeight() * o.verticalPixelRatio,
|
|
199
|
+
stacking: this.options.stacking,
|
|
200
|
+
timeToX: (h) => i.timeToBitmapX(h),
|
|
201
|
+
xToTime: (h) => i.xToTime(h / o.horizontalPixelRatio),
|
|
202
|
+
valueToY: (h) => s.valueToBitmapY(h),
|
|
203
|
+
layerCount: this.stores.length,
|
|
204
|
+
layerData: y,
|
|
205
|
+
layerMean: (h) => {
|
|
206
|
+
let m = p[h];
|
|
207
|
+
if (m === void 0) {
|
|
208
|
+
let u = 0, A = 0;
|
|
209
|
+
for (const R of y(h))
|
|
210
|
+
Number.isFinite(R.value) && (u += R.value, A++);
|
|
211
|
+
m = A > 0 ? u / A : null, p[h] = m;
|
|
212
|
+
}
|
|
213
|
+
return m;
|
|
214
|
+
},
|
|
215
|
+
primaryPath: () => {
|
|
216
|
+
if (f === void 0) {
|
|
217
|
+
f = null;
|
|
218
|
+
for (let h = 0; h < this.stores.length; h++) {
|
|
219
|
+
if (this.getLayerAlpha(h) <= 0 || !this.stores[h].isVisible()) continue;
|
|
220
|
+
const m = y(h).filter((u) => Number.isFinite(u.value));
|
|
221
|
+
if (!(m.length < 2)) {
|
|
222
|
+
f = m.map((u) => ({
|
|
223
|
+
x: i.timeToBitmapX(u.time),
|
|
224
|
+
y: s.valueToBitmapY(u.value),
|
|
225
|
+
time: u.time
|
|
226
|
+
}));
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return f;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* A custom/built-in intro's value transform rides this hook: every
|
|
237
|
+
* rendered value (stroke, area, stacked cumulative, trailing endpoint,
|
|
238
|
+
* overlay pulse) already flows through `effectiveValue`, so one override
|
|
239
|
+
* animates the whole geometry.
|
|
240
|
+
*/
|
|
241
|
+
effectiveValue(t, e, i, s) {
|
|
242
|
+
const o = super.effectiveValue(t, e, i, s), n = this.historyWave.active ? this.historyDirectives?.value : void 0, r = this.historyRange;
|
|
243
|
+
if (n !== void 0 && r !== null && i < r.to) {
|
|
244
|
+
const y = r.to - r.from, h = y > 0 ? Math.min(1, Math.max(0, (r.to - i) / y)) : 0;
|
|
245
|
+
return n({ layerIndex: e, time: i, value: o, position: h });
|
|
246
|
+
}
|
|
247
|
+
const l = this.introWave.active ? this.introDirectives?.value : void 0;
|
|
248
|
+
if (l === void 0) return o;
|
|
249
|
+
const a = t.timeScale.getRange(), p = a.to - a.from, f = p > 0 ? Math.min(1, Math.max(0, (i - a.from) / p)) : 0;
|
|
250
|
+
return l({ layerIndex: e, time: i, value: o, position: f });
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Extends the base last-value query with the 'grow' entrance's value-space
|
|
254
|
+
* equivalent of {@link chainedTailPositions}'s eased position lerp — the Y
|
|
255
|
+
* scale is affine, so lerping the *value* by the same eased progress and
|
|
256
|
+
* mapping it through `yScale` afterward lands on the identical pixel the
|
|
257
|
+
* renderer paints. Without this, a tooltip/YLabel query would report a
|
|
258
|
+
* freshly-appended point's raw value the instant it lands, `entryMs`
|
|
259
|
+
* before the marker visually arrives there.
|
|
260
|
+
*/
|
|
261
|
+
snapshotValue(t, e, i) {
|
|
262
|
+
const s = super.snapshotValue(t, e, i);
|
|
263
|
+
return (this.options.entryAnimation ?? "grow") !== "grow" ? s : this.chainedTailValues(t)?.get(e) ?? s;
|
|
264
|
+
}
|
|
265
|
+
/** Value-space counterpart of {@link chainedTailPositions} — see {@link snapshotValue}. */
|
|
266
|
+
chainedTailValues(t) {
|
|
267
|
+
const e = this.unsettledTail(t);
|
|
268
|
+
if (e.length === 0) return null;
|
|
269
|
+
const i = this.stores[t].getAll(), s = i.length - 1 - e.length;
|
|
270
|
+
if (s < 0) return null;
|
|
271
|
+
const o = i[s];
|
|
272
|
+
if (!Number.isFinite(o.value)) return null;
|
|
273
|
+
let n = this.liveValue(t, o.time, o.value);
|
|
274
|
+
const r = /* @__PURE__ */ new Map();
|
|
275
|
+
for (let l = 0; l < e.length; l++) {
|
|
276
|
+
const a = i[s + 1 + l];
|
|
277
|
+
if (!Number.isFinite(a.value)) return null;
|
|
278
|
+
const p = _(e[l].progress), f = this.liveValue(t, a.time, a.value), y = Y(n, f, p);
|
|
279
|
+
r.set(a.time, y), n = y;
|
|
280
|
+
}
|
|
281
|
+
return r;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Glowing pulse dots riding the intro's head anchors — the line reads as
|
|
285
|
+
* being plotted live, and hands off to the regular pulse dot the frame
|
|
286
|
+
* the reveal lands. Off-mode only: recomputing the stacked cumulative at
|
|
287
|
+
* an arbitrary head time isn't worth it for a one-second decoration.
|
|
288
|
+
*/
|
|
289
|
+
drawIntroHeads(t, e, i) {
|
|
290
|
+
if (this.options.stacking !== "off") return;
|
|
291
|
+
const s = Math.min(1, i / $), o = Math.min(1, (1 - i) / $), n = Math.max(0, Math.min(s, o));
|
|
292
|
+
if (n <= 0) return;
|
|
293
|
+
const { scope: r } = t;
|
|
294
|
+
for (const l of e)
|
|
295
|
+
for (let a = 0; a < this.stores.length; a++) {
|
|
296
|
+
const p = this.getLayerAlpha(a);
|
|
297
|
+
if (p <= 0 || !this.stores[a].isVisible()) continue;
|
|
298
|
+
const f = this.introHeadAnchor(t, a, l);
|
|
299
|
+
f !== null && this.drawPulse({
|
|
300
|
+
ctx: r.context,
|
|
301
|
+
x: f.x,
|
|
302
|
+
y: f.y,
|
|
303
|
+
color: this.resolveLayerColor(a, f.value),
|
|
304
|
+
pixelRatio: r.horizontalPixelRatio,
|
|
305
|
+
phase: i * 2,
|
|
306
|
+
alpha: n * p
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Where a head dot sits for one layer: pinned to the polyline as it is
|
|
312
|
+
* actually drawn this frame. Interior anchors interpolate through
|
|
313
|
+
* {@link effectiveValue}, so live smoothing and the intro's own value
|
|
314
|
+
* transform are honored while data streams during the reveal. Past the
|
|
315
|
+
* last point the head parks on the trailing endpoint — the exact spot the
|
|
316
|
+
* settled pulse dot takes over — and before the first point it parks on
|
|
317
|
+
* the line's start. Without the clamps the head slides into the
|
|
318
|
+
* right-padding region beyond the line's end (the sweep front travels the
|
|
319
|
+
* visible range, not the data span) and jumps back on settle.
|
|
320
|
+
*/
|
|
321
|
+
introHeadAnchor(t, e, i) {
|
|
322
|
+
const { timeScale: s, yScale: o } = t, n = s.getRange(), r = this.stores[e].getVisibleData(n.from, n.to);
|
|
323
|
+
if (r.length === 0) return null;
|
|
324
|
+
const l = this.stores[e].last();
|
|
325
|
+
if (l !== void 0 && i.time >= l.time) {
|
|
326
|
+
if (!Number.isFinite(l.value)) return null;
|
|
327
|
+
const f = this.trailingEndpoint(t, e);
|
|
328
|
+
return f === null ? null : { x: f.x, y: f.y, value: l.value };
|
|
329
|
+
}
|
|
330
|
+
const a = r[0];
|
|
331
|
+
if (i.time <= a.time) {
|
|
332
|
+
if (!Number.isFinite(a.value)) return null;
|
|
333
|
+
const f = this.effectiveValue(t, e, a.time, a.value);
|
|
334
|
+
return { x: s.timeToBitmapX(a.time), y: o.valueToBitmapY(f), value: a.value };
|
|
335
|
+
}
|
|
336
|
+
const p = U(r, i.time, (f) => this.effectiveValue(t, e, f.time, f.value));
|
|
337
|
+
return p === null ? null : { x: i.x, y: o.valueToBitmapY(p), value: p };
|
|
78
338
|
}
|
|
79
339
|
/**
|
|
80
340
|
* Rendered positions of the layer's still-unsettled trailing points, keyed
|
|
@@ -88,20 +348,70 @@ class ht extends nt {
|
|
|
88
348
|
* unsettled or any value in the chain (anchor included) is non-finite —
|
|
89
349
|
* callers fall back to raw geometry, mirroring the old NaN guard.
|
|
90
350
|
*/
|
|
351
|
+
/**
|
|
352
|
+
* Stacked cumulative value for `layerIndex` at `queryT`, alpha-weighted
|
|
353
|
+
* and reduced through {@link effectiveValue} — the single source of truth
|
|
354
|
+
* shared by {@link renderStacked}'s geometry and the overlay's crosshair /
|
|
355
|
+
* pulse dots, so they can never disagree. Any OTHER layer without a
|
|
356
|
+
* sample exactly at `queryT` holds its nearest earlier value forward
|
|
357
|
+
* instead of contributing 0: ragged streams tick independently, so a
|
|
358
|
+
* lagging sibling shouldn't zero out the moment another layer ticks past
|
|
359
|
+
* it (see `renderStacked`'s `valueMaps` comment for the full rationale).
|
|
360
|
+
*/
|
|
361
|
+
stackedValueAt(t, e, i) {
|
|
362
|
+
const s = this.options.stacking === "percent", o = (l) => {
|
|
363
|
+
const a = this.getLayerAlpha(l);
|
|
364
|
+
if (a <= 0) return 0;
|
|
365
|
+
const p = this.stores[l].getAll();
|
|
366
|
+
if (p.length === 0 || i < p[0].time) return 0;
|
|
367
|
+
const f = U(p, i, (y) => this.effectiveValue(t, l, y.time, y.value));
|
|
368
|
+
return f === null ? 0 : f * a;
|
|
369
|
+
};
|
|
370
|
+
let n = 0;
|
|
371
|
+
if (s)
|
|
372
|
+
for (let l = 0; l < this.stores.length; l++) n += o(l);
|
|
373
|
+
let r = 0;
|
|
374
|
+
for (let l = 0; l <= e; l++) {
|
|
375
|
+
const a = o(l);
|
|
376
|
+
r += s && n > 0 ? a / n * 100 : a;
|
|
377
|
+
}
|
|
378
|
+
return r;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Bitmap position for layer `li`'s stacked boundary at time `t`, chain-
|
|
382
|
+
* lerped through that layer's own still-unsettled trailing entries when
|
|
383
|
+
* `t` is its current live tip — a single dot has no shared edge to tear,
|
|
384
|
+
* so (unlike `renderStacked`'s polygon boundaries) gating off the layer's
|
|
385
|
+
* own entrance state is enough. Falls back to the raw settled position
|
|
386
|
+
* for historical points or when the 'grow' entrance is disabled.
|
|
387
|
+
*/
|
|
388
|
+
stackedPositionAt(t, e, i) {
|
|
389
|
+
const { timeScale: s, yScale: o } = t, n = s.timeToBitmapX(i), r = o.valueToBitmapY(this.stackedValueAt(t, e, i)), l = this.stores[e].last()?.time;
|
|
390
|
+
if ((this.options.entryAnimation ?? "grow") !== "grow" || i !== l) return { x: n, y: r };
|
|
391
|
+
const a = this.unsettledTail(e), p = this.stores[e].getAll(), f = p.length - 1 - a.length;
|
|
392
|
+
if (a.length === 0 || f < 0) return { x: n, y: r };
|
|
393
|
+
const y = p[f];
|
|
394
|
+
let h = s.timeToBitmapX(y.time), m = o.valueToBitmapY(this.stackedValueAt(t, e, y.time));
|
|
395
|
+
for (let u = 0; u < a.length; u++) {
|
|
396
|
+
const A = p[f + 1 + u], R = _(a[u].progress), M = s.timeToBitmapX(A.time), I = o.valueToBitmapY(this.stackedValueAt(t, e, A.time));
|
|
397
|
+
h = Y(h, M, R), m = Y(m, I, R);
|
|
398
|
+
}
|
|
399
|
+
return { x: h, y: m };
|
|
400
|
+
}
|
|
91
401
|
chainedTailPositions(t, e) {
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
96
|
-
const { timeScale:
|
|
97
|
-
if (!Number.isFinite(
|
|
98
|
-
let
|
|
402
|
+
const i = this.unsettledTail(e);
|
|
403
|
+
if (i.length === 0) return null;
|
|
404
|
+
const s = this.stores[e].getAll(), o = s.length - 1 - i.length;
|
|
405
|
+
if (o < 0) return null;
|
|
406
|
+
const { timeScale: n, yScale: r } = t, l = s[o];
|
|
407
|
+
if (!Number.isFinite(l.value)) return null;
|
|
408
|
+
let a = n.timeToBitmapX(l.time), p = r.valueToBitmapY(this.effectiveValue(t, e, l.time, l.value));
|
|
99
409
|
const f = /* @__PURE__ */ new Map();
|
|
100
|
-
for (let
|
|
101
|
-
const h =
|
|
410
|
+
for (let y = 0; y < i.length; y++) {
|
|
411
|
+
const h = s[o + 1 + y];
|
|
102
412
|
if (!Number.isFinite(h.value)) return null;
|
|
103
|
-
const
|
|
104
|
-
f.set(h.time, { x:
|
|
413
|
+
const m = _(i[y].progress), u = n.timeToBitmapX(h.time), A = r.valueToBitmapY(this.effectiveValue(t, e, h.time, h.value)), R = Y(a, u, m), M = Y(p, A, m);
|
|
414
|
+
f.set(h.time, { x: R, y: M }), a = R, p = M;
|
|
105
415
|
}
|
|
106
416
|
return f;
|
|
107
417
|
}
|
|
@@ -116,10 +426,10 @@ class ht extends nt {
|
|
|
116
426
|
* of teleporting to the raw last.time while the line still unfurls.
|
|
117
427
|
*/
|
|
118
428
|
trailingEndpoint(t, e) {
|
|
119
|
-
const
|
|
120
|
-
if (!
|
|
121
|
-
const { timeScale:
|
|
122
|
-
return (this.options.entryAnimation ?? "grow") !== "grow" ? { x:
|
|
429
|
+
const i = this.stores[e].last();
|
|
430
|
+
if (!i) return null;
|
|
431
|
+
const { timeScale: s, yScale: o } = t, n = s.timeToBitmapX(i.time), r = o.valueToBitmapY(this.effectiveValue(t, e, i.time, i.value));
|
|
432
|
+
return (this.options.entryAnimation ?? "grow") !== "grow" ? { x: n, y: r } : this.chainedTailPositions(t, e)?.get(i.time) ?? { x: n, y: r };
|
|
123
433
|
}
|
|
124
434
|
/**
|
|
125
435
|
* Vertical stroke + area gradients for `options.threshold`, pinned to the
|
|
@@ -131,191 +441,232 @@ class ht extends nt {
|
|
|
131
441
|
* the row would miss almost every frame anyway.
|
|
132
442
|
*/
|
|
133
443
|
buildThresholdPaint(t, e) {
|
|
134
|
-
const
|
|
135
|
-
if (!
|
|
136
|
-
const { scope:
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
return
|
|
444
|
+
const i = this.options.threshold;
|
|
445
|
+
if (!i) return null;
|
|
446
|
+
const { scope: s, yScale: o } = t, { context: n } = s, r = s.bitmapSize.height, l = i.above, a = i.below ?? e, p = Math.min(1, Math.max(0, o.valueToBitmapY(i.value) / r)), f = Math.min(6 * s.verticalPixelRatio, r * 0.02) / r, y = Math.max(0, p - f), h = Math.min(1, p + f), m = n.createLinearGradient(0, 0, 0, r);
|
|
447
|
+
m.addColorStop(0, l), m.addColorStop(y, l), m.addColorStop(h, a), m.addColorStop(1, a);
|
|
448
|
+
const u = n.createLinearGradient(0, 0, 0, r);
|
|
449
|
+
return u.addColorStop(0, C(l, 0.26)), u.addColorStop(y, C(l, 0.14)), u.addColorStop(h, C(a, 0.1)), u.addColorStop(1, C(a, 0.01)), { stroke: m, area: u };
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Dot markers at each data point (`options.points`). Callers pass the same
|
|
453
|
+
* animated vertices the stroke was built from, so the dots glide with the
|
|
454
|
+
* entrance unfurl and live-value smoothing instead of snapping to raw
|
|
455
|
+
* geometry. Skipped for the frame when the average horizontal spacing falls
|
|
456
|
+
* under ~1.5 dot diameters — dots that dense melt into a fat line and hide
|
|
457
|
+
* the stroke.
|
|
458
|
+
*/
|
|
459
|
+
drawPointMarkers(t) {
|
|
460
|
+
const e = this.options.points;
|
|
461
|
+
if (!e?.visible) return;
|
|
462
|
+
const { context: i, points: s, pixelRatio: o, color: n } = t;
|
|
463
|
+
if (s.length === 0) return;
|
|
464
|
+
const r = Math.max(1, (e.radius ?? 3) * o);
|
|
465
|
+
if (!(s.length > 1 && (s[s.length - 1].x - s[0].x) / (s.length - 1) < r * 3)) {
|
|
466
|
+
i.beginPath();
|
|
467
|
+
for (const l of s)
|
|
468
|
+
i.moveTo(l.x + r, l.y), i.arc(l.x, l.y, r, 0, Math.PI * 2);
|
|
469
|
+
i.fillStyle = e.color ?? n, i.fill();
|
|
470
|
+
}
|
|
140
471
|
}
|
|
141
472
|
/** Each layer drawn independently */
|
|
142
473
|
renderOff(t) {
|
|
143
|
-
const { scope: e, timeScale:
|
|
144
|
-
ctx:
|
|
474
|
+
const { scope: e, timeScale: i, yScale: s } = t, { context: o } = e, n = i.getRange(), { verticalPixelRatio: r } = e, l = this.options.strokeWidth > 0, a = Math.max(1, Math.round(this.options.strokeWidth * r)), p = this.options.entryAnimation ?? "grow", f = ht(this.options.linePainter ?? this.options.curve ?? "straight"), y = {
|
|
475
|
+
ctx: o,
|
|
145
476
|
theme: t.theme,
|
|
146
477
|
horizontalPixelRatio: e.horizontalPixelRatio,
|
|
147
|
-
verticalPixelRatio:
|
|
478
|
+
verticalPixelRatio: r
|
|
148
479
|
};
|
|
149
480
|
for (let h = 0; h < this.stores.length; h++) {
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
let
|
|
153
|
-
const
|
|
154
|
-
if (
|
|
155
|
-
const
|
|
156
|
-
x:
|
|
157
|
-
y:
|
|
158
|
-
},
|
|
159
|
-
(
|
|
160
|
-
const S =
|
|
161
|
-
let
|
|
162
|
-
for (let
|
|
163
|
-
const
|
|
164
|
-
if (!Number.isFinite(
|
|
165
|
-
|
|
481
|
+
const m = this.getLayerAlpha(h);
|
|
482
|
+
if (m <= 0) continue;
|
|
483
|
+
let u = this.stores[h].getVisibleData(n.from, n.to);
|
|
484
|
+
const A = e.mediaSize.width;
|
|
485
|
+
if (u.length > A * 2 && (u = j(u, Math.round(A * 1.5))), u.length < 2) continue;
|
|
486
|
+
const R = this.stores[h].last()?.value ?? u[u.length - 1].value, M = this.resolveLayerColor(h, R), I = this.buildThresholdPaint(t, M), F = u[u.length - 1], z = this.stores[h].last(), D = z !== void 0 && F.time === z.time, N = D ? this.entranceProgress(h, F.time) : 1, W = D && p === "fade" && N < 1, E = (D ? this.trailingEndpoint(t, h) : null) ?? {
|
|
487
|
+
x: i.timeToBitmapX(F.time),
|
|
488
|
+
y: s.valueToBitmapY(this.effectiveValue(t, h, F.time, F.value))
|
|
489
|
+
}, G = E.x, c = E.y, x = D && p === "grow" ? this.chainedTailPositions(t, h) : null, b = m < 1;
|
|
490
|
+
(b || W) && (o.save(), b && (o.globalAlpha *= m), W && (o.globalAlpha *= N));
|
|
491
|
+
const S = u.length - 1, d = [];
|
|
492
|
+
let T = null;
|
|
493
|
+
for (let P = 0; P < S; P++) {
|
|
494
|
+
const B = u[P].value;
|
|
495
|
+
if (!Number.isFinite(B)) {
|
|
496
|
+
T = null;
|
|
166
497
|
continue;
|
|
167
498
|
}
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
171
|
-
|
|
499
|
+
T || (T = [], d.push(T));
|
|
500
|
+
const g = x?.get(u[P].time);
|
|
501
|
+
if (g)
|
|
502
|
+
T.push({ x: g.x, y: g.y });
|
|
172
503
|
else {
|
|
173
|
-
const
|
|
174
|
-
|
|
504
|
+
const L = s.valueToBitmapY(this.effectiveValue(t, h, u[P].time, B));
|
|
505
|
+
T.push({ x: i.timeToBitmapX(u[P].time), y: L });
|
|
175
506
|
}
|
|
176
507
|
}
|
|
177
|
-
const
|
|
178
|
-
let
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
for (const
|
|
182
|
-
|
|
183
|
-
|
|
508
|
+
const k = u[S]?.value, V = Number.isFinite(G) && Number.isFinite(c) && Number.isFinite(k), X = p === "grow" && N < 1;
|
|
509
|
+
let H = null;
|
|
510
|
+
if (V && (T ? (T.push({ x: G, y: c }), H = T) : d.push([{ x: G, y: c }])), l && d.some((P) => P.length >= 2)) {
|
|
511
|
+
o.beginPath();
|
|
512
|
+
for (const P of d)
|
|
513
|
+
P.length < 2 || f(y, { points: P, color: M, lineWidth: a, closing: !1, grew: X && P === H });
|
|
514
|
+
o.strokeStyle = I ? I.stroke : M, o.lineWidth = a, o.lineJoin = "round", o.lineCap = "round", o.stroke();
|
|
184
515
|
}
|
|
185
|
-
if (
|
|
186
|
-
const
|
|
187
|
-
let
|
|
188
|
-
for (const
|
|
189
|
-
|
|
190
|
-
|
|
516
|
+
if (l) {
|
|
517
|
+
const P = Math.max(1, a / 2);
|
|
518
|
+
let B = !1;
|
|
519
|
+
for (const g of d)
|
|
520
|
+
g.length === 1 && (B || (o.beginPath(), B = !0), o.moveTo(g[0].x + P, g[0].y), o.arc(g[0].x, g[0].y, P, 0, Math.PI * 2));
|
|
521
|
+
B && (o.fillStyle = M, o.fill());
|
|
191
522
|
}
|
|
192
|
-
if (this.options.area.visible) {
|
|
193
|
-
const
|
|
194
|
-
let
|
|
523
|
+
if (this.options.area.visible && !this.introGhostPass) {
|
|
524
|
+
const P = e.bitmapSize.height;
|
|
525
|
+
let B;
|
|
195
526
|
if (I)
|
|
196
|
-
|
|
527
|
+
B = I.area;
|
|
197
528
|
else {
|
|
198
|
-
const
|
|
199
|
-
|
|
529
|
+
const g = String(h), L = this.areaGradientCache.get(g);
|
|
530
|
+
L && L.bottomY === P && L.color === M ? B = L.gradient : (B = o.createLinearGradient(0, 0, 0, P), B.addColorStop(0, C(M, 0.12)), B.addColorStop(1, C(M, 0.01)), this.areaGradientCache.set(g, { gradient: B, bottomY: P, color: M }));
|
|
200
531
|
}
|
|
201
|
-
|
|
202
|
-
for (const
|
|
203
|
-
|
|
532
|
+
o.fillStyle = B;
|
|
533
|
+
for (const g of d)
|
|
534
|
+
g.length < 2 || (o.beginPath(), f(y, { points: g, color: M, lineWidth: a, closing: !0, grew: X && g === H }), o.lineTo(g[g.length - 1].x, P), o.lineTo(g[0].x, P), o.closePath(), o.fill());
|
|
535
|
+
}
|
|
536
|
+
if (this.options.points?.visible) {
|
|
537
|
+
const P = [];
|
|
538
|
+
for (const B of d)
|
|
539
|
+
for (const g of B) P.push(g);
|
|
540
|
+
this.drawPointMarkers({ context: o, points: P, pixelRatio: e.horizontalPixelRatio, color: M });
|
|
204
541
|
}
|
|
205
|
-
(
|
|
542
|
+
(W || b) && o.restore();
|
|
206
543
|
}
|
|
207
544
|
}
|
|
208
545
|
/** Stacked area rendering */
|
|
209
546
|
renderStacked(t, e) {
|
|
210
|
-
const { scope:
|
|
211
|
-
if (this.getLayerAlpha(
|
|
212
|
-
let
|
|
213
|
-
return
|
|
214
|
-
}),
|
|
215
|
-
for (const
|
|
216
|
-
for (const
|
|
217
|
-
const
|
|
218
|
-
if (
|
|
219
|
-
const
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
547
|
+
const { scope: i, timeScale: s, yScale: o } = t, { context: n } = i, r = s.getRange(), { verticalPixelRatio: l } = i, a = this.options.strokeWidth > 0, p = Math.max(1, Math.round(this.options.strokeWidth * l)), f = this.options.curve ?? "straight", y = i.mediaSize.width, h = this.stores.map((c, x) => {
|
|
548
|
+
if (this.getLayerAlpha(x) <= 0) return [];
|
|
549
|
+
let b = c.getVisibleData(r.from, r.to);
|
|
550
|
+
return b.length > y * 2 && (b = j(b, Math.round(y * 1.5))), b;
|
|
551
|
+
}), m = /* @__PURE__ */ new Set();
|
|
552
|
+
for (const c of h)
|
|
553
|
+
for (const x of c) m.add(x.time);
|
|
554
|
+
const u = Array.from(m).sort((c, x) => c - x);
|
|
555
|
+
if (u.length < 2) return;
|
|
556
|
+
const A = h.map((c, x) => {
|
|
557
|
+
const b = /* @__PURE__ */ new Map();
|
|
558
|
+
if (c.length === 0) return b;
|
|
559
|
+
const S = this.getLayerAlpha(x), d = c[0].time;
|
|
560
|
+
for (const T of u) {
|
|
561
|
+
if (T < d) continue;
|
|
562
|
+
const k = U(c, T, (V) => this.effectiveValue(t, x, V.time, V.value));
|
|
563
|
+
k !== null && b.set(T, k * S);
|
|
564
|
+
}
|
|
565
|
+
return b;
|
|
566
|
+
}), R = Array.from({ length: this.stores.length }, () => new Array(u.length).fill(0));
|
|
567
|
+
for (let c = 0; c < u.length; c++) {
|
|
568
|
+
const x = u[c];
|
|
569
|
+
let b = 0;
|
|
227
570
|
if (e)
|
|
228
|
-
for (let
|
|
229
|
-
const
|
|
230
|
-
Number.isFinite(
|
|
571
|
+
for (let d = 0; d < this.stores.length; d++) {
|
|
572
|
+
const T = A[d].get(x);
|
|
573
|
+
Number.isFinite(T) && (b += T);
|
|
231
574
|
}
|
|
232
575
|
let S = 0;
|
|
233
|
-
for (let
|
|
234
|
-
const
|
|
235
|
-
S += e &&
|
|
576
|
+
for (let d = 0; d < this.stores.length; d++) {
|
|
577
|
+
const T = A[d].get(x), k = Number.isFinite(T) ? T : 0;
|
|
578
|
+
S += e && b > 0 ? k / b * 100 : k, R[d][c] = S;
|
|
236
579
|
}
|
|
237
580
|
}
|
|
238
|
-
const
|
|
239
|
-
for (let
|
|
240
|
-
const
|
|
241
|
-
for (let
|
|
242
|
-
if (this.getLayerAlpha(
|
|
243
|
-
const
|
|
244
|
-
if (
|
|
581
|
+
const M = this.options.entryAnimation ?? "grow", I = /* @__PURE__ */ new Map();
|
|
582
|
+
for (let c = 0; c < u.length; c++) I.set(u[c], c);
|
|
583
|
+
const F = new Array(this.stores.length).fill(1);
|
|
584
|
+
for (let c = 0; c < this.stores.length; c++) {
|
|
585
|
+
if (this.getLayerAlpha(c) <= 0) continue;
|
|
586
|
+
const x = this.unsettledTail(c), b = x.length;
|
|
587
|
+
if (b === 0) continue;
|
|
245
588
|
let S = !0;
|
|
246
|
-
for (let
|
|
247
|
-
if (I.get(
|
|
589
|
+
for (let d = 0; d < b; d++)
|
|
590
|
+
if (I.get(x[d].time) !== u.length - b + d) {
|
|
248
591
|
S = !1;
|
|
249
592
|
break;
|
|
250
593
|
}
|
|
251
|
-
|
|
252
|
-
const p = this.stores[i].getAll(), x = p.length - 1 - a;
|
|
253
|
-
x < 0 || I.get(p[x].time) === o.length - a - 1 && (E[i] = c.map((F) => J(F.progress)), b[i] = c[a - 1].progress);
|
|
594
|
+
S && (F[c] = x[b - 1].progress);
|
|
254
595
|
}
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
596
|
+
const z = [];
|
|
597
|
+
if (M === "grow")
|
|
598
|
+
for (let c = u.length - 1; c >= 0; c--) {
|
|
599
|
+
const x = u[c];
|
|
600
|
+
let b = 1, S = !1;
|
|
601
|
+
for (let d = 0; d < this.stores.length; d++) {
|
|
602
|
+
if (this.getLayerAlpha(d) <= 0 || this.entries[d]?.get(x) === void 0) continue;
|
|
603
|
+
const T = this.entranceProgress(d, x);
|
|
604
|
+
T >= 1 || (S = !0, T < b && (b = T));
|
|
261
605
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
T =
|
|
270
|
-
|
|
606
|
+
if (!S) break;
|
|
607
|
+
z.unshift(_(b));
|
|
608
|
+
}
|
|
609
|
+
const D = (c, x) => {
|
|
610
|
+
const b = x.length;
|
|
611
|
+
if (!(b === 0 || c.length < b + 1))
|
|
612
|
+
for (let S = 0; S < b; S++) {
|
|
613
|
+
const d = c.length - b + S, T = c[d - 1], k = c[d];
|
|
614
|
+
c[d] = [Y(T[0], k[0], x[S]), Y(T[1], k[1], x[S])];
|
|
271
615
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (c <= 0)
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
x = R;
|
|
616
|
+
}, N = i.bitmapSize.height;
|
|
617
|
+
let W = -1, E = -1;
|
|
618
|
+
for (let c = 0; c < this.stores.length; c++)
|
|
619
|
+
if (!(this.getLayerAlpha(c) <= 0))
|
|
620
|
+
if (W < 0)
|
|
621
|
+
W = c;
|
|
622
|
+
else {
|
|
623
|
+
E = c;
|
|
281
624
|
break;
|
|
282
625
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
626
|
+
const G = W >= 0 ? this.getLayerAlpha(W) : 1;
|
|
627
|
+
for (let c = this.stores.length - 1; c >= 0; c--) {
|
|
628
|
+
const x = this.getLayerAlpha(c);
|
|
629
|
+
if (x <= 0) continue;
|
|
630
|
+
const b = this.stores[c].last()?.value ?? 0, S = this.resolveLayerColor(c, b), d = c === W, T = E >= 0 && c === E && G < 1, k = [];
|
|
631
|
+
for (let g = 0; g < u.length; g++) {
|
|
632
|
+
const L = c > 0 ? o.valueToBitmapY(R[c - 1][g]) : N;
|
|
633
|
+
let O = L;
|
|
634
|
+
d ? O = N : T && (O = L + (N - L) * (1 - G)), k.push([s.timeToBitmapX(u[g]), O]);
|
|
288
635
|
}
|
|
289
|
-
|
|
290
|
-
const
|
|
291
|
-
for (let
|
|
292
|
-
let
|
|
293
|
-
|
|
636
|
+
M === "grow" && !d && D(k, z);
|
|
637
|
+
const V = [];
|
|
638
|
+
for (let g = 0; g < u.length; g++) {
|
|
639
|
+
let L = o.valueToBitmapY(R[c][g]);
|
|
640
|
+
d && x < 1 && (L = N + (L - N) * x), V.push([s.timeToBitmapX(u[g]), L]);
|
|
294
641
|
}
|
|
295
|
-
|
|
296
|
-
const
|
|
297
|
-
if (
|
|
298
|
-
let
|
|
299
|
-
for (let
|
|
300
|
-
|
|
301
|
-
for (let
|
|
302
|
-
|
|
303
|
-
let
|
|
304
|
-
if (
|
|
305
|
-
const
|
|
306
|
-
|
|
642
|
+
M === "grow" && D(V, z);
|
|
643
|
+
const X = Z(V), H = q(X, f, M === "grow" && z.length > 0), P = M === "fade" && F[c] < 1;
|
|
644
|
+
if (P && (n.save(), n.globalAlpha *= F[c]), this.options.area.visible && !this.introGhostPass) {
|
|
645
|
+
let g = V[0][1], L = k[0][1];
|
|
646
|
+
for (let w = 1; w < V.length; w++)
|
|
647
|
+
V[w][1] < g && (g = V[w][1]);
|
|
648
|
+
for (let w = 1; w < k.length; w++)
|
|
649
|
+
k[w][1] > L && (L = k[w][1]);
|
|
650
|
+
let O = C(S, 0.25);
|
|
651
|
+
if (L > g + 0.5) {
|
|
652
|
+
const w = n.createLinearGradient(0, g, 0, L);
|
|
653
|
+
w.addColorStop(0, C(S, 0.25)), w.addColorStop(1, C(S, 0.05)), O = w;
|
|
307
654
|
}
|
|
308
|
-
if (
|
|
309
|
-
for (let
|
|
310
|
-
|
|
655
|
+
if (n.beginPath(), n.moveTo(X[0].x, X[0].y), K(n, H), d)
|
|
656
|
+
for (let w = k.length - 1; w >= 0; w--)
|
|
657
|
+
n.lineTo(k[w][0], k[w][1]);
|
|
311
658
|
else {
|
|
312
|
-
const
|
|
313
|
-
|
|
659
|
+
const w = Z(k), nt = q(w, f, M === "grow" && z.length > 0), J = w[w.length - 1];
|
|
660
|
+
n.lineTo(J.x, J.y), ft(n, w, nt);
|
|
314
661
|
}
|
|
315
|
-
|
|
662
|
+
n.closePath(), n.fillStyle = O, n.fill();
|
|
663
|
+
}
|
|
664
|
+
const B = a && x < 1;
|
|
665
|
+
if (B && (n.save(), n.globalAlpha *= x), a && (n.beginPath(), n.moveTo(X[0].x, X[0].y), K(n, H), n.strokeStyle = S, n.lineWidth = p, n.lineJoin = "round", n.lineCap = "round", n.stroke()), B && n.restore(), this.options.points?.visible) {
|
|
666
|
+
const g = x < 1;
|
|
667
|
+
g && (n.save(), n.globalAlpha *= x), this.drawPointMarkers({ context: n, points: X, pixelRatio: i.horizontalPixelRatio, color: S }), g && n.restore();
|
|
316
668
|
}
|
|
317
|
-
|
|
318
|
-
j && (l.save(), l.globalAlpha *= c), k && (l.beginPath(), l.moveTo(w[0].x, w[0].y), tt(l, A), l.strokeStyle = S, l.lineWidth = B, l.lineJoin = "round", l.lineCap = "round", l.stroke()), j && l.restore(), O && l.restore();
|
|
669
|
+
P && n.restore();
|
|
319
670
|
}
|
|
320
671
|
}
|
|
321
672
|
/**
|
|
@@ -324,97 +675,54 @@ class ht extends nt {
|
|
|
324
675
|
*/
|
|
325
676
|
drawOverlay(t) {
|
|
326
677
|
this.tickAnimations(performance.now());
|
|
327
|
-
const { scope: e, timeScale:
|
|
328
|
-
if (
|
|
329
|
-
const
|
|
330
|
-
for (let
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
for (let y = 0; y < m.length; y++)
|
|
341
|
-
o += m[y] * this.getLayerAlpha(y);
|
|
342
|
-
let C = 0;
|
|
343
|
-
for (let y = 0; y < m.length; y++) {
|
|
344
|
-
const g = m[y] * this.getLayerAlpha(y);
|
|
345
|
-
C += B === "percent" && o > 0 ? g / o * 100 : g, P.push(C);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
for (let o = 0; o < this.stores.length; o++) {
|
|
349
|
-
const C = h[o];
|
|
350
|
-
if (C === null) continue;
|
|
351
|
-
const y = this.getLayerAlpha(o);
|
|
352
|
-
if (y <= 0) continue;
|
|
353
|
-
const g = this.resolveLayerColor(o, m[o]), I = s.timeToBitmapX(C), E = r.valueToBitmapY(P[o]), b = y < 1;
|
|
354
|
-
b && (e.context.save(), e.context.globalAlpha *= y), e.context.save(), e.context.globalAlpha *= 0.25, e.context.beginPath(), e.context.arc(I, E, f + 3 * d.horizontalPixelRatio, 0, Math.PI * 2), e.context.fillStyle = g, e.context.fill(), e.context.restore(), e.context.beginPath(), e.context.arc(I, E, f, 0, Math.PI * 2), e.context.fillStyle = g, e.context.fill(), b && e.context.restore();
|
|
678
|
+
const { scope: e, timeScale: i, yScale: s, crosshair: o, dataInterval: n } = t, r = e, l = this.options.pulseMs, a = l > 0 ? performance.now() / (l * 2 * Math.PI) % 1 : 0;
|
|
679
|
+
if (o) {
|
|
680
|
+
const y = this.options.stacking, h = 4 * r.horizontalPixelRatio;
|
|
681
|
+
for (let m = 0; m < this.stores.length; m++) {
|
|
682
|
+
const u = this.getLayerAlpha(m);
|
|
683
|
+
if (u <= 0) continue;
|
|
684
|
+
const A = this.stores[m].findNearest(o.time, n);
|
|
685
|
+
if (!A) continue;
|
|
686
|
+
const R = this.resolveLayerColor(m, A.value), { x: M, y: I } = y === "off" ? {
|
|
687
|
+
x: i.timeToBitmapX(A.time),
|
|
688
|
+
y: s.valueToBitmapY(this.effectiveValue(t, m, A.time, A.value))
|
|
689
|
+
} : this.stackedPositionAt(t, m, A.time), F = u < 1;
|
|
690
|
+
F && (e.context.save(), e.context.globalAlpha *= u), e.context.save(), e.context.globalAlpha *= 0.25, e.context.beginPath(), e.context.arc(M, I, h + 3 * r.horizontalPixelRatio, 0, Math.PI * 2), e.context.fillStyle = R, e.context.fill(), e.context.restore(), e.context.beginPath(), e.context.arc(M, I, h, 0, Math.PI * 2), e.context.fillStyle = R, e.context.fill(), F && e.context.restore();
|
|
355
691
|
}
|
|
356
692
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
693
|
+
const p = this.introWave.active && this.introDirectives?.clip !== void 0;
|
|
694
|
+
let f = 1;
|
|
695
|
+
if (p && (f = Math.max(0, (this.introWave.linear() - (1 - $)) / $)), this.hasPulse && l > 0 && f > 0) {
|
|
696
|
+
const y = this.options.stacking;
|
|
697
|
+
for (let h = 0; h < this.stores.length; h++) {
|
|
698
|
+
const m = this.getLayerAlpha(h);
|
|
361
699
|
if (m <= 0) continue;
|
|
362
|
-
const
|
|
363
|
-
if (
|
|
364
|
-
const
|
|
365
|
-
if (!
|
|
700
|
+
const u = this.stores[h].last()?.value ?? 0, A = this.resolveLayerColor(h, u);
|
|
701
|
+
if (y === "off") {
|
|
702
|
+
const F = this.trailingEndpoint(t, h);
|
|
703
|
+
if (!F) continue;
|
|
366
704
|
this.drawPulse({
|
|
367
705
|
ctx: e.context,
|
|
368
|
-
x:
|
|
369
|
-
y:
|
|
370
|
-
color:
|
|
371
|
-
pixelRatio:
|
|
372
|
-
phase:
|
|
373
|
-
alpha: m
|
|
706
|
+
x: F.x,
|
|
707
|
+
y: F.y,
|
|
708
|
+
color: A,
|
|
709
|
+
pixelRatio: r.horizontalPixelRatio,
|
|
710
|
+
phase: a,
|
|
711
|
+
alpha: m * f
|
|
374
712
|
});
|
|
375
713
|
continue;
|
|
376
714
|
}
|
|
377
|
-
const
|
|
378
|
-
if (!
|
|
379
|
-
const
|
|
380
|
-
const W = (T) => {
|
|
381
|
-
const z = this.getLayerAlpha(T);
|
|
382
|
-
if (z <= 0) return 0;
|
|
383
|
-
const i = T === f && b === C ? o : this.stores[T].findNearest(b, 0);
|
|
384
|
-
return !i || i.time !== b ? 0 : this.effectiveValue(t, T, b, i.value) * z;
|
|
385
|
-
};
|
|
386
|
-
let Y = 0;
|
|
387
|
-
if (y)
|
|
388
|
-
for (let T = 0; T < this.stores.length; T++)
|
|
389
|
-
Y += W(T);
|
|
390
|
-
let N = 0;
|
|
391
|
-
for (let T = 0; T <= f; T++) {
|
|
392
|
-
const z = W(T);
|
|
393
|
-
N += y && Y > 0 ? z / Y * 100 : z;
|
|
394
|
-
}
|
|
395
|
-
return N;
|
|
396
|
-
};
|
|
397
|
-
let I = s.timeToBitmapX(C), E = r.valueToBitmapY(g(C));
|
|
398
|
-
if ((this.options.entryAnimation ?? "grow") === "grow") {
|
|
399
|
-
const b = this.unsettledTail(t, f), W = this.stores[f].getAll(), Y = W.length - 1 - b.length;
|
|
400
|
-
if (b.length > 0 && Y >= 0) {
|
|
401
|
-
const N = W[Y];
|
|
402
|
-
let T = s.timeToBitmapX(N.time), z = r.valueToBitmapY(g(N.time));
|
|
403
|
-
for (let i = 0; i < b.length; i++) {
|
|
404
|
-
const c = W[Y + 1 + i], a = J(b[i].progress), S = s.timeToBitmapX(c.time), p = r.valueToBitmapY(g(c.time));
|
|
405
|
-
T = U(T, S, a), z = U(z, p, a);
|
|
406
|
-
}
|
|
407
|
-
I = T, E = z;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
715
|
+
const R = this.stores[h].last();
|
|
716
|
+
if (!R) continue;
|
|
717
|
+
const { x: M, y: I } = this.stackedPositionAt(t, h, R.time);
|
|
410
718
|
this.drawPulse({
|
|
411
719
|
ctx: e.context,
|
|
412
|
-
x:
|
|
413
|
-
y:
|
|
414
|
-
color:
|
|
415
|
-
pixelRatio:
|
|
416
|
-
phase:
|
|
417
|
-
alpha: m
|
|
720
|
+
x: M,
|
|
721
|
+
y: I,
|
|
722
|
+
color: A,
|
|
723
|
+
pixelRatio: r.horizontalPixelRatio,
|
|
724
|
+
phase: a,
|
|
725
|
+
alpha: m * f
|
|
418
726
|
});
|
|
419
727
|
}
|
|
420
728
|
}
|
|
@@ -422,25 +730,25 @@ class ht extends nt {
|
|
|
422
730
|
drawPulse({
|
|
423
731
|
ctx: t,
|
|
424
732
|
x: e,
|
|
425
|
-
y:
|
|
426
|
-
color:
|
|
427
|
-
pixelRatio:
|
|
428
|
-
phase:
|
|
429
|
-
alpha:
|
|
733
|
+
y: i,
|
|
734
|
+
color: s,
|
|
735
|
+
pixelRatio: o,
|
|
736
|
+
phase: n,
|
|
737
|
+
alpha: r = 1
|
|
430
738
|
}) {
|
|
431
|
-
const
|
|
432
|
-
f && (t.save(), t.globalAlpha *=
|
|
739
|
+
const l = 3 * o, a = 0.4 + 0.6 * Math.abs(Math.sin(n * 2 * Math.PI)), p = l + 4 * o * a, f = r < 1;
|
|
740
|
+
f && (t.save(), t.globalAlpha *= r), t.beginPath(), t.arc(e, i, p, 0, Math.PI * 2), t.fillStyle = C(s, a * 0.3), t.fill(), t.beginPath(), t.arc(e, i, l, 0, Math.PI * 2), t.fillStyle = s, t.fill(), f && t.restore();
|
|
433
741
|
}
|
|
434
742
|
}
|
|
435
|
-
const
|
|
743
|
+
const Pt = {
|
|
436
744
|
type: "line",
|
|
437
|
-
create: ({ theme: v, layerCount: t }, e) => new
|
|
745
|
+
create: ({ theme: v, layerCount: t }, e) => new mt(t, {
|
|
438
746
|
colors: t === 1 ? [v.line.color] : v.seriesColors.slice(0, t),
|
|
439
747
|
strokeWidth: v.line.width,
|
|
440
748
|
...e
|
|
441
749
|
})
|
|
442
750
|
};
|
|
443
751
|
export {
|
|
444
|
-
|
|
445
|
-
|
|
752
|
+
mt as LineRenderer,
|
|
753
|
+
Pt as LineSeriesDef
|
|
446
754
|
};
|