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