@wick-charts/vue 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/BandSeries.vue.js +43 -32
- package/dist/BarSeries.vue.js +44 -33
- package/dist/CandlestickSeries.vue.js +24 -23
- package/dist/ChartContainer.vue.js +1 -1
- package/dist/HeatmapSeries.vue.js +21 -20
- package/dist/LineSeries.vue.js +43 -32
- package/dist/PieSeries.vue.js +25 -24
- package/dist/composables.js +63 -36
- package/dist/core/dist/axis/dom-labels.js +64 -53
- package/dist/core/dist/chart/badge-animator.js +38 -28
- package/dist/core/dist/chart/options.js +1 -1
- package/dist/core/dist/chart/y-target.js +38 -32
- package/dist/core/dist/chart.js +852 -709
- package/dist/core/dist/data/decimation.js +52 -51
- package/dist/core/dist/data/store.js +38 -20
- package/dist/core/dist/data/sync.js +97 -59
- package/dist/core/dist/navigator/controller.js +11 -11
- package/dist/core/dist/perf/perf-hud.js +3 -3
- package/dist/core/dist/scales/tick-tracker.js +2 -1
- package/dist/core/dist/scales/time-ticks.js +99 -0
- package/dist/core/dist/scales/x-scale.js +33 -27
- package/dist/core/dist/series/band.js +83 -83
- package/dist/core/dist/series/bar.js +240 -211
- package/dist/core/dist/series/base-multi-layer.js +288 -240
- package/dist/core/dist/series/candlestick.js +168 -168
- package/dist/core/dist/series/line.js +545 -455
- package/dist/core/dist/snapshots.js +109 -86
- package/dist/core/dist/utils/point.js +4 -0
- package/dist/core/dist/utils/time.js +42 -26
- package/dist/index.d.ts +67 -28
- package/dist/ui/InfoBar.vue.js +69 -69
- package/dist/ui/NumberFlow.vue.js +36 -27
- package/dist/ui/Tooltip.vue.js +128 -131
- package/dist/ui/YLabel.vue.js +47 -47
- package/package.json +2 -2
- package/src/BandSeries.vue +20 -5
- package/src/BarSeries.vue +20 -5
- package/src/CandlestickSeries.vue +5 -4
- package/src/ChartContainer.vue +15 -9
- package/src/HeatmapSeries.vue +5 -4
- package/src/LineSeries.vue +20 -5
- package/src/PieSeries.vue +6 -5
- package/src/composables.ts +64 -1
- package/src/ui/InfoBar.vue +11 -3
- package/src/ui/NumberFlow.vue +17 -3
- package/src/ui/Tooltip.vue +23 -12
- package/src/ui/YLabel.vue +28 -27
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { Animator as nt } from "../animation/animator.js";
|
|
2
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
|
|
3
|
+
import { easeOutCubic as rt } from "../animation/easing.js";
|
|
4
4
|
import { IntroWave as U } from "../animation/intro-wave.js";
|
|
5
|
-
import { ScalarSpring as
|
|
6
|
-
import { decimateOHLCData as
|
|
5
|
+
import { ScalarSpring as I } from "../animation/scalar-spring.js";
|
|
6
|
+
import { decimateOHLCData as at } from "../data/decimation.js";
|
|
7
7
|
import { TimeSeriesStore as lt } from "../data/store.js";
|
|
8
|
-
import { resolveCandlestickBodyColor as
|
|
8
|
+
import { resolveCandlestickBodyColor as V } from "../theme/resolve.js";
|
|
9
9
|
import { hexToRgba as K, mixColors as G } from "../utils/color.js";
|
|
10
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
|
-
import { normalizeOHLCArray as J, normalizeTime as Q } from "../utils/time.js";
|
|
12
|
+
import { normalizeOHLCArray as J, normalizeTime as Q, sliceSample as mt } from "../utils/time.js";
|
|
13
13
|
import { candleUnfoldIntro as ct } from "./candlestick-intro.js";
|
|
14
14
|
import { fillRoundedRect as Z } from "./painters/canvas-path.js";
|
|
15
|
-
import { resolveCandlePainter as
|
|
16
|
-
import { fadeIntro as
|
|
17
|
-
const
|
|
18
|
-
class
|
|
15
|
+
import { resolveCandlePainter as pt } from "./painters/resolve.js";
|
|
16
|
+
import { fadeIntro as ut } from "./wave-intro.js";
|
|
17
|
+
const dt = 0.15, ft = 5e-3;
|
|
18
|
+
class bt {
|
|
19
19
|
#t;
|
|
20
20
|
#i;
|
|
21
21
|
#s;
|
|
22
|
-
#
|
|
22
|
+
#a;
|
|
23
23
|
#e;
|
|
24
24
|
#n;
|
|
25
25
|
// Sticky once any seen candle carries volume — mirrors the old lerp, which
|
|
@@ -27,13 +27,13 @@ class ft {
|
|
|
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 I(t.open), this.#i = new I(t.high), this.#s = new I(t.low), this.#a = new I(t.close), this.#e = new I(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.#l = !0), this.#t.retarget(t.open, i), this.#i.retarget(t.high, i), this.#s.retarget(t.low, i), 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.#a.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), h = this.#
|
|
36
|
+
const i = this.#t.tick(t), e = this.#i.tick(t), o = this.#s.tick(t), h = this.#a.tick(t), n = this.#e.tick(t);
|
|
37
37
|
return i || e || o || h || n;
|
|
38
38
|
}
|
|
39
39
|
get current() {
|
|
@@ -42,34 +42,34 @@ class ft {
|
|
|
42
42
|
open: this.#t.current,
|
|
43
43
|
high: this.#i.current,
|
|
44
44
|
low: this.#s.current,
|
|
45
|
-
close: this.#
|
|
45
|
+
close: this.#a.current
|
|
46
46
|
};
|
|
47
47
|
return this.#l && (t.volume = this.#e.current), t;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
const
|
|
50
|
+
const $ = 2, Yt = { tl: !0, tr: !0, br: !0, bl: !0 }, j = { tl: !0, tr: !0, br: !1, bl: !1 }, gt = ct(), xt = ut(), yt = {
|
|
51
51
|
up: { body: "#26a69a", wick: "#26a69a" },
|
|
52
52
|
down: { body: "#ef5350", wick: "#ef5350" },
|
|
53
53
|
bodyWidthRatio: 0.6,
|
|
54
|
-
cornerRadius:
|
|
54
|
+
cornerRadius: $,
|
|
55
55
|
entryMs: st,
|
|
56
56
|
smoothMs: ot,
|
|
57
57
|
introMs: et,
|
|
58
58
|
historyRevealMs: it
|
|
59
59
|
};
|
|
60
|
-
function q(
|
|
61
|
-
return [
|
|
60
|
+
function q(r, t) {
|
|
61
|
+
return [r.open, r.high, r.low, r.close].every((i) => Number.isFinite(i) && t(i));
|
|
62
62
|
}
|
|
63
|
-
function tt(
|
|
63
|
+
function tt(r) {
|
|
64
64
|
return {
|
|
65
|
-
...
|
|
66
|
-
entryMs:
|
|
67
|
-
smoothMs:
|
|
68
|
-
introMs:
|
|
69
|
-
historyRevealMs:
|
|
65
|
+
...r,
|
|
66
|
+
entryMs: r.entryMs === !1 ? 0 : r.entryMs ?? st,
|
|
67
|
+
smoothMs: r.smoothMs === !1 ? 0 : r.smoothMs ?? ot,
|
|
68
|
+
introMs: r.introMs === !1 ? 0 : r.introMs ?? et,
|
|
69
|
+
historyRevealMs: r.historyRevealMs === !1 ? 0 : r.historyRevealMs ?? it
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
-
class
|
|
72
|
+
class vt {
|
|
73
73
|
kind = "candlestick";
|
|
74
74
|
store;
|
|
75
75
|
options;
|
|
@@ -90,7 +90,7 @@ class xt {
|
|
|
90
90
|
* Crossing this boundary changes `volume` semantics (per-candle ↔ summed
|
|
91
91
|
* bucket), so the volume scale snaps rather than easing — otherwise the EMA
|
|
92
92
|
* clamps every bar to full band height for ~30 frames. */
|
|
93
|
-
#
|
|
93
|
+
#a = !1;
|
|
94
94
|
/** Series-level alpha for visibility cross-fade. Chart calls {@link setAlpha} on hide. */
|
|
95
95
|
#e = new nt({
|
|
96
96
|
initial: 1,
|
|
@@ -112,7 +112,7 @@ class xt {
|
|
|
112
112
|
/** Prepended time span: `from` = deepest new point, `to` = the boundary
|
|
113
113
|
* (the pre-prepend first point). Element stagger position is `0` at the
|
|
114
114
|
* boundary and `1` at the deepest point. */
|
|
115
|
-
#
|
|
115
|
+
#r = null;
|
|
116
116
|
/** Per-frame history-reveal directives; `null` when no reveal is in flight. */
|
|
117
117
|
#h = null;
|
|
118
118
|
/** Loading-indicator placeholder shapes handed over by the chart right
|
|
@@ -120,11 +120,11 @@ class xt {
|
|
|
120
120
|
* they were measured against) — mapped into bitmap space each frame and
|
|
121
121
|
* exposed to the reveal fn as {@link CandleIntroFrame.placeholders}.
|
|
122
122
|
* Cleared once the reveal settles. */
|
|
123
|
-
#
|
|
123
|
+
#m = null;
|
|
124
124
|
/** Body gradients keyed by `top|bottom|height` — built once at y=0..h and
|
|
125
125
|
* positioned per candle via `ctx.translate`, instead of a fresh
|
|
126
126
|
* `createLinearGradient` for every body on every frame. */
|
|
127
|
-
#
|
|
127
|
+
#c = /* @__PURE__ */ new Map();
|
|
128
128
|
constructor(t, i) {
|
|
129
129
|
this.store = t, this.options = tt({ ...yt, ...i }), this.displayedLast = t.last() ?? null;
|
|
130
130
|
}
|
|
@@ -135,14 +135,14 @@ class xt {
|
|
|
135
135
|
this.options = tt({ ...this.options, ...t });
|
|
136
136
|
}
|
|
137
137
|
getColor() {
|
|
138
|
-
return
|
|
138
|
+
return V(this.options.up.body);
|
|
139
139
|
}
|
|
140
140
|
// --- SeriesRenderer interface implementation ------------------------------
|
|
141
141
|
setData(t) {
|
|
142
|
-
const i =
|
|
143
|
-
this.store.
|
|
142
|
+
const i = J(t ?? []);
|
|
143
|
+
this.store.length === 0 && i.length > 0 && this.introWave.arm(this.options.introMs), this.store.setData(i);
|
|
144
144
|
const e = this.store.last();
|
|
145
|
-
this.displayedLast = e ?? null, this.#t = null, this.entries.clear(), this.#i = null, this.#o.finish(), this.#
|
|
145
|
+
this.displayedLast = e ?? null, this.#t = null, this.entries.clear(), this.#i = null, this.#o.finish(), this.#r = null, this.#m = null;
|
|
146
146
|
}
|
|
147
147
|
appendPoint(t) {
|
|
148
148
|
const i = t, e = Q(i.time), o = { ...i, time: e };
|
|
@@ -163,16 +163,16 @@ class xt {
|
|
|
163
163
|
#u(t, i) {
|
|
164
164
|
const e = this.options.historyRevealMs;
|
|
165
165
|
if (!(this.options.historyReveal === "none" || e <= 0 || i === void 0)) {
|
|
166
|
-
if (this.#o.active && this.#
|
|
167
|
-
this.#
|
|
166
|
+
if (this.#o.active && this.#r !== null) {
|
|
167
|
+
this.#r = { from: Math.min(this.#r.from, t), to: this.#r.to };
|
|
168
168
|
return;
|
|
169
169
|
}
|
|
170
|
-
this.#
|
|
170
|
+
this.#r = { from: t, to: i }, this.#o.arm(e);
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
setHistoryHandoff(t) {
|
|
174
174
|
const i = this.store.first()?.time;
|
|
175
|
-
i !== void 0 && (this.#
|
|
175
|
+
i !== void 0 && (this.#m = { bars: t, anchorTime: i });
|
|
176
176
|
}
|
|
177
177
|
updateLastPoint(t) {
|
|
178
178
|
const i = t, e = Q(i.time), o = { ...i, time: e };
|
|
@@ -185,7 +185,7 @@ class xt {
|
|
|
185
185
|
let n = this.#t;
|
|
186
186
|
if (n === null) {
|
|
187
187
|
const l = this.displayedLast ?? o;
|
|
188
|
-
n = new
|
|
188
|
+
n = new bt(l), this.#t = n;
|
|
189
189
|
}
|
|
190
190
|
n.retarget(o, { settleMs: h });
|
|
191
191
|
}
|
|
@@ -203,7 +203,7 @@ class xt {
|
|
|
203
203
|
return !0;
|
|
204
204
|
}
|
|
205
205
|
getLayerColors() {
|
|
206
|
-
return [
|
|
206
|
+
return [V(this.options.up.body)];
|
|
207
207
|
}
|
|
208
208
|
applyTheme(t, i) {
|
|
209
209
|
this.updateOptions({
|
|
@@ -223,7 +223,7 @@ class xt {
|
|
|
223
223
|
* fully-settled entrance entries. Called from `render()` once per frame.
|
|
224
224
|
*/
|
|
225
225
|
tickAnimations(t) {
|
|
226
|
-
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.#m = null), this.#e.tick(t);
|
|
227
227
|
const i = this.#t;
|
|
228
228
|
if (i !== null) {
|
|
229
229
|
const o = i.tick(t);
|
|
@@ -276,8 +276,8 @@ class xt {
|
|
|
276
276
|
const t = this.store.getAll();
|
|
277
277
|
return t.length >= 2 ? t[t.length - 2] : null;
|
|
278
278
|
}
|
|
279
|
-
sampleTimes(t) {
|
|
280
|
-
return this.store.getAll()
|
|
279
|
+
sampleTimes(t, i = "start") {
|
|
280
|
+
return mt(this.store.getAll(), { maxCount: t, from: i }).map((e) => e.time);
|
|
281
281
|
}
|
|
282
282
|
getVisibleDataPoints(t, i) {
|
|
283
283
|
return this.store.getVisibleData(t, i);
|
|
@@ -292,17 +292,17 @@ class xt {
|
|
|
292
292
|
render(t) {
|
|
293
293
|
this.tickAnimations(performance.now());
|
|
294
294
|
const { scope: i, timeScale: e, yScale: o, dataInterval: h } = t, { context: n, horizontalPixelRatio: l } = i, p = e.getRange();
|
|
295
|
-
let
|
|
296
|
-
const
|
|
297
|
-
if (
|
|
295
|
+
let c = this.store.getVisibleData(p.from, p.to);
|
|
296
|
+
const g = i.mediaSize.width, w = c.length > g * 2;
|
|
297
|
+
if (w && (c = at(c, Math.round(g * 1.5))), o.getTransform() !== null && (c = c.filter((a) => q(a, (m) => o.isPlottable(m)))), c.length === 0) return;
|
|
298
298
|
const S = this.displayedLast;
|
|
299
|
-
if (!
|
|
300
|
-
const
|
|
301
|
-
|
|
299
|
+
if (!w && S !== null) {
|
|
300
|
+
const a = c.length - 1;
|
|
301
|
+
c[a].time === S.time && (c = [...c.slice(0, a), S]);
|
|
302
302
|
}
|
|
303
303
|
if (this.#n = null, this.#l = null, this.introWave.active) {
|
|
304
|
-
const
|
|
305
|
-
this.#l = p, this.#n =
|
|
304
|
+
const a = this.options.introAnimation ?? gt;
|
|
305
|
+
this.#l = p, this.#n = a({
|
|
306
306
|
progress: this.introWave.linear(),
|
|
307
307
|
// Plot-area extent, not the canvas bitmap — the canvas also carries
|
|
308
308
|
// the axis strips, so a width-based front (wipeIntro) would overshoot
|
|
@@ -310,114 +310,114 @@ class xt {
|
|
|
310
310
|
width: e.getMediaWidth() * i.horizontalPixelRatio,
|
|
311
311
|
height: o.getMediaHeight() * i.verticalPixelRatio,
|
|
312
312
|
range: p,
|
|
313
|
-
timeToX: (
|
|
313
|
+
timeToX: (m) => e.timeToBitmapX(m)
|
|
314
314
|
});
|
|
315
315
|
}
|
|
316
316
|
this.#h = null;
|
|
317
|
-
const u = this.#
|
|
317
|
+
const u = this.#r;
|
|
318
318
|
if (this.#o.active && u !== null) {
|
|
319
|
-
const
|
|
320
|
-
if (
|
|
321
|
-
let
|
|
322
|
-
const
|
|
323
|
-
if (
|
|
324
|
-
const P = e.timeToBitmapX(
|
|
325
|
-
|
|
319
|
+
const a = this.options.historyReveal ?? xt;
|
|
320
|
+
if (a !== "none") {
|
|
321
|
+
let m;
|
|
322
|
+
const y = this.#m;
|
|
323
|
+
if (y !== null && y.bars.length > 0) {
|
|
324
|
+
const P = e.timeToBitmapX(y.anchorTime);
|
|
325
|
+
m = y.bars.map((k) => ({
|
|
326
326
|
x: P - k.offsetX * i.horizontalPixelRatio,
|
|
327
327
|
y: k.y * i.verticalPixelRatio,
|
|
328
328
|
halfHeight: k.halfHeight * i.verticalPixelRatio,
|
|
329
329
|
width: k.width * i.horizontalPixelRatio
|
|
330
330
|
}));
|
|
331
331
|
}
|
|
332
|
-
this.#h =
|
|
332
|
+
this.#h = a({
|
|
333
333
|
progress: this.#o.linear(),
|
|
334
334
|
width: Math.abs(e.timeToBitmapX(u.to) - e.timeToBitmapX(u.from)),
|
|
335
335
|
height: o.getMediaHeight() * i.verticalPixelRatio,
|
|
336
336
|
range: u,
|
|
337
337
|
timeToX: (P) => e.timeToBitmapX(P),
|
|
338
|
-
placeholders:
|
|
338
|
+
placeholders: m
|
|
339
339
|
});
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
let W = null;
|
|
343
343
|
if (this.entries.size > 0) {
|
|
344
|
-
const
|
|
345
|
-
for (const
|
|
346
|
-
const P = this.entries.get(
|
|
347
|
-
if (P === void 0 ||
|
|
348
|
-
const k =
|
|
349
|
-
|
|
344
|
+
const a = this.options.entryMs, m = performance.now();
|
|
345
|
+
for (const y of c) {
|
|
346
|
+
const P = this.entries.get(y.time);
|
|
347
|
+
if (P === void 0 || a <= 0) continue;
|
|
348
|
+
const k = m - P.startTime, H = Math.min(1, Math.max(0, k / a));
|
|
349
|
+
H >= 1 || (W === null && (W = /* @__PURE__ */ new Map()), W.set(y.time, rt(H)));
|
|
350
350
|
}
|
|
351
351
|
}
|
|
352
|
-
const X = e.barWidthBitmap(h), b = Math.round(30 * l),
|
|
353
|
-
let
|
|
354
|
-
(
|
|
355
|
-
const R = Math.floor(
|
|
356
|
-
if (
|
|
357
|
-
const
|
|
358
|
-
n.save(), n.beginPath(), n.rect(
|
|
352
|
+
const X = e.barWidthBitmap(h), b = Math.round(30 * l), v = c.length <= 2 ? Math.min(b, X) : X, f = Math.max(1, Math.round(l));
|
|
353
|
+
let Y = Math.max(1, Math.round(v * this.options.bodyWidthRatio));
|
|
354
|
+
(Y & 1) !== (f & 1) && (Y = Y + 1 < v || Y === 1 ? Y + 1 : Y - 1);
|
|
355
|
+
const R = Math.floor(Y / 2), M = this.#n?.clip;
|
|
356
|
+
if (M !== void 0) {
|
|
357
|
+
const a = M.fromX ?? 0, m = M.toX ?? i.bitmapSize.width;
|
|
358
|
+
n.save(), n.beginPath(), n.rect(a, 0, Math.max(0, m - a), i.bitmapSize.height), n.clip();
|
|
359
359
|
}
|
|
360
360
|
const T = this.#h?.clip;
|
|
361
361
|
let A = !1;
|
|
362
362
|
if (T !== void 0 && u !== null) {
|
|
363
|
-
const
|
|
364
|
-
n.save(), n.beginPath(), n.rect(
|
|
363
|
+
const a = e.timeToBitmapX(u.to), m = Math.abs(a - e.timeToBitmapX(u.from)), y = v, P = T.fromX ?? 0, k = T.toX ?? m;
|
|
364
|
+
n.save(), n.beginPath(), n.rect(a - k - y, 0, Math.max(0, k - P + y), i.bitmapSize.height), n.rect(a, 0, Math.max(0, i.bitmapSize.width - a), i.bitmapSize.height), n.clip(), A = !0;
|
|
365
365
|
}
|
|
366
|
-
const s =
|
|
367
|
-
this.#
|
|
366
|
+
const s = w !== this.#a;
|
|
367
|
+
this.#a = w;
|
|
368
368
|
const d = Math.round(o.getMediaHeight() * i.verticalPixelRatio);
|
|
369
369
|
this.drawVolume({
|
|
370
370
|
ctx: n,
|
|
371
|
-
data:
|
|
371
|
+
data: c,
|
|
372
372
|
timeScale: e,
|
|
373
373
|
chartHeight: d,
|
|
374
|
-
barWidth:
|
|
374
|
+
barWidth: v,
|
|
375
375
|
wickWidth: f,
|
|
376
376
|
entranceByTime: W,
|
|
377
377
|
snapVolScale: s,
|
|
378
|
-
radius: (this.options.cornerRadius ??
|
|
378
|
+
radius: (this.options.cornerRadius ?? $) * l
|
|
379
379
|
});
|
|
380
|
-
const
|
|
381
|
-
let
|
|
382
|
-
for (let
|
|
383
|
-
const
|
|
384
|
-
if (N(
|
|
385
|
-
B.push(
|
|
380
|
+
const x = [], C = [], B = [];
|
|
381
|
+
let L = null;
|
|
382
|
+
for (let a = 0; a < c.length; a++) {
|
|
383
|
+
const m = c[a];
|
|
384
|
+
if (N(m.open) || N(m.close) || N(m.high) || N(m.low)) {
|
|
385
|
+
B.push(a), L === null && (L = m);
|
|
386
386
|
continue;
|
|
387
387
|
}
|
|
388
|
-
|
|
388
|
+
m.close >= m.open ? x.push(m) : C.push(m);
|
|
389
389
|
}
|
|
390
|
-
|
|
390
|
+
L !== null && ht(this, "candlestick", B, `time ${L.time}`);
|
|
391
391
|
const E = {
|
|
392
|
-
painter:
|
|
392
|
+
painter: pt(this.options.candlePainter),
|
|
393
393
|
env: {
|
|
394
394
|
ctx: n,
|
|
395
395
|
theme: t.theme,
|
|
396
396
|
horizontalPixelRatio: l,
|
|
397
397
|
verticalPixelRatio: i.verticalPixelRatio
|
|
398
398
|
},
|
|
399
|
-
radius: (this.options.cornerRadius ??
|
|
399
|
+
radius: (this.options.cornerRadius ?? $) * l
|
|
400
400
|
}, D = {
|
|
401
401
|
ctx: n,
|
|
402
402
|
timeScale: e,
|
|
403
403
|
yScale: o,
|
|
404
404
|
halfBody: R,
|
|
405
|
-
bodyWidth:
|
|
405
|
+
bodyWidth: Y,
|
|
406
406
|
wickWidth: f,
|
|
407
407
|
entranceByTime: W,
|
|
408
408
|
candlePass: E
|
|
409
409
|
};
|
|
410
410
|
this.drawCandles({
|
|
411
411
|
...D,
|
|
412
|
-
candles:
|
|
412
|
+
candles: x,
|
|
413
413
|
body: this.options.up.body,
|
|
414
414
|
wickColor: this.options.up.wick
|
|
415
415
|
}), this.drawCandles({
|
|
416
416
|
...D,
|
|
417
|
-
candles:
|
|
417
|
+
candles: C,
|
|
418
418
|
body: this.options.down.body,
|
|
419
419
|
wickColor: this.options.down.wick
|
|
420
|
-
}), A && n.restore(),
|
|
420
|
+
}), A && n.restore(), M !== void 0 && n.restore();
|
|
421
421
|
}
|
|
422
422
|
/**
|
|
423
423
|
* Apply the intro's per-element directive to one element's settled (or
|
|
@@ -425,10 +425,10 @@ class xt {
|
|
|
425
425
|
* is in flight this frame.
|
|
426
426
|
*/
|
|
427
427
|
introTransform(t) {
|
|
428
|
-
const i = this.#h?.element, e = this.#
|
|
428
|
+
const i = this.#h?.element, e = this.#r;
|
|
429
429
|
if (i !== void 0 && e !== null && t.time < e.to) {
|
|
430
|
-
const
|
|
431
|
-
return this.#p(
|
|
430
|
+
const c = e.to - e.from, g = c > 0 ? F((e.to - t.time) / c, 0, 1) : 0, w = i({ ...t, position: g, progress: this.#o.progressAt(g) });
|
|
431
|
+
return this.#p(w, t);
|
|
432
432
|
}
|
|
433
433
|
const o = this.#n?.element, h = this.#l;
|
|
434
434
|
if (o === void 0 || h === null) return null;
|
|
@@ -458,35 +458,35 @@ class xt {
|
|
|
458
458
|
wickWidth: n,
|
|
459
459
|
entranceByTime: l,
|
|
460
460
|
snapVolScale: p,
|
|
461
|
-
radius:
|
|
461
|
+
radius: c
|
|
462
462
|
}) {
|
|
463
|
-
let
|
|
463
|
+
let g = 0;
|
|
464
464
|
for (const f of i)
|
|
465
|
-
Number.isFinite(f.volume) && f.volume >
|
|
466
|
-
if (
|
|
465
|
+
Number.isFinite(f.volume) && f.volume > g && (g = f.volume);
|
|
466
|
+
if (g === 0) {
|
|
467
467
|
this.#i = null, this.#s = !0;
|
|
468
468
|
return;
|
|
469
469
|
}
|
|
470
|
-
this.#i === null || p ? this.#i =
|
|
471
|
-
const
|
|
470
|
+
this.#i === null || p ? this.#i = g : this.#i += (g - this.#i) * dt, this.#s = Math.abs(g - this.#i) <= g * ft;
|
|
471
|
+
const w = this.#i, S = o * 0.2;
|
|
472
472
|
let u = Math.max(1, h - 2);
|
|
473
473
|
(u & 1) !== (n & 1) && (u = u > 1 ? u - 1 : 2);
|
|
474
|
-
const W = Math.floor(u / 2), X = K(
|
|
474
|
+
const W = Math.floor(u / 2), X = K(V(this.options.up.body), 0.2), b = K(V(this.options.down.body), 0.2), v = this.options.entryAnimation ?? "unfold";
|
|
475
475
|
for (const f of i) {
|
|
476
476
|
if (!Number.isFinite(f.volume) || f.volume <= 0) continue;
|
|
477
|
-
const
|
|
477
|
+
const Y = f.volume, R = e.timeToBitmapX(f.time), M = Math.min(S, Math.max(1, Y / w * S)), T = f.close >= f.open;
|
|
478
478
|
t.fillStyle = T ? X : b;
|
|
479
479
|
const A = l?.get(f.time) ?? 1;
|
|
480
|
-
let s = { x: R - W, topY: o -
|
|
481
|
-
if (A < 1 &&
|
|
482
|
-
const
|
|
480
|
+
let s = { x: R - W, topY: o - M, bottomY: o, alpha: 1 };
|
|
481
|
+
if (A < 1 && v !== "none") {
|
|
482
|
+
const x = _(A, v, {
|
|
483
483
|
x: s.x,
|
|
484
484
|
barWidth: u,
|
|
485
485
|
anchorY: o,
|
|
486
486
|
topY: s.topY,
|
|
487
487
|
bottomY: s.bottomY
|
|
488
488
|
});
|
|
489
|
-
s = { x:
|
|
489
|
+
s = { x: x.x, topY: x.topY, bottomY: x.bottomY, alpha: x.alpha };
|
|
490
490
|
}
|
|
491
491
|
const d = this.introTransform({
|
|
492
492
|
element: "volume",
|
|
@@ -503,7 +503,7 @@ class xt {
|
|
|
503
503
|
y: s.topY,
|
|
504
504
|
width: u,
|
|
505
505
|
height: Math.max(1, s.bottomY - s.topY),
|
|
506
|
-
radius:
|
|
506
|
+
radius: c,
|
|
507
507
|
corners: j
|
|
508
508
|
});
|
|
509
509
|
continue;
|
|
@@ -513,7 +513,7 @@ class xt {
|
|
|
513
513
|
y: s.topY,
|
|
514
514
|
width: u,
|
|
515
515
|
height: Math.max(1, s.bottomY - s.topY),
|
|
516
|
-
radius:
|
|
516
|
+
radius: c,
|
|
517
517
|
corners: j
|
|
518
518
|
}), t.restore();
|
|
519
519
|
}
|
|
@@ -527,25 +527,25 @@ class xt {
|
|
|
527
527
|
bodyWidth: n,
|
|
528
528
|
wickWidth: l,
|
|
529
529
|
body: p,
|
|
530
|
-
wickColor:
|
|
531
|
-
entranceByTime:
|
|
532
|
-
candlePass:
|
|
530
|
+
wickColor: c,
|
|
531
|
+
entranceByTime: g,
|
|
532
|
+
candlePass: w
|
|
533
533
|
}) {
|
|
534
534
|
if (i.length === 0) return;
|
|
535
|
-
const S = this.options.entryAnimation ?? "unfold", u = n + 2, W =
|
|
536
|
-
t.fillStyle =
|
|
535
|
+
const S = this.options.entryAnimation ?? "unfold", u = n + 2, W = w.env.theme.axis.textColor ?? "#787b86";
|
|
536
|
+
t.fillStyle = c;
|
|
537
537
|
for (const b of i) {
|
|
538
|
-
const
|
|
539
|
-
let A = !1, s = { x: T, topY: R, bottomY:
|
|
540
|
-
if (
|
|
541
|
-
const
|
|
538
|
+
const v = g?.get(b.time) ?? 1, f = e.timeToBitmapX(b.time), Y = o.valueToBitmapY(b.open), R = o.valueToBitmapY(b.high), M = o.valueToBitmapY(b.low), T = f - Math.floor(l / 2);
|
|
539
|
+
let A = !1, s = { x: T, topY: R, bottomY: M, alpha: 1 };
|
|
540
|
+
if (v < 1 && S !== "none") {
|
|
541
|
+
const C = _(v, S, {
|
|
542
542
|
x: T,
|
|
543
543
|
barWidth: u,
|
|
544
|
-
anchorY:
|
|
544
|
+
anchorY: Y,
|
|
545
545
|
topY: R,
|
|
546
|
-
bottomY:
|
|
546
|
+
bottomY: M
|
|
547
547
|
});
|
|
548
|
-
s = { x:
|
|
548
|
+
s = { x: C.x, topY: C.topY, bottomY: C.bottomY, alpha: C.alpha }, A = !0;
|
|
549
549
|
}
|
|
550
550
|
const d = this.introTransform({
|
|
551
551
|
element: "wick",
|
|
@@ -553,55 +553,55 @@ class xt {
|
|
|
553
553
|
x: s.x,
|
|
554
554
|
topY: s.topY,
|
|
555
555
|
bottomY: s.bottomY,
|
|
556
|
-
anchorY:
|
|
556
|
+
anchorY: Y,
|
|
557
557
|
barWidth: u
|
|
558
558
|
});
|
|
559
|
-
let
|
|
560
|
-
if (d !== null && (s = { x: d.x, topY: d.topY, bottomY: d.bottomY, alpha: s.alpha * d.alpha },
|
|
561
|
-
t.fillRect(T, R, l,
|
|
559
|
+
let x = 0;
|
|
560
|
+
if (d !== null && (s = { x: d.x, topY: d.topY, bottomY: d.bottomY, alpha: s.alpha * d.alpha }, x = d.tint ?? 0, A = !0), !A) {
|
|
561
|
+
t.fillRect(T, R, l, M - R);
|
|
562
562
|
continue;
|
|
563
563
|
}
|
|
564
|
-
t.save(), t.globalAlpha = s.alpha,
|
|
564
|
+
t.save(), t.globalAlpha = s.alpha, x > 0 && (t.fillStyle = G(c, W, x)), t.fillRect(s.x, s.topY, l, Math.max(1, s.bottomY - s.topY)), t.restore();
|
|
565
565
|
}
|
|
566
566
|
const X = Array.isArray(p);
|
|
567
567
|
for (const b of i) {
|
|
568
|
-
const
|
|
569
|
-
let s = f - h, d =
|
|
570
|
-
if (
|
|
571
|
-
const
|
|
568
|
+
const v = g?.get(b.time) ?? 1, f = e.timeToBitmapX(b.time), Y = o.valueToBitmapY(b.open), R = o.valueToBitmapY(b.close), M = Math.min(Y, R), T = Math.max(Y, R), A = Math.max(1, T - M);
|
|
569
|
+
let s = f - h, d = M, x = T, C = 1, B = !1;
|
|
570
|
+
if (v < 1 && S !== "none") {
|
|
571
|
+
const O = _(v, S, {
|
|
572
572
|
x: s,
|
|
573
573
|
barWidth: u,
|
|
574
|
-
anchorY:
|
|
575
|
-
topY:
|
|
574
|
+
anchorY: Y,
|
|
575
|
+
topY: M,
|
|
576
576
|
bottomY: T
|
|
577
577
|
});
|
|
578
|
-
s =
|
|
578
|
+
s = O.x, d = O.topY, x = O.bottomY, C = O.alpha, B = !0;
|
|
579
579
|
}
|
|
580
|
-
const
|
|
580
|
+
const L = this.introTransform({
|
|
581
581
|
element: "body",
|
|
582
582
|
time: b.time,
|
|
583
583
|
x: s,
|
|
584
584
|
topY: d,
|
|
585
|
-
bottomY:
|
|
586
|
-
anchorY:
|
|
585
|
+
bottomY: x,
|
|
586
|
+
anchorY: Y,
|
|
587
587
|
barWidth: u
|
|
588
588
|
});
|
|
589
589
|
let E = 0;
|
|
590
|
-
|
|
591
|
-
const D = B ? Math.max(1,
|
|
590
|
+
L !== null && (s = L.x, d = L.topY, x = L.bottomY, C *= L.alpha, E = L.tint ?? 0, B = !0);
|
|
591
|
+
const D = B ? Math.max(1, x - d) : A;
|
|
592
592
|
B && t.save();
|
|
593
|
-
const
|
|
594
|
-
t.fillStyle = P, B && (t.globalAlpha =
|
|
595
|
-
const k =
|
|
596
|
-
|
|
593
|
+
const a = Array.isArray(p) ? p[0] : p, m = E > 0 ? G(a, W, E) : a, y = X && D > 2 && E <= 0, P = y ? this.#d(t, p, D) : m;
|
|
594
|
+
t.fillStyle = P, B && (t.globalAlpha = C), y && t.translate(0, d);
|
|
595
|
+
const k = y ? 0 : d, H = F(w.radius, 0, Math.min(n, D) / 2);
|
|
596
|
+
H < 1 && !this.options.candlePainter ? t.fillRect(s, k, n, D) : w.painter(w.env, {
|
|
597
597
|
geom: { x: s, y: k, width: n, height: D },
|
|
598
598
|
fillStyle: P,
|
|
599
|
-
color:
|
|
600
|
-
corners:
|
|
601
|
-
radius:
|
|
602
|
-
progress:
|
|
599
|
+
color: m,
|
|
600
|
+
corners: Yt,
|
|
601
|
+
radius: H,
|
|
602
|
+
progress: v,
|
|
603
603
|
isBullish: b.close >= b.open
|
|
604
|
-
}),
|
|
604
|
+
}), y && t.translate(0, -d), B && t.restore();
|
|
605
605
|
}
|
|
606
606
|
}
|
|
607
607
|
/**
|
|
@@ -612,52 +612,52 @@ class xt {
|
|
|
612
612
|
* continuously, and a full clear is cheaper than an eviction policy.
|
|
613
613
|
*/
|
|
614
614
|
#d(t, i, e) {
|
|
615
|
-
const o = Math.max(3, Math.round(e)), h = `${i[0]}|${i[1]}|${o}`, n = this.#
|
|
615
|
+
const o = Math.max(3, Math.round(e)), h = `${i[0]}|${i[1]}|${o}`, n = this.#c.get(h);
|
|
616
616
|
if (n !== void 0) return n;
|
|
617
|
-
this.#
|
|
617
|
+
this.#c.size >= 512 && this.#c.clear();
|
|
618
618
|
const l = t.createLinearGradient(0, 0, 0, o);
|
|
619
|
-
return l.addColorStop(0, i[0]), l.addColorStop(1, i[1]), this.#
|
|
619
|
+
return l.addColorStop(0, i[0]), l.addColorStop(1, i[1]), this.#c.set(h, l), l;
|
|
620
620
|
}
|
|
621
621
|
}
|
|
622
|
-
function
|
|
622
|
+
function _(r, t, i) {
|
|
623
623
|
switch (t) {
|
|
624
624
|
case "none":
|
|
625
625
|
return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha: 1 };
|
|
626
626
|
case "fade":
|
|
627
|
-
return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha:
|
|
627
|
+
return { x: i.x, topY: i.topY, bottomY: i.bottomY, alpha: r };
|
|
628
628
|
case "unfold":
|
|
629
629
|
return {
|
|
630
630
|
x: i.x,
|
|
631
|
-
topY: z(i.anchorY, i.topY,
|
|
632
|
-
bottomY: z(i.anchorY, i.bottomY,
|
|
631
|
+
topY: z(i.anchorY, i.topY, r),
|
|
632
|
+
bottomY: z(i.anchorY, i.bottomY, r),
|
|
633
633
|
alpha: 1
|
|
634
634
|
};
|
|
635
635
|
case "slide":
|
|
636
636
|
return {
|
|
637
|
-
x: i.x + (1 -
|
|
637
|
+
x: i.x + (1 - r) * i.barWidth,
|
|
638
638
|
topY: i.topY,
|
|
639
639
|
bottomY: i.bottomY,
|
|
640
|
-
alpha:
|
|
640
|
+
alpha: r
|
|
641
641
|
};
|
|
642
642
|
case "fade-unfold":
|
|
643
643
|
return {
|
|
644
644
|
x: i.x,
|
|
645
|
-
topY: z(i.anchorY, i.topY,
|
|
646
|
-
bottomY: z(i.anchorY, i.bottomY,
|
|
647
|
-
alpha:
|
|
645
|
+
topY: z(i.anchorY, i.topY, r),
|
|
646
|
+
bottomY: z(i.anchorY, i.bottomY, r),
|
|
647
|
+
alpha: r
|
|
648
648
|
};
|
|
649
649
|
}
|
|
650
650
|
}
|
|
651
|
-
const
|
|
651
|
+
const Ht = {
|
|
652
652
|
type: "candlestick",
|
|
653
653
|
xTypes: ["time"],
|
|
654
|
-
create: ({ theme:
|
|
655
|
-
up: { ...
|
|
656
|
-
down: { ...
|
|
654
|
+
create: ({ theme: r }, t) => new vt(new lt(), {
|
|
655
|
+
up: { ...r.candlestick.up },
|
|
656
|
+
down: { ...r.candlestick.down },
|
|
657
657
|
...t
|
|
658
658
|
})
|
|
659
659
|
};
|
|
660
660
|
export {
|
|
661
|
-
|
|
662
|
-
|
|
661
|
+
vt as CandlestickRenderer,
|
|
662
|
+
Ht as CandlestickSeriesDef
|
|
663
663
|
};
|