@wick-charts/vue 0.6.2 → 0.6.4
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 -2
- package/dist/BandSeries.vue.js +50 -0
- package/dist/BandSeries.vue2.js +4 -0
- package/dist/ChartContainer.vue.js +45 -39
- package/dist/composables.js +39 -26
- package/dist/core/dist/animation/config.js +92 -75
- package/dist/core/dist/axis/dom-labels.js +56 -43
- package/dist/core/dist/chart/badge-animator.js +30 -22
- package/dist/core/dist/chart/edge-indicators.js +22 -21
- package/dist/core/dist/chart/last-value.js +33 -26
- package/dist/core/dist/chart/options.js +5 -5
- package/dist/core/dist/chart/scale-guards.js +26 -0
- package/dist/core/dist/chart/y-target.js +46 -19
- package/dist/core/dist/chart.js +670 -518
- package/dist/core/dist/components/crosshair.js +8 -8
- package/dist/core/dist/components/grid.js +26 -17
- package/dist/core/dist/components/marker.js +28 -28
- package/dist/core/dist/components/reference-line.js +16 -16
- package/dist/core/dist/data/decimation.js +58 -39
- package/dist/core/dist/interactions/handler.js +3 -2
- package/dist/core/dist/interactions/zoom.js +6 -5
- package/dist/core/dist/navigator/controller.js +47 -44
- package/dist/core/dist/perf/perf-hud.js +3 -3
- package/dist/core/dist/scales/log-scale.js +76 -0
- package/dist/core/dist/scales/y-scale.js +134 -35
- package/dist/core/dist/series/band.js +670 -0
- package/dist/core/dist/series/bar-intro.js +11 -11
- package/dist/core/dist/series/bar.js +301 -251
- package/dist/core/dist/series/base-multi-layer.js +100 -76
- package/dist/core/dist/series/candlestick.js +238 -235
- package/dist/core/dist/series/heatmap.js +5 -5
- package/dist/core/dist/series/line-intro.js +50 -40
- package/dist/core/dist/series/line.js +561 -483
- package/dist/core/dist/series/painters/builtins.js +4 -4
- package/dist/core/dist/series/painters/canvas-path.js +64 -52
- package/dist/core/dist/series/register-builtins.js +9 -8
- package/dist/core/dist/series/scale-stack.js +25 -0
- package/dist/core/dist/snapshots.js +36 -35
- package/dist/core/dist/tooltip-position.js +5 -5
- package/dist/core/dist/utils/point.js +10 -0
- package/dist/index.d.ts +501 -128
- package/dist/index.js +195 -189
- package/dist/ui/Crosshair.vue.js +14 -14
- package/dist/ui/HeatmapTooltip.vue.js +6 -6
- package/dist/ui/InfoBar.vue.js +100 -81
- package/dist/ui/PieTooltip.vue.js +4 -4
- package/dist/ui/TimeAxis.vue.js +23 -22
- package/dist/ui/Tooltip.vue.js +140 -111
- package/dist/ui/YAxis.vue.js +25 -24
- package/dist/ui/YLabel.vue.js +63 -70
- package/package.json +2 -2
- package/src/BandSeries.vue +87 -0
- package/src/ChartContainer.vue +20 -8
- package/src/composables.ts +35 -1
- package/src/index.ts +13 -0
- package/src/ui/Crosshair.vue +2 -2
- package/src/ui/InfoBar.vue +20 -1
- package/src/ui/TimeAxis.vue +7 -4
- package/src/ui/Tooltip.vue +40 -3
- package/src/ui/YAxis.vue +5 -3
- package/src/ui/YLabel.vue +5 -16
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { Animator as
|
|
2
|
-
import { DEFAULT_HISTORY_REVEAL as
|
|
3
|
-
import { easeOutCubic as
|
|
1
|
+
import { Animator as nt } from "../animation/animator.js";
|
|
2
|
+
import { DEFAULT_HISTORY_REVEAL as it, DEFAULT_CANDLESTICK_INTRO as et, DEFAULT_CANDLESTICK_SMOOTH as ot, DEFAULT_CANDLESTICK_ENTRY as st } from "../animation/config.js";
|
|
3
|
+
import { easeOutCubic as at } from "../animation/easing.js";
|
|
4
4
|
import { IntroWave as U } from "../animation/intro-wave.js";
|
|
5
|
-
import { ScalarSpring as
|
|
6
|
-
import { decimateOHLCData as
|
|
7
|
-
import { TimeSeriesStore as
|
|
5
|
+
import { ScalarSpring as $ } from "../animation/scalar-spring.js";
|
|
6
|
+
import { decimateOHLCData as rt } from "../data/decimation.js";
|
|
7
|
+
import { TimeSeriesStore as lt } from "../data/store.js";
|
|
8
8
|
import { resolveCandlestickBodyColor as I } from "../theme/resolve.js";
|
|
9
9
|
import { hexToRgba as K, mixColors as G } from "../utils/color.js";
|
|
10
|
-
import { clamp as
|
|
10
|
+
import { clamp as F, lerp as z } from "../utils/math.js";
|
|
11
11
|
import { isPoisonedNumber as N, reportPoisonedData as ht } from "../utils/poisoned-data-reporter.js";
|
|
12
12
|
import { normalizeOHLCArray as J, normalizeTime as Q } from "../utils/time.js";
|
|
13
|
-
import { candleUnfoldIntro as
|
|
13
|
+
import { candleUnfoldIntro as ct } from "./candlestick-intro.js";
|
|
14
14
|
import { fillRoundedRect as Z } from "./painters/canvas-path.js";
|
|
15
15
|
import { resolveCandlePainter as mt } from "./painters/resolve.js";
|
|
16
|
-
import { fadeIntro as
|
|
17
|
-
const
|
|
18
|
-
class
|
|
16
|
+
import { fadeIntro as pt } from "./wave-intro.js";
|
|
17
|
+
const ut = 0.15, dt = 5e-3;
|
|
18
|
+
class ft {
|
|
19
19
|
#t;
|
|
20
20
|
#i;
|
|
21
21
|
#s;
|
|
@@ -25,16 +25,16 @@ class dt {
|
|
|
25
25
|
// Sticky once any seen candle carries volume — mirrors the old lerp, which
|
|
26
26
|
// only emitted `volume` when a side had it, so a volume-less candle stays
|
|
27
27
|
// volume-less and the histogram keeps skipping it.
|
|
28
|
-
#
|
|
28
|
+
#l;
|
|
29
29
|
constructor(t) {
|
|
30
|
-
this.#t = new
|
|
30
|
+
this.#t = new $(t.open), this.#i = new $(t.high), this.#s = new $(t.low), this.#r = new $(t.close), this.#e = new $(t.volume ?? 0), this.#n = t.time, this.#l = t.volume !== void 0;
|
|
31
31
|
}
|
|
32
32
|
retarget(t, i = {}) {
|
|
33
|
-
this.#n = t.time, t.volume !== void 0 && (this.#
|
|
33
|
+
this.#n = t.time, t.volume !== void 0 && (this.#l = !0), this.#t.retarget(t.open, i), this.#i.retarget(t.high, i), this.#s.retarget(t.low, i), this.#r.retarget(t.close, i), this.#e.retarget(t.volume ?? 0, i);
|
|
34
34
|
}
|
|
35
35
|
tick(t) {
|
|
36
|
-
const i = this.#t.tick(t), e = this.#i.tick(t), o = this.#s.tick(t),
|
|
37
|
-
return i || e || o ||
|
|
36
|
+
const i = this.#t.tick(t), e = this.#i.tick(t), o = this.#s.tick(t), h = this.#r.tick(t), n = this.#e.tick(t);
|
|
37
|
+
return i || e || o || h || n;
|
|
38
38
|
}
|
|
39
39
|
get current() {
|
|
40
40
|
const t = {
|
|
@@ -44,26 +44,29 @@ class dt {
|
|
|
44
44
|
low: this.#s.current,
|
|
45
45
|
close: this.#r.current
|
|
46
46
|
};
|
|
47
|
-
return this.#
|
|
47
|
+
return this.#l && (t.volume = this.#e.current), t;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
const
|
|
50
|
+
const _ = 2, bt = { tl: !0, tr: !0, br: !0, bl: !0 }, j = { tl: !0, tr: !0, br: !1, bl: !1 }, Yt = ct(), gt = pt(), yt = {
|
|
51
51
|
up: { body: "#26a69a", wick: "#26a69a" },
|
|
52
52
|
down: { body: "#ef5350", wick: "#ef5350" },
|
|
53
53
|
bodyWidthRatio: 0.6,
|
|
54
|
-
cornerRadius:
|
|
55
|
-
entryMs:
|
|
56
|
-
smoothMs:
|
|
57
|
-
introMs:
|
|
58
|
-
historyRevealMs:
|
|
54
|
+
cornerRadius: _,
|
|
55
|
+
entryMs: st,
|
|
56
|
+
smoothMs: ot,
|
|
57
|
+
introMs: et,
|
|
58
|
+
historyRevealMs: it
|
|
59
59
|
};
|
|
60
|
-
function q(
|
|
60
|
+
function q(a, t) {
|
|
61
|
+
return [a.open, a.high, a.low, a.close].every((i) => Number.isFinite(i) && t(i));
|
|
62
|
+
}
|
|
63
|
+
function tt(a) {
|
|
61
64
|
return {
|
|
62
|
-
...
|
|
63
|
-
entryMs:
|
|
64
|
-
smoothMs:
|
|
65
|
-
introMs:
|
|
66
|
-
historyRevealMs:
|
|
65
|
+
...a,
|
|
66
|
+
entryMs: a.entryMs === !1 ? 0 : a.entryMs ?? st,
|
|
67
|
+
smoothMs: a.smoothMs === !1 ? 0 : a.smoothMs ?? ot,
|
|
68
|
+
introMs: a.introMs === !1 ? 0 : a.introMs ?? et,
|
|
69
|
+
historyRevealMs: a.historyRevealMs === !1 ? 0 : a.historyRevealMs ?? it
|
|
67
70
|
};
|
|
68
71
|
}
|
|
69
72
|
class xt {
|
|
@@ -89,7 +92,7 @@ class xt {
|
|
|
89
92
|
* clamps every bar to full band height for ~30 frames. */
|
|
90
93
|
#r = !1;
|
|
91
94
|
/** Series-level alpha for visibility cross-fade. Chart calls {@link setAlpha} on hide. */
|
|
92
|
-
#e = new
|
|
95
|
+
#e = new nt({
|
|
93
96
|
initial: 1,
|
|
94
97
|
duration: 0,
|
|
95
98
|
lerp: (t, i, e) => t + (i - t) * e
|
|
@@ -102,7 +105,7 @@ class xt {
|
|
|
102
105
|
#n = null;
|
|
103
106
|
/** Visible range captured alongside {@link #introDirectives} — positions
|
|
104
107
|
* the per-element wave stagger. */
|
|
105
|
-
#
|
|
108
|
+
#l = null;
|
|
106
109
|
/** History-prepend reveal clock — armed by {@link prependPoints} so the
|
|
107
110
|
* new candles wave in from the data boundary instead of popping. */
|
|
108
111
|
#o = new U();
|
|
@@ -111,25 +114,25 @@ class xt {
|
|
|
111
114
|
* boundary and `1` at the deepest point. */
|
|
112
115
|
#a = null;
|
|
113
116
|
/** Per-frame history-reveal directives; `null` when no reveal is in flight. */
|
|
114
|
-
#
|
|
117
|
+
#h = null;
|
|
115
118
|
/** Loading-indicator placeholder shapes handed over by the chart right
|
|
116
119
|
* before a prepend (media px relative to `anchorTime`, the data boundary
|
|
117
120
|
* they were measured against) — mapped into bitmap space each frame and
|
|
118
121
|
* exposed to the reveal fn as {@link CandleIntroFrame.placeholders}.
|
|
119
122
|
* Cleared once the reveal settles. */
|
|
120
|
-
#
|
|
123
|
+
#c = null;
|
|
121
124
|
/** Body gradients keyed by `top|bottom|height` — built once at y=0..h and
|
|
122
125
|
* positioned per candle via `ctx.translate`, instead of a fresh
|
|
123
126
|
* `createLinearGradient` for every body on every frame. */
|
|
124
|
-
#
|
|
127
|
+
#m = /* @__PURE__ */ new Map();
|
|
125
128
|
constructor(t, i) {
|
|
126
|
-
this.store = t, this.options =
|
|
129
|
+
this.store = t, this.options = tt({ ...yt, ...i }), this.displayedLast = t.last() ?? null;
|
|
127
130
|
}
|
|
128
131
|
isEntryEnabled() {
|
|
129
132
|
return (this.options.entryAnimation ?? "unfold") !== "none";
|
|
130
133
|
}
|
|
131
134
|
updateOptions(t) {
|
|
132
|
-
this.options =
|
|
135
|
+
this.options = tt({ ...this.options, ...t });
|
|
133
136
|
}
|
|
134
137
|
getColor() {
|
|
135
138
|
return I(this.options.up.body);
|
|
@@ -139,13 +142,13 @@ class xt {
|
|
|
139
142
|
const i = this.store.length > 0;
|
|
140
143
|
this.store.setData(J(t ?? [])), !i && this.store.length > 0 && this.introWave.arm(this.options.introMs);
|
|
141
144
|
const e = this.store.last();
|
|
142
|
-
this.displayedLast = e ?? null, this.#t = null, this.entries.clear(), this.#i = null, this.#o.finish(), this.#a = null, this.#
|
|
145
|
+
this.displayedLast = e ?? null, this.#t = null, this.entries.clear(), this.#i = null, this.#o.finish(), this.#a = null, this.#c = null;
|
|
143
146
|
}
|
|
144
147
|
appendPoint(t) {
|
|
145
148
|
const i = t, e = Q(i.time), o = { ...i, time: e };
|
|
146
149
|
this.store.append(o), this.displayedLast = o, this.#t = null;
|
|
147
|
-
const
|
|
148
|
-
this.isEntryEnabled() &&
|
|
150
|
+
const h = this.options.entryMs;
|
|
151
|
+
this.isEntryEnabled() && h > 0 && this.entries.set(e, { startTime: performance.now() });
|
|
149
152
|
}
|
|
150
153
|
prependPoints(t) {
|
|
151
154
|
if (t.length === 0) return;
|
|
@@ -169,22 +172,22 @@ class xt {
|
|
|
169
172
|
}
|
|
170
173
|
setHistoryHandoff(t) {
|
|
171
174
|
const i = this.store.first()?.time;
|
|
172
|
-
i !== void 0 && (this.#
|
|
175
|
+
i !== void 0 && (this.#c = { bars: t, anchorTime: i });
|
|
173
176
|
}
|
|
174
177
|
updateLastPoint(t) {
|
|
175
178
|
const i = t, e = Q(i.time), o = { ...i, time: e };
|
|
176
179
|
this.store.updateLast(o);
|
|
177
|
-
const
|
|
178
|
-
if (
|
|
180
|
+
const h = this.options.smoothMs;
|
|
181
|
+
if (h <= 0) {
|
|
179
182
|
this.displayedLast = o, this.#t = null;
|
|
180
183
|
return;
|
|
181
184
|
}
|
|
182
|
-
let
|
|
183
|
-
if (
|
|
184
|
-
const
|
|
185
|
-
|
|
185
|
+
let n = this.#t;
|
|
186
|
+
if (n === null) {
|
|
187
|
+
const l = this.displayedLast ?? o;
|
|
188
|
+
n = new ft(l), this.#t = n;
|
|
186
189
|
}
|
|
187
|
-
|
|
190
|
+
n.retarget(o, { settleMs: h });
|
|
188
191
|
}
|
|
189
192
|
keepLast(t) {
|
|
190
193
|
if (t < 0) return;
|
|
@@ -220,7 +223,7 @@ class xt {
|
|
|
220
223
|
* fully-settled entrance entries. Called from `render()` once per frame.
|
|
221
224
|
*/
|
|
222
225
|
tickAnimations(t) {
|
|
223
|
-
this.introWave.tick(t), this.#o.tick(t), this.#o.active || (this.#
|
|
226
|
+
this.introWave.tick(t), this.#o.tick(t), this.#o.active || (this.#c = null), this.#e.tick(t);
|
|
224
227
|
const i = this.#t;
|
|
225
228
|
if (i !== null) {
|
|
226
229
|
const o = i.tick(t);
|
|
@@ -231,8 +234,8 @@ class xt {
|
|
|
231
234
|
this.entries.clear();
|
|
232
235
|
return;
|
|
233
236
|
}
|
|
234
|
-
for (const [o,
|
|
235
|
-
t -
|
|
237
|
+
for (const [o, h] of this.entries)
|
|
238
|
+
t - h.startTime >= e && this.entries.delete(o);
|
|
236
239
|
}
|
|
237
240
|
/** True while OHLC chase, any per-candle entrance, the initial reveal,
|
|
238
241
|
* alpha fade, or the volume scale is unsettled. */
|
|
@@ -279,134 +282,134 @@ class xt {
|
|
|
279
282
|
getVisibleDataPoints(t, i) {
|
|
280
283
|
return this.store.getVisibleData(t, i);
|
|
281
284
|
}
|
|
282
|
-
getValueRange(t, i) {
|
|
283
|
-
const
|
|
284
|
-
let
|
|
285
|
-
for (const
|
|
286
|
-
Number.isFinite(
|
|
287
|
-
return
|
|
285
|
+
getValueRange(t, i, e) {
|
|
286
|
+
const o = this.store.getVisibleData(t, i), h = e?.plottable;
|
|
287
|
+
let n = 1 / 0, l = -1 / 0;
|
|
288
|
+
for (const p of o)
|
|
289
|
+
h && !q(p, h) || (Number.isFinite(p.low) && p.low < n && (n = p.low), Number.isFinite(p.high) && p.high > l && (l = p.high));
|
|
290
|
+
return n === 1 / 0 || l === -1 / 0 ? null : { min: n, max: l };
|
|
288
291
|
}
|
|
289
292
|
render(t) {
|
|
290
293
|
this.tickAnimations(performance.now());
|
|
291
|
-
const { scope: i, timeScale: e, yScale: o, dataInterval:
|
|
292
|
-
let m = this.store.getVisibleData(
|
|
293
|
-
const
|
|
294
|
-
if (
|
|
294
|
+
const { scope: i, timeScale: e, yScale: o, dataInterval: h } = t, { context: n, horizontalPixelRatio: l } = i, p = e.getRange();
|
|
295
|
+
let m = this.store.getVisibleData(p.from, p.to);
|
|
296
|
+
const Y = i.mediaSize.width, M = m.length > Y * 2;
|
|
297
|
+
if (M && (m = rt(m, Math.round(Y * 1.5))), o.getTransform() !== null && (m = m.filter((r) => q(r, (c) => o.isPlottable(c)))), m.length === 0) return;
|
|
295
298
|
const S = this.displayedLast;
|
|
296
|
-
if (!
|
|
299
|
+
if (!M && S !== null) {
|
|
297
300
|
const r = m.length - 1;
|
|
298
301
|
m[r].time === S.time && (m = [...m.slice(0, r), S]);
|
|
299
302
|
}
|
|
300
|
-
if (this.#n = null, this.#
|
|
301
|
-
const r = this.options.introAnimation ??
|
|
302
|
-
this.#
|
|
303
|
+
if (this.#n = null, this.#l = null, this.introWave.active) {
|
|
304
|
+
const r = this.options.introAnimation ?? Yt;
|
|
305
|
+
this.#l = p, this.#n = r({
|
|
303
306
|
progress: this.introWave.linear(),
|
|
304
307
|
// Plot-area extent, not the canvas bitmap — the canvas also carries
|
|
305
308
|
// the axis strips, so a width-based front (wipeIntro) would overshoot
|
|
306
309
|
// the data area.
|
|
307
310
|
width: e.getMediaWidth() * i.horizontalPixelRatio,
|
|
308
311
|
height: o.getMediaHeight() * i.verticalPixelRatio,
|
|
309
|
-
range:
|
|
310
|
-
timeToX: (
|
|
312
|
+
range: p,
|
|
313
|
+
timeToX: (c) => e.timeToBitmapX(c)
|
|
311
314
|
});
|
|
312
315
|
}
|
|
313
|
-
this.#
|
|
314
|
-
const
|
|
315
|
-
if (this.#o.active &&
|
|
316
|
-
const r = this.options.historyReveal ??
|
|
316
|
+
this.#h = null;
|
|
317
|
+
const u = this.#a;
|
|
318
|
+
if (this.#o.active && u !== null) {
|
|
319
|
+
const r = this.options.historyReveal ?? gt;
|
|
317
320
|
if (r !== "none") {
|
|
318
|
-
let
|
|
319
|
-
const x = this.#
|
|
321
|
+
let c;
|
|
322
|
+
const x = this.#c;
|
|
320
323
|
if (x !== null && x.bars.length > 0) {
|
|
321
324
|
const P = e.timeToBitmapX(x.anchorTime);
|
|
322
|
-
|
|
325
|
+
c = x.bars.map((k) => ({
|
|
323
326
|
x: P - k.offsetX * i.horizontalPixelRatio,
|
|
324
327
|
y: k.y * i.verticalPixelRatio,
|
|
325
328
|
halfHeight: k.halfHeight * i.verticalPixelRatio,
|
|
326
329
|
width: k.width * i.horizontalPixelRatio
|
|
327
330
|
}));
|
|
328
331
|
}
|
|
329
|
-
this.#
|
|
332
|
+
this.#h = r({
|
|
330
333
|
progress: this.#o.linear(),
|
|
331
|
-
width: Math.abs(e.timeToBitmapX(
|
|
334
|
+
width: Math.abs(e.timeToBitmapX(u.to) - e.timeToBitmapX(u.from)),
|
|
332
335
|
height: o.getMediaHeight() * i.verticalPixelRatio,
|
|
333
|
-
range:
|
|
336
|
+
range: u,
|
|
334
337
|
timeToX: (P) => e.timeToBitmapX(P),
|
|
335
|
-
placeholders:
|
|
338
|
+
placeholders: c
|
|
336
339
|
});
|
|
337
340
|
}
|
|
338
341
|
}
|
|
339
342
|
let W = null;
|
|
340
343
|
if (this.entries.size > 0) {
|
|
341
|
-
const r = this.options.entryMs,
|
|
344
|
+
const r = this.options.entryMs, c = performance.now();
|
|
342
345
|
for (const x of m) {
|
|
343
346
|
const P = this.entries.get(x.time);
|
|
344
347
|
if (P === void 0 || r <= 0) continue;
|
|
345
|
-
const k =
|
|
346
|
-
|
|
348
|
+
const k = c - P.startTime, V = Math.min(1, Math.max(0, k / r));
|
|
349
|
+
V >= 1 || (W === null && (W = /* @__PURE__ */ new Map()), W.set(x.time, at(V)));
|
|
347
350
|
}
|
|
348
351
|
}
|
|
349
|
-
const X = e.barWidthBitmap(
|
|
350
|
-
let
|
|
351
|
-
(
|
|
352
|
-
const R = Math.floor(
|
|
352
|
+
const X = e.barWidthBitmap(h), b = Math.round(30 * l), w = m.length <= 2 ? Math.min(b, X) : X, f = Math.max(1, Math.round(l));
|
|
353
|
+
let g = Math.max(1, Math.round(w * this.options.bodyWidthRatio) - 2);
|
|
354
|
+
(g & 1) !== (f & 1) && (g = g > 1 ? g - 1 : 2);
|
|
355
|
+
const R = Math.floor(g / 2), v = this.#n?.clip;
|
|
353
356
|
if (v !== void 0) {
|
|
354
|
-
const r = v.fromX ?? 0,
|
|
355
|
-
|
|
357
|
+
const r = v.fromX ?? 0, c = v.toX ?? i.bitmapSize.width;
|
|
358
|
+
n.save(), n.beginPath(), n.rect(r, 0, Math.max(0, c - r), i.bitmapSize.height), n.clip();
|
|
356
359
|
}
|
|
357
|
-
const T = this.#
|
|
360
|
+
const T = this.#h?.clip;
|
|
358
361
|
let A = !1;
|
|
359
|
-
if (T !== void 0 &&
|
|
360
|
-
const r = e.timeToBitmapX(
|
|
361
|
-
|
|
362
|
+
if (T !== void 0 && u !== null) {
|
|
363
|
+
const r = e.timeToBitmapX(u.to), c = Math.abs(r - e.timeToBitmapX(u.from)), x = w, P = T.fromX ?? 0, k = T.toX ?? c;
|
|
364
|
+
n.save(), n.beginPath(), n.rect(r - k - x, 0, Math.max(0, k - P + x), i.bitmapSize.height), n.rect(r, 0, Math.max(0, i.bitmapSize.width - r), i.bitmapSize.height), n.clip(), A = !0;
|
|
362
365
|
}
|
|
363
|
-
const
|
|
364
|
-
this.#r =
|
|
365
|
-
const
|
|
366
|
+
const s = M !== this.#r;
|
|
367
|
+
this.#r = M;
|
|
368
|
+
const d = Math.round(o.getMediaHeight() * i.verticalPixelRatio);
|
|
366
369
|
this.drawVolume({
|
|
367
|
-
ctx:
|
|
370
|
+
ctx: n,
|
|
368
371
|
data: m,
|
|
369
372
|
timeScale: e,
|
|
370
|
-
chartHeight:
|
|
371
|
-
barWidth:
|
|
372
|
-
wickWidth:
|
|
373
|
+
chartHeight: d,
|
|
374
|
+
barWidth: w,
|
|
375
|
+
wickWidth: f,
|
|
373
376
|
entranceByTime: W,
|
|
374
|
-
snapVolScale:
|
|
375
|
-
radius: (this.options.cornerRadius ??
|
|
377
|
+
snapVolScale: s,
|
|
378
|
+
radius: (this.options.cornerRadius ?? _) * l
|
|
376
379
|
});
|
|
377
|
-
const
|
|
380
|
+
const y = [], L = [], B = [];
|
|
378
381
|
let C = null;
|
|
379
382
|
for (let r = 0; r < m.length; r++) {
|
|
380
|
-
const
|
|
381
|
-
if (N(
|
|
382
|
-
B.push(r), C === null && (C =
|
|
383
|
+
const c = m[r];
|
|
384
|
+
if (N(c.open) || N(c.close) || N(c.high) || N(c.low)) {
|
|
385
|
+
B.push(r), C === null && (C = c);
|
|
383
386
|
continue;
|
|
384
387
|
}
|
|
385
|
-
|
|
388
|
+
c.close >= c.open ? y.push(c) : L.push(c);
|
|
386
389
|
}
|
|
387
390
|
C !== null && ht(this, "candlestick", B, `time ${C.time}`);
|
|
388
391
|
const E = {
|
|
389
392
|
painter: mt(this.options.candlePainter),
|
|
390
393
|
env: {
|
|
391
|
-
ctx:
|
|
394
|
+
ctx: n,
|
|
392
395
|
theme: t.theme,
|
|
393
|
-
horizontalPixelRatio:
|
|
396
|
+
horizontalPixelRatio: l,
|
|
394
397
|
verticalPixelRatio: i.verticalPixelRatio
|
|
395
398
|
},
|
|
396
|
-
radius: (this.options.cornerRadius ??
|
|
399
|
+
radius: (this.options.cornerRadius ?? _) * l
|
|
397
400
|
}, D = {
|
|
398
|
-
ctx:
|
|
401
|
+
ctx: n,
|
|
399
402
|
timeScale: e,
|
|
400
403
|
yScale: o,
|
|
401
404
|
halfBody: R,
|
|
402
|
-
bodyWidth:
|
|
403
|
-
wickWidth:
|
|
405
|
+
bodyWidth: g,
|
|
406
|
+
wickWidth: f,
|
|
404
407
|
entranceByTime: W,
|
|
405
408
|
candlePass: E
|
|
406
409
|
};
|
|
407
410
|
this.drawCandles({
|
|
408
411
|
...D,
|
|
409
|
-
candles:
|
|
412
|
+
candles: y,
|
|
410
413
|
body: this.options.up.body,
|
|
411
414
|
wickColor: this.options.up.wick
|
|
412
415
|
}), this.drawCandles({
|
|
@@ -414,7 +417,7 @@ class xt {
|
|
|
414
417
|
candles: L,
|
|
415
418
|
body: this.options.down.body,
|
|
416
419
|
wickColor: this.options.down.wick
|
|
417
|
-
}), A &&
|
|
420
|
+
}), A && n.restore(), v !== void 0 && n.restore();
|
|
418
421
|
}
|
|
419
422
|
/**
|
|
420
423
|
* Apply the intro's per-element directive to one element's settled (or
|
|
@@ -422,15 +425,15 @@ class xt {
|
|
|
422
425
|
* is in flight this frame.
|
|
423
426
|
*/
|
|
424
427
|
introTransform(t) {
|
|
425
|
-
const i = this.#
|
|
428
|
+
const i = this.#h?.element, e = this.#a;
|
|
426
429
|
if (i !== void 0 && e !== null && t.time < e.to) {
|
|
427
|
-
const m = e.to - e.from,
|
|
428
|
-
return this.#p(
|
|
430
|
+
const m = e.to - e.from, Y = m > 0 ? F((e.to - t.time) / m, 0, 1) : 0, M = i({ ...t, position: Y, progress: this.#o.progressAt(Y) });
|
|
431
|
+
return this.#p(M, t);
|
|
429
432
|
}
|
|
430
|
-
const o = this.#n?.element,
|
|
431
|
-
if (o === void 0 ||
|
|
432
|
-
const
|
|
433
|
-
return this.#p(
|
|
433
|
+
const o = this.#n?.element, h = this.#l;
|
|
434
|
+
if (o === void 0 || h === null) return null;
|
|
435
|
+
const n = h.to - h.from, l = n > 0 ? F((t.time - h.from) / n, 0, 1) : 0, p = o({ ...t, position: l, progress: this.introWave.progressAt(l) });
|
|
436
|
+
return this.#p(p, t);
|
|
434
437
|
}
|
|
435
438
|
/** Map a directive's declarative transform onto the element's settled
|
|
436
439
|
* geometry. Absolute `topY`/`bottomY` overrides (a morph's arbitrary
|
|
@@ -451,65 +454,65 @@ class xt {
|
|
|
451
454
|
data: i,
|
|
452
455
|
timeScale: e,
|
|
453
456
|
chartHeight: o,
|
|
454
|
-
barWidth:
|
|
455
|
-
wickWidth:
|
|
456
|
-
entranceByTime:
|
|
457
|
-
snapVolScale:
|
|
457
|
+
barWidth: h,
|
|
458
|
+
wickWidth: n,
|
|
459
|
+
entranceByTime: l,
|
|
460
|
+
snapVolScale: p,
|
|
458
461
|
radius: m
|
|
459
462
|
}) {
|
|
460
|
-
let
|
|
461
|
-
for (const
|
|
462
|
-
Number.isFinite(
|
|
463
|
-
if (
|
|
463
|
+
let Y = 0;
|
|
464
|
+
for (const f of i)
|
|
465
|
+
Number.isFinite(f.volume) && f.volume > Y && (Y = f.volume);
|
|
466
|
+
if (Y === 0) {
|
|
464
467
|
this.#i = null, this.#s = !0;
|
|
465
468
|
return;
|
|
466
469
|
}
|
|
467
|
-
this.#i === null ||
|
|
468
|
-
const
|
|
469
|
-
let
|
|
470
|
-
(
|
|
471
|
-
const W = Math.floor(
|
|
472
|
-
for (const
|
|
473
|
-
if (!Number.isFinite(
|
|
474
|
-
const
|
|
475
|
-
t.fillStyle = T ? X :
|
|
476
|
-
const A =
|
|
477
|
-
let
|
|
478
|
-
if (A < 1 &&
|
|
479
|
-
const
|
|
480
|
-
x:
|
|
481
|
-
barWidth:
|
|
470
|
+
this.#i === null || p ? this.#i = Y : this.#i += (Y - this.#i) * ut, this.#s = Math.abs(Y - this.#i) <= Y * dt;
|
|
471
|
+
const M = this.#i, S = o * 0.2;
|
|
472
|
+
let u = Math.max(1, h - 2);
|
|
473
|
+
(u & 1) !== (n & 1) && (u = u > 1 ? u - 1 : 2);
|
|
474
|
+
const W = Math.floor(u / 2), X = K(I(this.options.up.body), 0.2), b = K(I(this.options.down.body), 0.2), w = this.options.entryAnimation ?? "unfold";
|
|
475
|
+
for (const f of i) {
|
|
476
|
+
if (!Number.isFinite(f.volume) || f.volume <= 0) continue;
|
|
477
|
+
const g = f.volume, R = e.timeToBitmapX(f.time), v = Math.min(S, Math.max(1, g / M * S)), T = f.close >= f.open;
|
|
478
|
+
t.fillStyle = T ? X : b;
|
|
479
|
+
const A = l?.get(f.time) ?? 1;
|
|
480
|
+
let s = { x: R - W, topY: o - v, bottomY: o, alpha: 1 };
|
|
481
|
+
if (A < 1 && w !== "none") {
|
|
482
|
+
const y = O(A, w, {
|
|
483
|
+
x: s.x,
|
|
484
|
+
barWidth: u,
|
|
482
485
|
anchorY: o,
|
|
483
|
-
topY:
|
|
484
|
-
bottomY:
|
|
486
|
+
topY: s.topY,
|
|
487
|
+
bottomY: s.bottomY
|
|
485
488
|
});
|
|
486
|
-
|
|
489
|
+
s = { x: y.x, topY: y.topY, bottomY: y.bottomY, alpha: y.alpha };
|
|
487
490
|
}
|
|
488
|
-
const
|
|
491
|
+
const d = this.introTransform({
|
|
489
492
|
element: "volume",
|
|
490
|
-
time:
|
|
491
|
-
x:
|
|
492
|
-
topY:
|
|
493
|
-
bottomY:
|
|
493
|
+
time: f.time,
|
|
494
|
+
x: s.x,
|
|
495
|
+
topY: s.topY,
|
|
496
|
+
bottomY: s.bottomY,
|
|
494
497
|
anchorY: o,
|
|
495
|
-
barWidth:
|
|
498
|
+
barWidth: u
|
|
496
499
|
});
|
|
497
|
-
if (
|
|
500
|
+
if (d !== null && (s = { x: d.x, topY: d.topY, bottomY: d.bottomY, alpha: s.alpha * d.alpha }), s.alpha >= 1) {
|
|
498
501
|
Z(t, {
|
|
499
|
-
x:
|
|
500
|
-
y:
|
|
501
|
-
width:
|
|
502
|
-
height: Math.max(1,
|
|
502
|
+
x: s.x,
|
|
503
|
+
y: s.topY,
|
|
504
|
+
width: u,
|
|
505
|
+
height: Math.max(1, s.bottomY - s.topY),
|
|
503
506
|
radius: m,
|
|
504
507
|
corners: j
|
|
505
508
|
});
|
|
506
509
|
continue;
|
|
507
510
|
}
|
|
508
|
-
t.save(), t.globalAlpha =
|
|
509
|
-
x:
|
|
510
|
-
y:
|
|
511
|
-
width:
|
|
512
|
-
height: Math.max(1,
|
|
511
|
+
t.save(), t.globalAlpha = s.alpha, Z(t, {
|
|
512
|
+
x: s.x,
|
|
513
|
+
y: s.topY,
|
|
514
|
+
width: u,
|
|
515
|
+
height: Math.max(1, s.bottomY - s.topY),
|
|
513
516
|
radius: m,
|
|
514
517
|
corners: j
|
|
515
518
|
}), t.restore();
|
|
@@ -520,85 +523,85 @@ class xt {
|
|
|
520
523
|
candles: i,
|
|
521
524
|
timeScale: e,
|
|
522
525
|
yScale: o,
|
|
523
|
-
halfBody:
|
|
524
|
-
bodyWidth:
|
|
525
|
-
wickWidth:
|
|
526
|
-
body:
|
|
526
|
+
halfBody: h,
|
|
527
|
+
bodyWidth: n,
|
|
528
|
+
wickWidth: l,
|
|
529
|
+
body: p,
|
|
527
530
|
wickColor: m,
|
|
528
|
-
entranceByTime:
|
|
529
|
-
candlePass:
|
|
531
|
+
entranceByTime: Y,
|
|
532
|
+
candlePass: M
|
|
530
533
|
}) {
|
|
531
534
|
if (i.length === 0) return;
|
|
532
|
-
const S = this.options.entryAnimation ?? "unfold",
|
|
535
|
+
const S = this.options.entryAnimation ?? "unfold", u = n + 2, W = M.env.theme.axis.textColor ?? "#787b86";
|
|
533
536
|
t.fillStyle = m;
|
|
534
|
-
for (const
|
|
535
|
-
const
|
|
536
|
-
let A = !1,
|
|
537
|
-
if (
|
|
538
|
-
const L =
|
|
537
|
+
for (const b of i) {
|
|
538
|
+
const w = Y?.get(b.time) ?? 1, f = e.timeToBitmapX(b.time), g = o.valueToBitmapY(b.open), R = o.valueToBitmapY(b.high), v = o.valueToBitmapY(b.low), T = f - Math.floor(l / 2);
|
|
539
|
+
let A = !1, s = { x: T, topY: R, bottomY: v, alpha: 1 };
|
|
540
|
+
if (w < 1 && S !== "none") {
|
|
541
|
+
const L = O(w, S, {
|
|
539
542
|
x: T,
|
|
540
|
-
barWidth:
|
|
541
|
-
anchorY:
|
|
543
|
+
barWidth: u,
|
|
544
|
+
anchorY: g,
|
|
542
545
|
topY: R,
|
|
543
546
|
bottomY: v
|
|
544
547
|
});
|
|
545
|
-
|
|
548
|
+
s = { x: L.x, topY: L.topY, bottomY: L.bottomY, alpha: L.alpha }, A = !0;
|
|
546
549
|
}
|
|
547
|
-
const
|
|
550
|
+
const d = this.introTransform({
|
|
548
551
|
element: "wick",
|
|
549
|
-
time:
|
|
550
|
-
x:
|
|
551
|
-
topY:
|
|
552
|
-
bottomY:
|
|
553
|
-
anchorY:
|
|
554
|
-
barWidth:
|
|
552
|
+
time: b.time,
|
|
553
|
+
x: s.x,
|
|
554
|
+
topY: s.topY,
|
|
555
|
+
bottomY: s.bottomY,
|
|
556
|
+
anchorY: g,
|
|
557
|
+
barWidth: u
|
|
555
558
|
});
|
|
556
|
-
let
|
|
557
|
-
if (
|
|
558
|
-
t.fillRect(T, R,
|
|
559
|
+
let y = 0;
|
|
560
|
+
if (d !== null && (s = { x: d.x, topY: d.topY, bottomY: d.bottomY, alpha: s.alpha * d.alpha }, y = d.tint ?? 0, A = !0), !A) {
|
|
561
|
+
t.fillRect(T, R, l, v - R);
|
|
559
562
|
continue;
|
|
560
563
|
}
|
|
561
|
-
t.save(), t.globalAlpha =
|
|
564
|
+
t.save(), t.globalAlpha = s.alpha, y > 0 && (t.fillStyle = G(m, W, y)), t.fillRect(s.x, s.topY, l, Math.max(1, s.bottomY - s.topY)), t.restore();
|
|
562
565
|
}
|
|
563
|
-
const X = Array.isArray(
|
|
564
|
-
for (const
|
|
565
|
-
const
|
|
566
|
-
let
|
|
567
|
-
if (
|
|
568
|
-
const H =
|
|
569
|
-
x:
|
|
570
|
-
barWidth:
|
|
571
|
-
anchorY:
|
|
566
|
+
const X = Array.isArray(p);
|
|
567
|
+
for (const b of i) {
|
|
568
|
+
const w = Y?.get(b.time) ?? 1, f = e.timeToBitmapX(b.time), g = o.valueToBitmapY(b.open), R = o.valueToBitmapY(b.close), v = Math.min(g, R), T = Math.max(g, R), A = Math.max(1, T - v);
|
|
569
|
+
let s = f - h, d = v, y = T, L = 1, B = !1;
|
|
570
|
+
if (w < 1 && S !== "none") {
|
|
571
|
+
const H = O(w, S, {
|
|
572
|
+
x: s,
|
|
573
|
+
barWidth: u,
|
|
574
|
+
anchorY: g,
|
|
572
575
|
topY: v,
|
|
573
576
|
bottomY: T
|
|
574
577
|
});
|
|
575
|
-
|
|
578
|
+
s = H.x, d = H.topY, y = H.bottomY, L = H.alpha, B = !0;
|
|
576
579
|
}
|
|
577
580
|
const C = this.introTransform({
|
|
578
581
|
element: "body",
|
|
579
|
-
time:
|
|
580
|
-
x:
|
|
581
|
-
topY:
|
|
582
|
-
bottomY:
|
|
583
|
-
anchorY:
|
|
584
|
-
barWidth:
|
|
582
|
+
time: b.time,
|
|
583
|
+
x: s,
|
|
584
|
+
topY: d,
|
|
585
|
+
bottomY: y,
|
|
586
|
+
anchorY: g,
|
|
587
|
+
barWidth: u
|
|
585
588
|
});
|
|
586
589
|
let E = 0;
|
|
587
|
-
C !== null && (
|
|
588
|
-
const D = B ? Math.max(1,
|
|
590
|
+
C !== null && (s = C.x, d = C.topY, y = C.bottomY, L *= C.alpha, E = C.tint ?? 0, B = !0);
|
|
591
|
+
const D = B ? Math.max(1, y - d) : A;
|
|
589
592
|
B && t.save();
|
|
590
|
-
const r = Array.isArray(
|
|
591
|
-
t.fillStyle = P, B && (t.globalAlpha = L), x && t.translate(0,
|
|
592
|
-
const k = x ? 0 :
|
|
593
|
-
|
|
594
|
-
geom: { x:
|
|
593
|
+
const r = Array.isArray(p) ? p[0] : p, c = E > 0 ? G(r, W, E) : r, x = X && D > 2 && E <= 0, P = x ? this.#d(t, p, D) : c;
|
|
594
|
+
t.fillStyle = P, B && (t.globalAlpha = L), x && t.translate(0, d);
|
|
595
|
+
const k = x ? 0 : d, V = F(M.radius, 0, Math.min(n, D) / 2);
|
|
596
|
+
V < 1 && !this.options.candlePainter ? t.fillRect(s, k, n, D) : M.painter(M.env, {
|
|
597
|
+
geom: { x: s, y: k, width: n, height: D },
|
|
595
598
|
fillStyle: P,
|
|
596
|
-
color:
|
|
597
|
-
corners:
|
|
598
|
-
radius:
|
|
599
|
-
progress:
|
|
600
|
-
isBullish:
|
|
601
|
-
}), x && t.translate(0, -
|
|
599
|
+
color: c,
|
|
600
|
+
corners: bt,
|
|
601
|
+
radius: V,
|
|
602
|
+
progress: w,
|
|
603
|
+
isBullish: b.close >= b.open
|
|
604
|
+
}), x && t.translate(0, -d), B && t.restore();
|
|
602
605
|
}
|
|
603
606
|
}
|
|
604
607
|
/**
|
|
@@ -609,51 +612,51 @@ class xt {
|
|
|
609
612
|
* continuously, and a full clear is cheaper than an eviction policy.
|
|
610
613
|
*/
|
|
611
614
|
#d(t, i, e) {
|
|
612
|
-
const o = Math.max(3, Math.round(e)),
|
|
613
|
-
if (
|
|
614
|
-
this.#
|
|
615
|
-
const
|
|
616
|
-
return
|
|
615
|
+
const o = Math.max(3, Math.round(e)), h = `${i[0]}|${i[1]}|${o}`, n = this.#m.get(h);
|
|
616
|
+
if (n !== void 0) return n;
|
|
617
|
+
this.#m.size >= 512 && this.#m.clear();
|
|
618
|
+
const l = t.createLinearGradient(0, 0, 0, o);
|
|
619
|
+
return l.addColorStop(0, i[0]), l.addColorStop(1, i[1]), this.#m.set(h, l), l;
|
|
617
620
|
}
|
|
618
621
|
}
|
|
619
|
-
function
|
|
622
|
+
function O(a, t, i) {
|
|
620
623
|
switch (t) {
|
|
621
624
|
case "none":
|
|
622
625
|
return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha: 1 };
|
|
623
626
|
case "fade":
|
|
624
|
-
return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha:
|
|
627
|
+
return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha: a };
|
|
625
628
|
case "unfold":
|
|
626
629
|
return {
|
|
627
630
|
x: i.x,
|
|
628
|
-
topY: z(i.anchorY, i.topY,
|
|
629
|
-
bottomY: z(i.anchorY, i.bottomY,
|
|
631
|
+
topY: z(i.anchorY, i.topY, a),
|
|
632
|
+
bottomY: z(i.anchorY, i.bottomY, a),
|
|
630
633
|
alpha: 1
|
|
631
634
|
};
|
|
632
635
|
case "slide":
|
|
633
636
|
return {
|
|
634
|
-
x: i.x + (1 -
|
|
637
|
+
x: i.x + (1 - a) * i.barWidth,
|
|
635
638
|
topY: i.topY,
|
|
636
639
|
bottomY: i.bottomY,
|
|
637
|
-
alpha:
|
|
640
|
+
alpha: a
|
|
638
641
|
};
|
|
639
642
|
case "fade-unfold":
|
|
640
643
|
return {
|
|
641
644
|
x: i.x,
|
|
642
|
-
topY: z(i.anchorY, i.topY,
|
|
643
|
-
bottomY: z(i.anchorY, i.bottomY,
|
|
644
|
-
alpha:
|
|
645
|
+
topY: z(i.anchorY, i.topY, a),
|
|
646
|
+
bottomY: z(i.anchorY, i.bottomY, a),
|
|
647
|
+
alpha: a
|
|
645
648
|
};
|
|
646
649
|
}
|
|
647
650
|
}
|
|
648
|
-
const
|
|
651
|
+
const zt = {
|
|
649
652
|
type: "candlestick",
|
|
650
|
-
create: ({ theme:
|
|
651
|
-
up: { ...
|
|
652
|
-
down: { ...
|
|
653
|
+
create: ({ theme: a }, t) => new xt(new lt(), {
|
|
654
|
+
up: { ...a.candlestick.up },
|
|
655
|
+
down: { ...a.candlestick.down },
|
|
653
656
|
...t
|
|
654
657
|
})
|
|
655
658
|
};
|
|
656
659
|
export {
|
|
657
660
|
xt as CandlestickRenderer,
|
|
658
|
-
|
|
661
|
+
zt as CandlestickSeriesDef
|
|
659
662
|
};
|