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