@wick-charts/vue 0.8.0 → 0.8.2
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 +2 -0
- package/dist/BandSeries.vue.js +43 -32
- package/dist/BarSeries.vue.js +44 -33
- package/dist/CandlestickSeries.vue.js +24 -23
- package/dist/ChartContainer.vue.js +1 -1
- package/dist/HeatmapSeries.vue.js +21 -20
- package/dist/LineSeries.vue.js +43 -32
- package/dist/PieSeries.vue.js +25 -24
- package/dist/composables.js +63 -36
- package/dist/core/dist/axis/dom-labels.js +64 -53
- package/dist/core/dist/chart/badge-animator.js +38 -28
- package/dist/core/dist/chart/options.js +1 -1
- package/dist/core/dist/chart/y-target.js +38 -32
- package/dist/core/dist/chart.js +852 -709
- package/dist/core/dist/data/decimation.js +52 -51
- package/dist/core/dist/data/store.js +38 -20
- package/dist/core/dist/data/sync.js +97 -59
- package/dist/core/dist/navigator/controller.js +11 -11
- package/dist/core/dist/perf/perf-hud.js +3 -3
- package/dist/core/dist/scales/tick-tracker.js +2 -1
- package/dist/core/dist/scales/time-ticks.js +99 -0
- package/dist/core/dist/scales/x-scale.js +33 -27
- package/dist/core/dist/series/band.js +83 -83
- package/dist/core/dist/series/bar.js +240 -211
- package/dist/core/dist/series/base-multi-layer.js +288 -240
- package/dist/core/dist/series/candlestick.js +168 -168
- package/dist/core/dist/series/line.js +545 -455
- package/dist/core/dist/snapshots.js +109 -86
- package/dist/core/dist/utils/point.js +4 -0
- package/dist/core/dist/utils/time.js +42 -26
- package/dist/index.d.ts +67 -28
- package/dist/ui/InfoBar.vue.js +69 -69
- package/dist/ui/NumberFlow.vue.js +36 -27
- package/dist/ui/Tooltip.vue.js +128 -131
- package/dist/ui/YLabel.vue.js +47 -47
- package/package.json +2 -2
- package/src/BandSeries.vue +20 -5
- package/src/BarSeries.vue +20 -5
- package/src/CandlestickSeries.vue +5 -4
- package/src/ChartContainer.vue +15 -9
- package/src/HeatmapSeries.vue +5 -4
- package/src/LineSeries.vue +20 -5
- package/src/PieSeries.vue +6 -5
- package/src/composables.ts +64 -1
- package/src/ui/InfoBar.vue +11 -3
- package/src/ui/NumberFlow.vue +17 -3
- package/src/ui/Tooltip.vue +23 -12
- package/src/ui/YLabel.vue +28 -27
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { DEFAULT_HISTORY_REVEAL as
|
|
2
|
-
import { growIntro as
|
|
3
|
-
import { BaseMultiLayerSeries as
|
|
4
|
-
import { resolveBarPainter as
|
|
1
|
+
import { DEFAULT_HISTORY_REVEAL as D, DEFAULT_BAR_INTRO as C, DEFAULT_BAR_SMOOTH as O, DEFAULT_BAR_ENTRY as _ } from "../animation/config.js";
|
|
2
|
+
import { growIntro as N } from "./bar-intro.js";
|
|
3
|
+
import { BaseMultiLayerSeries as U } from "./base-multi-layer.js";
|
|
4
|
+
import { resolveBarPainter as G } from "./painters/resolve.js";
|
|
5
5
|
import { ScaleStack as z } from "./scale-stack.js";
|
|
6
|
-
import { fadeIntro as
|
|
6
|
+
import { fadeIntro as $ } from "./wave-intro.js";
|
|
7
7
|
const F = 2, J = {
|
|
8
8
|
// Single fallback resolver; the definition's `create` swaps in `theme.bar.color`.
|
|
9
9
|
colors: ["#26a69a"],
|
|
@@ -12,34 +12,34 @@ const F = 2, J = {
|
|
|
12
12
|
anchor: "center",
|
|
13
13
|
cornerRadius: F,
|
|
14
14
|
entryMs: _,
|
|
15
|
-
smoothMs:
|
|
16
|
-
introMs:
|
|
17
|
-
historyRevealMs:
|
|
15
|
+
smoothMs: O,
|
|
16
|
+
introMs: C,
|
|
17
|
+
historyRevealMs: D
|
|
18
18
|
};
|
|
19
|
-
function
|
|
19
|
+
function I(y) {
|
|
20
20
|
return {
|
|
21
21
|
...y,
|
|
22
22
|
entryMs: y.entryMs === !1 ? 0 : y.entryMs ?? _,
|
|
23
|
-
smoothMs: y.smoothMs === !1 ? 0 : y.smoothMs ??
|
|
24
|
-
introMs: y.introMs === !1 ? 0 : y.introMs ??
|
|
25
|
-
historyRevealMs: y.historyRevealMs === !1 ? 0 : y.historyRevealMs ??
|
|
23
|
+
smoothMs: y.smoothMs === !1 ? 0 : y.smoothMs ?? O,
|
|
24
|
+
introMs: y.introMs === !1 ? 0 : y.introMs ?? C,
|
|
25
|
+
historyRevealMs: y.historyRevealMs === !1 ? 0 : y.historyRevealMs ?? D
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
const Q =
|
|
28
|
+
const Q = N(), Z = $(), q = {
|
|
29
29
|
top: { tl: !0, tr: !0, br: !1, bl: !1 },
|
|
30
30
|
bottom: { tl: !1, tr: !1, br: !0, bl: !0 },
|
|
31
31
|
none: { tl: !1, tr: !1, br: !1, bl: !1 }
|
|
32
32
|
};
|
|
33
33
|
function K(y) {
|
|
34
34
|
const e = [], t = [];
|
|
35
|
-
let o = 0,
|
|
35
|
+
let o = 0, s = 0;
|
|
36
36
|
for (const i of y) {
|
|
37
|
-
const
|
|
38
|
-
e.push(
|
|
37
|
+
const h = i > 0 ? o : s;
|
|
38
|
+
e.push(h), t.push(h + i), i > 0 ? o += i : s += i;
|
|
39
39
|
}
|
|
40
40
|
return { base: e, end: t };
|
|
41
41
|
}
|
|
42
|
-
class tt extends
|
|
42
|
+
class tt extends U {
|
|
43
43
|
kind = "bar";
|
|
44
44
|
/** Resolved drawing context for the in-flight render pass. Set at the top of
|
|
45
45
|
* {@link render}, read by {@link drawAnimatedBar}. */
|
|
@@ -53,10 +53,14 @@ class tt extends N {
|
|
|
53
53
|
/** Per-frame history-reveal directives; `null` when no reveal is in flight. */
|
|
54
54
|
#t = null;
|
|
55
55
|
constructor(e, t) {
|
|
56
|
-
super(e), this.options =
|
|
56
|
+
super(e), this.options = I({ ...J, ...t });
|
|
57
57
|
}
|
|
58
58
|
updateOptions(e) {
|
|
59
|
-
this.options =
|
|
59
|
+
this.options = I({ ...this.options, ...e });
|
|
60
|
+
}
|
|
61
|
+
getValueRange(e, t, o) {
|
|
62
|
+
const s = super.getValueRange(e, t, o), i = o?.plottable?.(0) ?? !0;
|
|
63
|
+
return s === null || !i ? s : { min: Math.min(0, s.min), max: Math.max(0, s.max) };
|
|
60
64
|
}
|
|
61
65
|
isEntryEnabled() {
|
|
62
66
|
return (this.options.entryAnimation ?? "fade-grow") !== "none";
|
|
@@ -65,10 +69,10 @@ class tt extends N {
|
|
|
65
69
|
* Normalized x-position + eased wave progress for the intro's callbacks.
|
|
66
70
|
* `null` when no intro is in flight this frame.
|
|
67
71
|
*/
|
|
68
|
-
#
|
|
72
|
+
#s(e) {
|
|
69
73
|
const t = this.#i;
|
|
70
74
|
if (t === null) return null;
|
|
71
|
-
const o = t.to - t.from,
|
|
75
|
+
const o = t.to - t.from, s = o > 0 ? (e - t.from) / o : 0, i = Math.min(1, Math.max(0, s));
|
|
72
76
|
return { position: i, progress: this.introWave.progressAt(i) };
|
|
73
77
|
}
|
|
74
78
|
/**
|
|
@@ -77,10 +81,10 @@ class tt extends N {
|
|
|
77
81
|
* the deepest prepended point). `null` for bars outside the prepended
|
|
78
82
|
* span or when no reveal is in flight this frame.
|
|
79
83
|
*/
|
|
80
|
-
#
|
|
84
|
+
#a(e) {
|
|
81
85
|
const t = this.historyRange;
|
|
82
86
|
if (this.#t === null || t === null || e >= t.to) return null;
|
|
83
|
-
const o = t.to - t.from,
|
|
87
|
+
const o = t.to - t.from, s = o > 0 ? (t.to - e) / o : 0, i = Math.min(1, Math.max(0, s));
|
|
84
88
|
return { position: i, progress: this.historyWave.progressAt(i) };
|
|
85
89
|
}
|
|
86
90
|
/**
|
|
@@ -95,19 +99,44 @@ class tt extends N {
|
|
|
95
99
|
if (this.isProjectedTime(e.time)) return e.value;
|
|
96
100
|
const t = this.#t?.value;
|
|
97
101
|
if (t !== void 0) {
|
|
98
|
-
const i = this.#
|
|
102
|
+
const i = this.#a(e.time);
|
|
99
103
|
if (i !== null) return t({ ...e, ...i });
|
|
100
104
|
}
|
|
101
105
|
const o = this.#e?.value;
|
|
102
106
|
if (o === void 0) return e.value;
|
|
103
|
-
const
|
|
104
|
-
return
|
|
107
|
+
const s = this.#s(e.time);
|
|
108
|
+
return s === null ? e.value : o({ ...e, ...s });
|
|
105
109
|
}
|
|
106
110
|
applyTheme(e, t) {
|
|
107
|
-
const o = this.stores.length === 1,
|
|
111
|
+
const o = this.stores.length === 1, s = e.seriesColors[0] ?? "#26a69a", i = o ? [e.bar?.color ?? s] : e.seriesColors.slice(0, this.stores.length);
|
|
108
112
|
this.updateOptions({ colors: i });
|
|
109
113
|
}
|
|
110
114
|
/** True when `time` is at/after the configured `projectedFrom` forecast cut. */
|
|
115
|
+
/**
|
|
116
|
+
* The bar stack's reading of a percent column (see `renderStacked`): each
|
|
117
|
+
* layer's sample at `time` as drawn — smoothed, faded, growing in, intro applied — with
|
|
118
|
+
* positives scaled to 100% and negatives to -100% on their own; `null` when
|
|
119
|
+
* the column draws nothing.
|
|
120
|
+
*/
|
|
121
|
+
percentShares(e) {
|
|
122
|
+
const t = this.options.entryAnimation ?? "fade-grow", o = (t === "grow" || t === "fade-grow") && !this.isProjectedTime(e), s = /* @__PURE__ */ new Map();
|
|
123
|
+
let i = 0, h = 0;
|
|
124
|
+
for (let c = 0; c < this.stores.length; c++) {
|
|
125
|
+
const m = this.getLayerAlpha(c);
|
|
126
|
+
if (m <= 0) continue;
|
|
127
|
+
const l = this.stores[c].findNearest(e, 0);
|
|
128
|
+
if (l === null || !Number.isFinite(l.value)) continue;
|
|
129
|
+
const r = o ? this.entranceProgress(c, e) : 1, u = this.liveValue(c, e, l.value) * m * r, a = this.introValue({ layerIndex: c, time: e, value: u });
|
|
130
|
+
s.set(c, a), a > 0 && (i += a), a < 0 && (h += a);
|
|
131
|
+
}
|
|
132
|
+
if (i === 0 && h === 0) return null;
|
|
133
|
+
const d = /* @__PURE__ */ new Map();
|
|
134
|
+
for (const [c, m] of s) {
|
|
135
|
+
let l = 0;
|
|
136
|
+
m > 0 && (l = m / i * 100), m < 0 && (l = m / h * -100), d.set(c, l);
|
|
137
|
+
}
|
|
138
|
+
return d;
|
|
139
|
+
}
|
|
111
140
|
isProjectedTime(e) {
|
|
112
141
|
const t = this.options.projectedFrom;
|
|
113
142
|
return t !== void 0 && e >= t;
|
|
@@ -118,21 +147,21 @@ class tt extends N {
|
|
|
118
147
|
* each render path.
|
|
119
148
|
*/
|
|
120
149
|
applyBarTransform(e, t) {
|
|
121
|
-
const { baselineY: o, topY:
|
|
122
|
-
if (t >= 1 ||
|
|
123
|
-
return { topY:
|
|
124
|
-
let
|
|
125
|
-
if ((
|
|
126
|
-
const
|
|
127
|
-
|
|
150
|
+
const { baselineY: o, topY: s, barHeight: i, x: h, barWidth: d } = e, c = this.options.entryAnimation ?? "fade-grow";
|
|
151
|
+
if (t >= 1 || c === "none")
|
|
152
|
+
return { topY: s, barHeight: i, x: h, barWidth: d, alpha: 1 };
|
|
153
|
+
let m = s, l = i, r = h, u = 1;
|
|
154
|
+
if ((c === "fade" || c === "fade-grow") && (u = t), (c === "grow" || c === "fade-grow") && !e.growBaked) {
|
|
155
|
+
const a = i * t;
|
|
156
|
+
s < o ? m = o - a : m = o, l = Math.max(1, a);
|
|
128
157
|
}
|
|
129
|
-
return
|
|
158
|
+
return c === "slide" && (r = h + (1 - t) * d, u = t), { topY: m, barHeight: l, x: r, barWidth: d, alpha: u };
|
|
130
159
|
}
|
|
131
160
|
render(e) {
|
|
132
161
|
this.tickAnimations(performance.now());
|
|
133
|
-
const { scope: t, timeScale: o, yScale:
|
|
162
|
+
const { scope: t, timeScale: o, yScale: s } = e;
|
|
134
163
|
this.#o = {
|
|
135
|
-
painter:
|
|
164
|
+
painter: G(this.options.barPainter),
|
|
136
165
|
env: {
|
|
137
166
|
ctx: t.context,
|
|
138
167
|
theme: e.theme,
|
|
@@ -142,46 +171,46 @@ class tt extends N {
|
|
|
142
171
|
radius: (this.options.cornerRadius ?? F) * t.horizontalPixelRatio
|
|
143
172
|
};
|
|
144
173
|
const i = {
|
|
145
|
-
baseline:
|
|
146
|
-
lerpValue: (
|
|
174
|
+
baseline: s.baselineValue(),
|
|
175
|
+
lerpValue: (l, r, u) => s.lerpValue(l, r, u)
|
|
147
176
|
};
|
|
148
177
|
if (this.#e = null, this.#i = null, this.introWave.active) {
|
|
149
|
-
const
|
|
150
|
-
this.#i =
|
|
178
|
+
const l = this.options.introAnimation ?? Q, r = o.getRange();
|
|
179
|
+
this.#i = r, this.#e = l({
|
|
151
180
|
progress: this.introWave.linear(),
|
|
152
181
|
// Plot-area extent, not the canvas bitmap — the canvas also carries
|
|
153
182
|
// the axis strips, so a width-based front (wipeIntro) would overshoot
|
|
154
183
|
// the data area.
|
|
155
184
|
width: o.getMediaWidth() * t.horizontalPixelRatio,
|
|
156
|
-
height:
|
|
157
|
-
range:
|
|
158
|
-
timeToX: (
|
|
185
|
+
height: s.getMediaHeight() * t.verticalPixelRatio,
|
|
186
|
+
range: r,
|
|
187
|
+
timeToX: (u) => o.timeToBitmapX(u),
|
|
159
188
|
...i
|
|
160
189
|
});
|
|
161
190
|
}
|
|
162
191
|
this.#t = null;
|
|
163
|
-
const
|
|
164
|
-
if (this.historyWave.active &&
|
|
165
|
-
const
|
|
166
|
-
|
|
192
|
+
const h = this.historyRange;
|
|
193
|
+
if (this.historyWave.active && h !== null) {
|
|
194
|
+
const l = this.options.historyReveal ?? Z;
|
|
195
|
+
l !== "none" && (this.#t = l({
|
|
167
196
|
progress: this.historyWave.linear(),
|
|
168
|
-
width: Math.abs(o.timeToBitmapX(
|
|
169
|
-
height:
|
|
170
|
-
range:
|
|
171
|
-
timeToX: (
|
|
197
|
+
width: Math.abs(o.timeToBitmapX(h.to) - o.timeToBitmapX(h.from)),
|
|
198
|
+
height: s.getMediaHeight() * t.verticalPixelRatio,
|
|
199
|
+
range: h,
|
|
200
|
+
timeToX: (r) => o.timeToBitmapX(r),
|
|
172
201
|
...i
|
|
173
202
|
}));
|
|
174
203
|
}
|
|
175
|
-
const
|
|
176
|
-
if (
|
|
177
|
-
const
|
|
178
|
-
t.context.save(), t.context.beginPath(), t.context.rect(
|
|
204
|
+
const d = this.#e?.clip;
|
|
205
|
+
if (d !== void 0) {
|
|
206
|
+
const l = d.fromX ?? 0, r = d.toX ?? t.bitmapSize.width;
|
|
207
|
+
t.context.save(), t.context.beginPath(), t.context.rect(l, 0, Math.max(0, r - l), t.bitmapSize.height), t.context.clip();
|
|
179
208
|
}
|
|
180
|
-
const
|
|
181
|
-
let
|
|
182
|
-
if (
|
|
183
|
-
const
|
|
184
|
-
t.context.save(), t.context.beginPath(), t.context.rect(
|
|
209
|
+
const c = this.#t?.clip;
|
|
210
|
+
let m = !1;
|
|
211
|
+
if (c !== void 0 && h !== null) {
|
|
212
|
+
const l = o.timeToBitmapX(h.to), r = Math.abs(l - o.timeToBitmapX(h.from)), u = o.barWidthBitmap(e.dataInterval), a = c.fromX ?? 0, A = c.toX ?? r;
|
|
213
|
+
t.context.save(), t.context.beginPath(), t.context.rect(l - A - u, 0, Math.max(0, A - a + u), t.bitmapSize.height), t.context.rect(l, 0, Math.max(0, t.bitmapSize.width - l), t.bitmapSize.height), t.context.clip(), m = !0;
|
|
185
214
|
}
|
|
186
215
|
switch (this.options.stacking) {
|
|
187
216
|
case "normal":
|
|
@@ -194,7 +223,7 @@ class tt extends N {
|
|
|
194
223
|
this.renderOff(e);
|
|
195
224
|
break;
|
|
196
225
|
}
|
|
197
|
-
|
|
226
|
+
m && t.context.restore(), d !== void 0 && t.context.restore();
|
|
198
227
|
}
|
|
199
228
|
/**
|
|
200
229
|
* Bar body width in bitmap px. On a category axis a bar fills its band;
|
|
@@ -203,53 +232,53 @@ class tt extends N {
|
|
|
203
232
|
* zooms must keep wide bars. See the matching comment in candlestick.ts.
|
|
204
233
|
*/
|
|
205
234
|
#r(e) {
|
|
206
|
-
const { scope: t, timeScale: o, dataInterval:
|
|
235
|
+
const { scope: t, timeScale: o, dataInterval: s } = e;
|
|
207
236
|
if (o.getType() === "category") return o.bandWidthBitmap();
|
|
208
237
|
const i = o.getRange();
|
|
209
|
-
let
|
|
210
|
-
for (const
|
|
211
|
-
if (!
|
|
212
|
-
const
|
|
213
|
-
if (
|
|
238
|
+
let h = 0;
|
|
239
|
+
for (const l of this.stores) {
|
|
240
|
+
if (!l.isVisible()) continue;
|
|
241
|
+
const r = l.getVisibleData(i.from, i.to).length;
|
|
242
|
+
if (r > h && (h = r), h > 2) break;
|
|
214
243
|
}
|
|
215
|
-
const
|
|
216
|
-
return Math.max(1, Math.round(
|
|
244
|
+
const d = o.barWidthBitmap(s), c = Math.round(30 * t.horizontalPixelRatio), m = h <= 2 ? Math.min(c, d) : d;
|
|
245
|
+
return Math.max(1, Math.round(m * this.options.barWidthRatio));
|
|
217
246
|
}
|
|
218
247
|
/** Stacking off — each layer drawn independently from zero, overlapping */
|
|
219
248
|
renderOff(e) {
|
|
220
|
-
const { scope: t, timeScale: o, yScale:
|
|
249
|
+
const { scope: t, timeScale: o, yScale: s } = e, { context: i } = t, h = o.getRange(), d = this.#r(e), c = Math.floor(d / 2), m = this.options.anchor === "right" ? d : c, l = s.getRange().min < 0, r = l ? s.valueToBitmapY(0) : t.bitmapSize.height;
|
|
221
250
|
if (this.stores.length === 1) {
|
|
222
251
|
if (!this.stores[0].isVisible()) return;
|
|
223
|
-
const
|
|
224
|
-
for (const
|
|
225
|
-
if (!
|
|
226
|
-
const A = this.effectiveValue(e, 0,
|
|
227
|
-
if (
|
|
228
|
-
const
|
|
252
|
+
const u = this.stores[0].getVisibleData(h.from, h.to);
|
|
253
|
+
for (const a of u) {
|
|
254
|
+
if (!s.isPlottable(a.value)) continue;
|
|
255
|
+
const A = this.effectiveValue(e, 0, a.time, a.value), g = this.introValue({ layerIndex: 0, time: a.time, value: A }), b = this.entranceProgress(0, a.time), v = this.isProjectedTime(a.time), w = o.timeToBitmapX(a.time), M = this.resolveLayerColor(0, A);
|
|
256
|
+
if (g >= 0) {
|
|
257
|
+
const n = s.valueToBitmapY(g), f = Math.max(1, r - n);
|
|
229
258
|
this.drawAnimatedBar({
|
|
230
259
|
context: i,
|
|
231
|
-
time:
|
|
260
|
+
time: a.time,
|
|
232
261
|
progress: b,
|
|
233
|
-
baselineY:
|
|
234
|
-
topY:
|
|
262
|
+
baselineY: r,
|
|
263
|
+
topY: n,
|
|
235
264
|
barHeight: f,
|
|
236
|
-
x:
|
|
237
|
-
barWidth:
|
|
265
|
+
x: w - m,
|
|
266
|
+
barWidth: d,
|
|
238
267
|
color: M,
|
|
239
268
|
roundEdge: "top",
|
|
240
269
|
isProjected: v
|
|
241
270
|
});
|
|
242
271
|
} else {
|
|
243
|
-
const
|
|
272
|
+
const n = s.valueToBitmapY(g), f = Math.max(1, n - r);
|
|
244
273
|
this.drawAnimatedBar({
|
|
245
274
|
context: i,
|
|
246
|
-
time:
|
|
275
|
+
time: a.time,
|
|
247
276
|
progress: b,
|
|
248
|
-
baselineY:
|
|
249
|
-
topY:
|
|
277
|
+
baselineY: r,
|
|
278
|
+
topY: r,
|
|
250
279
|
barHeight: f,
|
|
251
|
-
x:
|
|
252
|
-
barWidth:
|
|
280
|
+
x: w - m,
|
|
281
|
+
barWidth: d,
|
|
253
282
|
color: M,
|
|
254
283
|
roundEdge: "bottom",
|
|
255
284
|
isProjected: v
|
|
@@ -257,19 +286,19 @@ class tt extends N {
|
|
|
257
286
|
}
|
|
258
287
|
}
|
|
259
288
|
} else {
|
|
260
|
-
const
|
|
261
|
-
(
|
|
262
|
-
),
|
|
263
|
-
for (let
|
|
264
|
-
const b = this.getLayerAlpha(
|
|
265
|
-
for (const v of g
|
|
266
|
-
if (!
|
|
267
|
-
let
|
|
268
|
-
|
|
269
|
-
const M = this.effectiveValue(e,
|
|
270
|
-
|
|
271
|
-
layer:
|
|
272
|
-
value: this.introValue({ layerIndex:
|
|
289
|
+
const u = this.stores.map(
|
|
290
|
+
(g, b) => this.getLayerAlpha(b) > 0 ? g.getVisibleData(h.from, h.to) : []
|
|
291
|
+
), a = /* @__PURE__ */ new Map(), A = s.baselineValue();
|
|
292
|
+
for (let g = 0; g < u.length; g++) {
|
|
293
|
+
const b = this.getLayerAlpha(g);
|
|
294
|
+
for (const v of u[g]) {
|
|
295
|
+
if (!s.isPlottable(v.value)) continue;
|
|
296
|
+
let w = a.get(v.time);
|
|
297
|
+
w || (w = [], a.set(v.time, w));
|
|
298
|
+
const M = this.effectiveValue(e, g, v.time, v.value), n = b === 1 ? M : s.lerpValue(A, M, b);
|
|
299
|
+
w.push({
|
|
300
|
+
layer: g,
|
|
301
|
+
value: this.introValue({ layerIndex: g, time: v.time, value: n }),
|
|
273
302
|
// Color resolves from the settled data value — same contract as
|
|
274
303
|
// the single-layer path — so a threshold value-fn doesn't flicker
|
|
275
304
|
// hues while the intro sweeps the drawn value from 0 to final.
|
|
@@ -277,135 +306,135 @@ class tt extends N {
|
|
|
277
306
|
});
|
|
278
307
|
}
|
|
279
308
|
}
|
|
280
|
-
for (const [
|
|
309
|
+
for (const [g, b] of a) {
|
|
281
310
|
b.sort(
|
|
282
|
-
(M,
|
|
311
|
+
(M, n) => Math.abs(n.value) - Math.abs(M.value)
|
|
283
312
|
);
|
|
284
|
-
const v = o.timeToBitmapX(
|
|
313
|
+
const v = o.timeToBitmapX(g), w = this.isProjectedTime(g);
|
|
285
314
|
for (let M = 0; M < b.length; M++) {
|
|
286
|
-
const { layer:
|
|
315
|
+
const { layer: n, value: f, colorValue: p } = b[M], B = this.resolveLayerColor(n, p), x = this.entranceProgress(n, g);
|
|
287
316
|
if (f >= 0) {
|
|
288
|
-
const R =
|
|
317
|
+
const R = s.valueToBitmapY(f), T = Math.max(1, r - R);
|
|
289
318
|
this.drawAnimatedBar({
|
|
290
319
|
context: i,
|
|
291
|
-
time:
|
|
320
|
+
time: g,
|
|
292
321
|
progress: x,
|
|
293
|
-
baselineY:
|
|
322
|
+
baselineY: r,
|
|
294
323
|
topY: R,
|
|
295
324
|
barHeight: T,
|
|
296
|
-
x: v -
|
|
297
|
-
barWidth:
|
|
298
|
-
color:
|
|
325
|
+
x: v - m,
|
|
326
|
+
barWidth: d,
|
|
327
|
+
color: B,
|
|
299
328
|
roundEdge: "top",
|
|
300
|
-
isProjected:
|
|
329
|
+
isProjected: w
|
|
301
330
|
});
|
|
302
331
|
} else {
|
|
303
|
-
const R =
|
|
332
|
+
const R = s.valueToBitmapY(f), T = Math.max(1, R - r);
|
|
304
333
|
this.drawAnimatedBar({
|
|
305
334
|
context: i,
|
|
306
|
-
time:
|
|
335
|
+
time: g,
|
|
307
336
|
progress: x,
|
|
308
|
-
baselineY:
|
|
309
|
-
topY:
|
|
337
|
+
baselineY: r,
|
|
338
|
+
topY: r,
|
|
310
339
|
barHeight: T,
|
|
311
|
-
x: v -
|
|
312
|
-
barWidth:
|
|
313
|
-
color:
|
|
340
|
+
x: v - m,
|
|
341
|
+
barWidth: d,
|
|
342
|
+
color: B,
|
|
314
343
|
roundEdge: "bottom",
|
|
315
|
-
isProjected:
|
|
344
|
+
isProjected: w
|
|
316
345
|
});
|
|
317
346
|
}
|
|
318
347
|
}
|
|
319
348
|
}
|
|
320
349
|
}
|
|
321
|
-
if (
|
|
350
|
+
if (l) {
|
|
322
351
|
i.strokeStyle = e.theme.grid.color, i.lineWidth = 1;
|
|
323
|
-
const
|
|
324
|
-
i.beginPath(), i.moveTo(0,
|
|
352
|
+
const u = Math.round(r) + 0.5;
|
|
353
|
+
i.beginPath(), i.moveTo(0, u), i.lineTo(t.bitmapSize.width, u), i.stroke();
|
|
325
354
|
}
|
|
326
355
|
}
|
|
327
356
|
/** Stacked (normal or percent) rendering */
|
|
328
357
|
renderStacked(e, t) {
|
|
329
|
-
const { scope: o, timeScale:
|
|
330
|
-
(
|
|
358
|
+
const { scope: o, timeScale: s, yScale: i } = e, { context: h } = o, d = s.getRange(), c = this.#r(e), m = Math.floor(c / 2), l = this.options.anchor === "right" ? c : m, r = this.stores.map(
|
|
359
|
+
(n, f) => this.getLayerAlpha(f) > 0 ? n.getVisibleData(d.from, d.to) : []
|
|
331
360
|
);
|
|
332
|
-
if (
|
|
333
|
-
const
|
|
334
|
-
for (let
|
|
335
|
-
const f = this.getLayerAlpha(
|
|
336
|
-
for (const
|
|
337
|
-
let
|
|
338
|
-
|
|
339
|
-
const x = i.isPlottable(
|
|
361
|
+
if (r.every((n) => n.length === 0)) return;
|
|
362
|
+
const u = this.options.entryAnimation ?? "fade-grow", a = u === "grow" || u === "fade-grow", A = i.getTransform() !== null && !t, g = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map();
|
|
363
|
+
for (let n = 0; n < r.length; n++) {
|
|
364
|
+
const f = this.getLayerAlpha(n);
|
|
365
|
+
for (const p of r[n]) {
|
|
366
|
+
let B = b.get(p.time);
|
|
367
|
+
B || (B = new Array(r.length).fill(0), b.set(p.time, B));
|
|
368
|
+
const x = i.isPlottable(p.value) ? p.value : 0, R = this.effectiveValue(e, n, p.time, x);
|
|
340
369
|
let T = R * f, V = f;
|
|
341
|
-
if (
|
|
342
|
-
const P = this.entranceProgress(
|
|
370
|
+
if (a && !this.isProjectedTime(p.time)) {
|
|
371
|
+
const P = this.entranceProgress(n, p.time);
|
|
343
372
|
T *= P, V *= P;
|
|
344
373
|
}
|
|
345
374
|
if (A) {
|
|
346
|
-
|
|
347
|
-
let P =
|
|
348
|
-
P || (P = { settled: new Array(
|
|
375
|
+
B[n] = T;
|
|
376
|
+
let P = g.get(p.time);
|
|
377
|
+
P || (P = { settled: new Array(r.length).fill(0), weights: new Array(r.length).fill(0) }, g.set(p.time, P)), P.settled[n] = R, P.weights[n] = V;
|
|
349
378
|
continue;
|
|
350
379
|
}
|
|
351
|
-
|
|
380
|
+
B[n] = this.introValue({ layerIndex: n, time: p.time, value: T });
|
|
352
381
|
}
|
|
353
382
|
}
|
|
354
383
|
const v = /* @__PURE__ */ new Map();
|
|
355
384
|
if (!t)
|
|
356
|
-
for (const [
|
|
357
|
-
const
|
|
358
|
-
v.set(
|
|
385
|
+
for (const [n, f] of b) {
|
|
386
|
+
const p = g.get(n);
|
|
387
|
+
v.set(n, p === void 0 ? K(f) : this.scaleEdges({ time: n, share: p, yScale: i }));
|
|
359
388
|
}
|
|
360
|
-
const
|
|
361
|
-
for (const [
|
|
362
|
-
let
|
|
389
|
+
const w = /* @__PURE__ */ new Map(), M = /* @__PURE__ */ new Map();
|
|
390
|
+
for (const [n, f] of b) {
|
|
391
|
+
let p = -1, B = -1;
|
|
363
392
|
for (let x = 0; x < f.length; x++)
|
|
364
|
-
f[x] > 0 && (
|
|
365
|
-
|
|
393
|
+
f[x] > 0 && (p = x), f[x] < 0 && (B = x);
|
|
394
|
+
p >= 0 && w.set(n, p), B >= 0 && M.set(n, B);
|
|
366
395
|
}
|
|
367
|
-
for (let
|
|
368
|
-
const f = this.resolveLayerColor(
|
|
369
|
-
for (const [
|
|
370
|
-
const x =
|
|
396
|
+
for (let n = 0; n < r.length; n++) {
|
|
397
|
+
const f = this.resolveLayerColor(n, this.lastFinitePoint(n)?.value ?? 0);
|
|
398
|
+
for (const [p, B] of b) {
|
|
399
|
+
const x = B[n];
|
|
371
400
|
if (x === 0) continue;
|
|
372
|
-
const R =
|
|
401
|
+
const R = s.timeToBitmapX(p), T = this.entranceProgress(n, p), V = this.isProjectedTime(p), P = x > 0 ? w.get(p) === n ? "top" : "none" : M.get(p) === n ? "bottom" : "none";
|
|
373
402
|
if (t) {
|
|
374
|
-
let
|
|
375
|
-
for (let
|
|
376
|
-
const S = Y
|
|
377
|
-
S > 0 ?
|
|
403
|
+
let H = 0, E = 0;
|
|
404
|
+
for (let Y = 0; Y < n; Y++) {
|
|
405
|
+
const S = B[Y];
|
|
406
|
+
S > 0 ? H += S : E += S;
|
|
378
407
|
}
|
|
379
|
-
let
|
|
380
|
-
for (const
|
|
381
|
-
|
|
382
|
-
if (x > 0 &&
|
|
383
|
-
const
|
|
408
|
+
let k = 0, W = 0;
|
|
409
|
+
for (const Y of B)
|
|
410
|
+
Y > 0 ? k += Y : W += Y;
|
|
411
|
+
if (x > 0 && k > 0) {
|
|
412
|
+
const Y = H / k * 100, S = (H + x) / k * 100, j = i.valueToBitmapY(S), X = i.valueToBitmapY(Y), L = Math.max(1, X - j);
|
|
384
413
|
this.drawAnimatedBar({
|
|
385
|
-
context:
|
|
386
|
-
time:
|
|
414
|
+
context: h,
|
|
415
|
+
time: p,
|
|
387
416
|
progress: T,
|
|
388
417
|
baselineY: X,
|
|
389
418
|
topY: j,
|
|
390
419
|
barHeight: L,
|
|
391
|
-
x: R -
|
|
392
|
-
barWidth:
|
|
420
|
+
x: R - l,
|
|
421
|
+
barWidth: c,
|
|
393
422
|
color: f,
|
|
394
423
|
roundEdge: P,
|
|
395
424
|
isProjected: V,
|
|
396
425
|
growBaked: !0
|
|
397
426
|
});
|
|
398
427
|
} else if (x < 0 && W < 0) {
|
|
399
|
-
const
|
|
428
|
+
const Y = E / W * -100, S = (E + x) / W * -100, j = i.valueToBitmapY(Y), X = i.valueToBitmapY(S), L = Math.max(1, X - j);
|
|
400
429
|
this.drawAnimatedBar({
|
|
401
|
-
context:
|
|
402
|
-
time:
|
|
430
|
+
context: h,
|
|
431
|
+
time: p,
|
|
403
432
|
progress: T,
|
|
404
433
|
baselineY: j,
|
|
405
434
|
topY: j,
|
|
406
435
|
barHeight: L,
|
|
407
|
-
x: R -
|
|
408
|
-
barWidth:
|
|
436
|
+
x: R - l,
|
|
437
|
+
barWidth: c,
|
|
409
438
|
color: f,
|
|
410
439
|
roundEdge: P,
|
|
411
440
|
isProjected: V,
|
|
@@ -413,36 +442,36 @@ class tt extends N {
|
|
|
413
442
|
});
|
|
414
443
|
}
|
|
415
444
|
} else {
|
|
416
|
-
const
|
|
417
|
-
if (
|
|
418
|
-
const
|
|
445
|
+
const H = v.get(p);
|
|
446
|
+
if (H === void 0) continue;
|
|
447
|
+
const E = H.base[n], k = H.end[n];
|
|
419
448
|
if (x > 0) {
|
|
420
|
-
const W = i.valueToBitmapY(
|
|
449
|
+
const W = i.valueToBitmapY(k), Y = i.valueToBitmapY(E), S = Math.max(1, Y - W);
|
|
421
450
|
this.drawAnimatedBar({
|
|
422
|
-
context:
|
|
423
|
-
time:
|
|
451
|
+
context: h,
|
|
452
|
+
time: p,
|
|
424
453
|
progress: T,
|
|
425
|
-
baselineY:
|
|
454
|
+
baselineY: Y,
|
|
426
455
|
topY: W,
|
|
427
456
|
barHeight: S,
|
|
428
|
-
x: R -
|
|
429
|
-
barWidth:
|
|
457
|
+
x: R - l,
|
|
458
|
+
barWidth: c,
|
|
430
459
|
color: f,
|
|
431
460
|
roundEdge: P,
|
|
432
461
|
isProjected: V,
|
|
433
462
|
growBaked: !0
|
|
434
463
|
});
|
|
435
464
|
} else {
|
|
436
|
-
const W = i.valueToBitmapY(
|
|
465
|
+
const W = i.valueToBitmapY(E), Y = i.valueToBitmapY(k), S = Math.max(1, Y - W);
|
|
437
466
|
this.drawAnimatedBar({
|
|
438
|
-
context:
|
|
439
|
-
time:
|
|
467
|
+
context: h,
|
|
468
|
+
time: p,
|
|
440
469
|
progress: T,
|
|
441
470
|
baselineY: W,
|
|
442
471
|
topY: W,
|
|
443
472
|
barHeight: S,
|
|
444
|
-
x: R -
|
|
445
|
-
barWidth:
|
|
473
|
+
x: R - l,
|
|
474
|
+
barWidth: c,
|
|
446
475
|
color: f,
|
|
447
476
|
roundEdge: P,
|
|
448
477
|
isProjected: V,
|
|
@@ -459,12 +488,12 @@ class tt extends N {
|
|
|
459
488
|
* so the column grows from the floor as one unit at an even pixel speed.
|
|
460
489
|
*/
|
|
461
490
|
scaleEdges(e) {
|
|
462
|
-
const { time: t, share: o, yScale:
|
|
463
|
-
for (let
|
|
464
|
-
const
|
|
465
|
-
|
|
491
|
+
const { time: t, share: o, yScale: s } = e, i = { positive: new z(s), negative: new z(s) }, h = { positive: i.positive.edge, negative: i.negative.edge }, d = [], c = [];
|
|
492
|
+
for (let m = 0; m < o.settled.length; m++) {
|
|
493
|
+
const l = o.settled[m], r = l < 0 ? "negative" : "positive", u = i[r].push(l, o.weights[m]), a = this.introValue({ layerIndex: m, time: t, value: u });
|
|
494
|
+
d.push(h[r]), c.push(a), h[r] = a;
|
|
466
495
|
}
|
|
467
|
-
return { base:
|
|
496
|
+
return { base: d, end: c };
|
|
468
497
|
}
|
|
469
498
|
/**
|
|
470
499
|
* Paint one bar through the resolved painter, applying any entrance transform
|
|
@@ -475,41 +504,41 @@ class tt extends N {
|
|
|
475
504
|
drawAnimatedBar(e) {
|
|
476
505
|
const t = this.#o;
|
|
477
506
|
if (t === null) return;
|
|
478
|
-
const { context: o, baselineY:
|
|
479
|
-
let
|
|
507
|
+
const { context: o, baselineY: s, topY: i, barHeight: h, x: d, barWidth: c, color: m, roundEdge: l } = e, r = e.isProjected ? 1 : e.progress, u = this.options.entryAnimation ?? "fade-grow";
|
|
508
|
+
let a = r >= 1 || u === "none" ? { x: d, topY: i, barWidth: c, barHeight: h, alpha: 1 } : this.applyBarTransform(e, r);
|
|
480
509
|
if (!e.isProjected) {
|
|
481
|
-
const
|
|
482
|
-
if (v !== void 0 &&
|
|
510
|
+
const g = this.#t?.element, b = g !== void 0 ? this.#a(e.time) : null, v = b !== null ? g : this.#e?.element, w = b ?? (v !== void 0 ? this.#s(e.time) : null);
|
|
511
|
+
if (v !== void 0 && w !== null) {
|
|
483
512
|
const M = v({
|
|
484
|
-
...
|
|
513
|
+
...w,
|
|
485
514
|
time: e.time,
|
|
486
|
-
x:
|
|
487
|
-
topY:
|
|
488
|
-
barHeight:
|
|
489
|
-
baselineY:
|
|
490
|
-
barWidth:
|
|
515
|
+
x: a.x,
|
|
516
|
+
topY: a.topY,
|
|
517
|
+
barHeight: a.barHeight,
|
|
518
|
+
baselineY: s,
|
|
519
|
+
barWidth: a.barWidth
|
|
491
520
|
});
|
|
492
|
-
|
|
493
|
-
...
|
|
494
|
-
x:
|
|
495
|
-
topY:
|
|
496
|
-
alpha:
|
|
521
|
+
a = {
|
|
522
|
+
...a,
|
|
523
|
+
x: a.x + (M.offsetX ?? 0),
|
|
524
|
+
topY: a.topY + (M.offsetY ?? 0),
|
|
525
|
+
alpha: a.alpha * (M.alpha ?? 1)
|
|
497
526
|
};
|
|
498
527
|
}
|
|
499
528
|
}
|
|
500
529
|
const A = {
|
|
501
|
-
geom: { x:
|
|
502
|
-
color:
|
|
503
|
-
corners: q[
|
|
530
|
+
geom: { x: a.x, y: a.topY, width: a.barWidth, height: a.barHeight, baselineY: s },
|
|
531
|
+
color: m,
|
|
532
|
+
corners: q[l],
|
|
504
533
|
// Clamp to this bar's geometry so `radius` honors its pre-clamped contract
|
|
505
534
|
// for custom painters; `fillRoundedRect` re-clamps to the same bound, so
|
|
506
535
|
// the built-in output is unchanged.
|
|
507
|
-
radius: Math.min(t.radius,
|
|
508
|
-
progress:
|
|
536
|
+
radius: Math.min(t.radius, a.barWidth / 2, a.barHeight / 2),
|
|
537
|
+
progress: r,
|
|
509
538
|
isProjected: e.isProjected
|
|
510
539
|
};
|
|
511
|
-
if (
|
|
512
|
-
o.save(), o.globalAlpha =
|
|
540
|
+
if (a.alpha < 1) {
|
|
541
|
+
o.save(), o.globalAlpha = a.alpha, t.painter(t.env, A), o.restore();
|
|
513
542
|
return;
|
|
514
543
|
}
|
|
515
544
|
t.painter(t.env, A);
|