chartai 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chart-library.d.ts +1 -0
- package/dist/chart-library.d.ts.map +1 -1
- package/dist/chart-library.js +43 -11
- package/dist/chart-library.min.js +1 -1
- package/dist/charts/area.js +1 -1
- package/dist/charts/area.min.js +1 -1
- package/dist/charts/bar.js +1 -1
- package/dist/charts/bar.min.js +1 -1
- package/dist/charts/boids.js +9 -9
- package/dist/charts/boids.min.js +1 -1
- package/dist/charts/candlestick.js +5 -127
- package/dist/charts/candlestick.min.js +1 -32
- package/dist/charts/experimental/baseline-area.js +70 -0
- package/dist/charts/experimental/baseline-area.min.js +1 -0
- package/dist/charts/experimental/bubble.js +48 -0
- package/dist/charts/experimental/bubble.min.js +1 -0
- package/dist/charts/experimental/error-band.js +111 -0
- package/dist/charts/experimental/error-band.min.js +1 -0
- package/dist/charts/experimental/heatmap.js +69 -0
- package/dist/charts/experimental/heatmap.min.js +1 -0
- package/dist/charts/experimental/histogram.js +139 -0
- package/dist/charts/experimental/histogram.min.js +7 -0
- package/dist/charts/experimental/ohlc.js +132 -0
- package/dist/charts/experimental/ohlc.min.js +32 -0
- package/dist/charts/experimental/step.js +67 -0
- package/dist/charts/experimental/step.min.js +1 -0
- package/dist/charts/experimental/waterfall.js +121 -0
- package/dist/charts/experimental/waterfall.min.js +7 -0
- package/dist/charts/line.js +1 -1
- package/dist/charts/line.min.js +1 -1
- package/dist/charts/scatter.js +1 -1
- package/dist/charts/scatter.min.js +1 -1
- package/dist/{chunk-e7d3zgw5.min.js → chunk-0eh4rzy9.min.js} +1 -1
- package/dist/{chunk-a27be8p9.js → chunk-1ngxm8t2.js} +25 -1
- package/dist/chunk-50bcv2hw.min.js +2 -0
- package/dist/{chunk-dmaxrg6s.min.js → chunk-64q9a7nw.min.js} +1 -1
- package/dist/{chunk-me3qaz3m.min.js → chunk-bbyt23tw.min.js} +1 -1
- package/dist/chunk-cbydth3q.min.js +2 -0
- package/dist/chunk-cvtt04m6.min.js +2 -0
- package/dist/chunk-g2qmt43n.min.js +33 -0
- package/dist/{chunk-1p45ex5n.min.js → chunk-gm0d4cgx.min.js} +2 -2
- package/dist/chunk-mmsy3yqt.js +27 -0
- package/dist/{chunk-g6m56ptf.js → chunk-n8ew0z0e.js} +38 -10
- package/dist/chunk-t0kdz02m.js +129 -0
- package/dist/{chunk-bfyv7z27.min.js → chunk-wdfq2fpx.min.js} +1 -1
- package/dist/gpu-worker.js +8 -3
- package/dist/gpu-worker.min.js +1 -1
- package/dist/plugins/experimental/annotations.js +164 -0
- package/dist/plugins/experimental/annotations.min.js +1 -0
- package/dist/plugins/experimental/crosshair.js +82 -0
- package/dist/plugins/experimental/crosshair.min.js +1 -0
- package/dist/plugins/experimental/minimap.js +190 -0
- package/dist/plugins/experimental/minimap.min.js +1 -0
- package/dist/plugins/experimental/range-selector.js +220 -0
- package/dist/plugins/experimental/range-selector.min.js +1 -0
- package/dist/plugins/experimental/ruler.js +434 -0
- package/dist/plugins/experimental/ruler.min.js +59 -0
- package/dist/plugins/experimental/stats.js +229 -0
- package/dist/plugins/experimental/stats.min.js +8 -0
- package/dist/plugins/experimental/threshold.js +96 -0
- package/dist/plugins/experimental/threshold.min.js +1 -0
- package/dist/plugins/experimental/tooltip-pin.js +177 -0
- package/dist/plugins/experimental/tooltip-pin.min.js +1 -0
- package/dist/plugins/experimental/watermark.js +76 -0
- package/dist/plugins/experimental/watermark.min.js +1 -0
- package/dist/plugins/hover.d.ts.map +1 -1
- package/dist/plugins/hover.js +12 -30
- package/dist/plugins/hover.min.js +1 -1
- package/dist/plugins/labels-panel.js +3 -3
- package/dist/plugins/labels-panel.min.js +1 -1
- package/dist/plugins/labels.d.ts.map +1 -1
- package/dist/plugins/labels.js +3 -3
- package/dist/plugins/labels.min.js +1 -1
- package/dist/plugins/legend.d.ts.map +1 -1
- package/dist/plugins/legend.js +87 -16
- package/dist/plugins/legend.min.js +23 -7
- package/dist/plugins/zoom.js +2 -2
- package/dist/plugins/zoom.min.js +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker-inline.d.ts +1 -1
- package/dist/worker-inline.d.ts.map +1 -1
- package/package.json +1 -1
- package/readme.md +6 -3
- package/dist/chunk-94kc81rr.min.js +0 -2
- package/dist/chunk-qr6mweck.min.js +0 -2
- /package/dist/{chunk-m17t3vjq.js → chunk-5gtx3pza.js} +0 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_FONT
|
|
3
|
+
} from "../../chunk-1ngxm8t2.js";
|
|
4
|
+
import {
|
|
5
|
+
MARGIN
|
|
6
|
+
} from "../../chunk-831dem4f.js";
|
|
7
|
+
import {
|
|
8
|
+
ChartManager
|
|
9
|
+
} from "../../chunk-n8ew0z0e.js";
|
|
10
|
+
import"../../chunk-93yrr7er.js";
|
|
11
|
+
import"../../chunk-5gtx3pza.js";
|
|
12
|
+
|
|
13
|
+
// src/plugins/experimental/stats.ts
|
|
14
|
+
var states = new WeakMap;
|
|
15
|
+
function computeStats(values) {
|
|
16
|
+
if (values.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
let min = Infinity, max = -Infinity, sum = 0;
|
|
19
|
+
for (const v of values) {
|
|
20
|
+
if (v < min)
|
|
21
|
+
min = v;
|
|
22
|
+
if (v > max)
|
|
23
|
+
max = v;
|
|
24
|
+
sum += v;
|
|
25
|
+
}
|
|
26
|
+
const mean = sum / values.length;
|
|
27
|
+
let variance = 0;
|
|
28
|
+
for (const v of values) {
|
|
29
|
+
const d = v - mean;
|
|
30
|
+
variance += d * d;
|
|
31
|
+
}
|
|
32
|
+
const stddev = Math.sqrt(variance / values.length);
|
|
33
|
+
return { min, max, mean, stddev, count: values.length };
|
|
34
|
+
}
|
|
35
|
+
function updateOverlay(chart, state) {
|
|
36
|
+
const { overlay, header, body } = state;
|
|
37
|
+
const dark = ChartManager.isDark;
|
|
38
|
+
const cfg = chart.config;
|
|
39
|
+
const bgColor = cfg.bgColor ?? (dark ? [0.11, 0.11, 0.12] : [0.98, 0.98, 0.98]);
|
|
40
|
+
const rgb = bgColor.map((c) => Math.round(c * 255)).join(",");
|
|
41
|
+
const panelBg = dark ? `rgba(${rgb},0.92)` : "rgba(255,255,255,0.95)";
|
|
42
|
+
const border = dark ? "rgba(255,255,255,0.14)" : "rgba(0,0,0,0.10)";
|
|
43
|
+
const text = cfg.textColor ?? (dark ? "#c0c0c0" : "#333333");
|
|
44
|
+
const muted = dark ? "#777" : "#aaa";
|
|
45
|
+
const font = cfg.fontFamily ?? DEFAULT_FONT;
|
|
46
|
+
const precision = cfg.statsPrecision ?? 2;
|
|
47
|
+
const fmt = cfg.formatValue ?? ((n) => n.toFixed(precision));
|
|
48
|
+
const pos = cfg.statsPosition ?? "top-left";
|
|
49
|
+
overlay.style.display = "block";
|
|
50
|
+
overlay.style.position = "absolute";
|
|
51
|
+
overlay.style.pointerEvents = "auto";
|
|
52
|
+
overlay.style.zIndex = "15";
|
|
53
|
+
overlay.style.background = panelBg;
|
|
54
|
+
overlay.style.border = `1px solid ${border}`;
|
|
55
|
+
overlay.style.borderRadius = "6px";
|
|
56
|
+
overlay.style.padding = "7px 10px";
|
|
57
|
+
overlay.style.fontFamily = font;
|
|
58
|
+
overlay.style.fontSize = "11px";
|
|
59
|
+
overlay.style.color = text;
|
|
60
|
+
overlay.style.minWidth = "100px";
|
|
61
|
+
overlay.style.userSelect = "none";
|
|
62
|
+
if (!state.dragOffset) {
|
|
63
|
+
const m = MARGIN;
|
|
64
|
+
const pad = 6;
|
|
65
|
+
if (state.customPos) {
|
|
66
|
+
overlay.style.top = `${state.customPos.y}px`;
|
|
67
|
+
overlay.style.left = `${state.customPos.x}px`;
|
|
68
|
+
overlay.style.right = "auto";
|
|
69
|
+
overlay.style.bottom = "auto";
|
|
70
|
+
} else {
|
|
71
|
+
overlay.style.right = "auto";
|
|
72
|
+
overlay.style.bottom = "auto";
|
|
73
|
+
overlay.style.top = "auto";
|
|
74
|
+
overlay.style.left = "auto";
|
|
75
|
+
if (pos === "top-left") {
|
|
76
|
+
overlay.style.top = `${m.top + pad}px`;
|
|
77
|
+
overlay.style.left = `${m.left + pad}px`;
|
|
78
|
+
}
|
|
79
|
+
if (pos === "top-right") {
|
|
80
|
+
overlay.style.top = `${m.top + pad}px`;
|
|
81
|
+
overlay.style.right = `${m.right + pad}px`;
|
|
82
|
+
overlay.style.left = "auto";
|
|
83
|
+
}
|
|
84
|
+
if (pos === "bottom-left") {
|
|
85
|
+
overlay.style.bottom = `${m.bottom + pad}px`;
|
|
86
|
+
overlay.style.left = `${m.left + pad}px`;
|
|
87
|
+
overlay.style.top = "auto";
|
|
88
|
+
}
|
|
89
|
+
if (pos === "bottom-right") {
|
|
90
|
+
overlay.style.bottom = `${m.bottom + pad}px`;
|
|
91
|
+
overlay.style.right = `${m.right + pad}px`;
|
|
92
|
+
overlay.style.top = "auto";
|
|
93
|
+
overlay.style.left = "auto";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (state.collapsed) {
|
|
98
|
+
header.innerHTML = `<span style="color:${muted};font-size:10px;font-weight:600;letter-spacing:.04em;cursor:grab">STATS ▼</span>`;
|
|
99
|
+
body.innerHTML = "";
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const { bounds: b, view: v } = chart;
|
|
103
|
+
const fullX = b.maxX - b.minX;
|
|
104
|
+
const visMinX = b.minX + v.panX * fullX;
|
|
105
|
+
const visMaxX = visMinX + fullX / v.zoomX;
|
|
106
|
+
const allValues = [];
|
|
107
|
+
for (const s of chart.series) {
|
|
108
|
+
let lo = 0, hi = s.rawX.length;
|
|
109
|
+
while (lo < hi) {
|
|
110
|
+
const mid = lo + hi >> 1;
|
|
111
|
+
if (s.rawX[mid] < visMinX)
|
|
112
|
+
lo = mid + 1;
|
|
113
|
+
else
|
|
114
|
+
hi = mid;
|
|
115
|
+
}
|
|
116
|
+
const start = lo;
|
|
117
|
+
lo = 0;
|
|
118
|
+
hi = s.rawX.length;
|
|
119
|
+
while (lo < hi) {
|
|
120
|
+
const mid = lo + hi >> 1;
|
|
121
|
+
if (s.rawX[mid] <= visMaxX)
|
|
122
|
+
lo = mid + 1;
|
|
123
|
+
else
|
|
124
|
+
hi = mid;
|
|
125
|
+
}
|
|
126
|
+
const end = lo;
|
|
127
|
+
for (let i = start;i < end; i++)
|
|
128
|
+
allValues.push(s.rawY[i]);
|
|
129
|
+
}
|
|
130
|
+
const stats = computeStats(allValues);
|
|
131
|
+
if (!stats) {
|
|
132
|
+
overlay.style.display = "none";
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
header.innerHTML = `<div style="margin-bottom:4px"><span style="color:${muted};font-size:10px;font-weight:600;letter-spacing:.04em;cursor:grab">STATS ▲</span></div>`;
|
|
136
|
+
body.innerHTML = `
|
|
137
|
+
<div style="display:grid;grid-template-columns:auto auto;gap:1px 10px">
|
|
138
|
+
<span style="color:${muted}">min</span><span>${fmt(stats.min)}</span>
|
|
139
|
+
<span style="color:${muted}">max</span><span>${fmt(stats.max)}</span>
|
|
140
|
+
<span style="color:${muted}">avg</span><span>${fmt(stats.mean)}</span>
|
|
141
|
+
<span style="color:${muted}">σ</span><span>${fmt(stats.stddev)}</span>
|
|
142
|
+
<span style="color:${muted}">n</span><span>${stats.count.toLocaleString()}</span>
|
|
143
|
+
</div>`;
|
|
144
|
+
}
|
|
145
|
+
var statsPlugin = {
|
|
146
|
+
name: "stats",
|
|
147
|
+
install(chart, el) {
|
|
148
|
+
const ac = new AbortController;
|
|
149
|
+
const overlay = document.createElement("div");
|
|
150
|
+
overlay.style.cssText = "position:absolute;pointer-events:auto;z-index:15;";
|
|
151
|
+
const header = document.createElement("div");
|
|
152
|
+
const body = document.createElement("div");
|
|
153
|
+
overlay.appendChild(header);
|
|
154
|
+
overlay.appendChild(body);
|
|
155
|
+
el.appendChild(overlay);
|
|
156
|
+
const state = { overlay, header, body, collapsed: false, abort: ac, dragOffset: null, customPos: null, tiltAngle: 0, tiltVelocity: 0, tiltRafId: null };
|
|
157
|
+
states.set(chart, state);
|
|
158
|
+
header.addEventListener("click", () => {
|
|
159
|
+
state.collapsed = !state.collapsed;
|
|
160
|
+
updateOverlay(chart, state);
|
|
161
|
+
}, { signal: ac.signal });
|
|
162
|
+
overlay.addEventListener("pointerdown", (e) => {
|
|
163
|
+
e.stopPropagation();
|
|
164
|
+
if (!state.customPos) {
|
|
165
|
+
state.customPos = { x: overlay.offsetLeft, y: overlay.offsetTop };
|
|
166
|
+
overlay.style.left = state.customPos.x + "px";
|
|
167
|
+
overlay.style.top = state.customPos.y + "px";
|
|
168
|
+
overlay.style.right = "auto";
|
|
169
|
+
overlay.style.bottom = "auto";
|
|
170
|
+
}
|
|
171
|
+
state.dragOffset = { x: 0, y: 0 };
|
|
172
|
+
if (state.tiltRafId !== null) {
|
|
173
|
+
cancelAnimationFrame(state.tiltRafId);
|
|
174
|
+
state.tiltRafId = null;
|
|
175
|
+
}
|
|
176
|
+
overlay.setPointerCapture(e.pointerId);
|
|
177
|
+
overlay.style.cursor = "grabbing";
|
|
178
|
+
}, { signal: ac.signal });
|
|
179
|
+
overlay.addEventListener("pointermove", (e) => {
|
|
180
|
+
if (!state.dragOffset || !state.customPos)
|
|
181
|
+
return;
|
|
182
|
+
const x = Math.max(0, Math.min(state.customPos.x + e.movementX, el.clientWidth - overlay.offsetWidth));
|
|
183
|
+
const y = Math.max(0, Math.min(state.customPos.y + e.movementY, el.clientHeight - overlay.offsetHeight));
|
|
184
|
+
state.customPos = { x, y };
|
|
185
|
+
overlay.style.left = x + "px";
|
|
186
|
+
overlay.style.top = y + "px";
|
|
187
|
+
state.tiltVelocity = state.tiltVelocity * 0.6 + e.movementX * 0.4;
|
|
188
|
+
state.tiltAngle = Math.max(-15, Math.min(15, state.tiltVelocity * 1.5));
|
|
189
|
+
overlay.style.transform = `rotate(${state.tiltAngle}deg)`;
|
|
190
|
+
}, { signal: ac.signal });
|
|
191
|
+
overlay.addEventListener("pointerup", () => {
|
|
192
|
+
state.dragOffset = null;
|
|
193
|
+
overlay.style.cursor = "";
|
|
194
|
+
const decayTilt = () => {
|
|
195
|
+
state.tiltAngle *= 0.78;
|
|
196
|
+
state.tiltVelocity *= 0.78;
|
|
197
|
+
if (Math.abs(state.tiltAngle) > 0.05) {
|
|
198
|
+
overlay.style.transform = `rotate(${state.tiltAngle}deg)`;
|
|
199
|
+
state.tiltRafId = requestAnimationFrame(decayTilt);
|
|
200
|
+
} else {
|
|
201
|
+
state.tiltAngle = 0;
|
|
202
|
+
state.tiltVelocity = 0;
|
|
203
|
+
overlay.style.transform = "";
|
|
204
|
+
state.tiltRafId = null;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
state.tiltRafId = requestAnimationFrame(decayTilt);
|
|
208
|
+
}, { signal: ac.signal });
|
|
209
|
+
},
|
|
210
|
+
afterDraw(_, chart) {
|
|
211
|
+
const state = states.get(chart);
|
|
212
|
+
if (!state)
|
|
213
|
+
return;
|
|
214
|
+
updateOverlay(chart, state);
|
|
215
|
+
},
|
|
216
|
+
uninstall(chart) {
|
|
217
|
+
const state = states.get(chart);
|
|
218
|
+
if (state) {
|
|
219
|
+
if (state.tiltRafId !== null)
|
|
220
|
+
cancelAnimationFrame(state.tiltRafId);
|
|
221
|
+
state.abort.abort();
|
|
222
|
+
state.overlay.remove();
|
|
223
|
+
states.delete(chart);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
export {
|
|
228
|
+
statsPlugin
|
|
229
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{l as V}from"../../chunk-cvtt04m6.js";import{o as N}from"../../chunk-0eh4rzy9.js";import{q as F}from"../../chunk-50bcv2hw.js";import"../../chunk-wdfq2fpx.js";import"../../chunk-bbyt23tw.js";var I=new WeakMap;function p(P){if(P.length===0)return null;let H=1/0,j=-1/0,z=0;for(let J of P){if(J<H)H=J;if(J>j)j=J;z+=J}let Z=z/P.length,Q=0;for(let J of P){let $=J-Z;Q+=$*$}let q=Math.sqrt(Q/P.length);return{min:H,max:j,mean:Z,stddev:q,count:P.length}}function A(P,H){let{overlay:j,header:z,body:Z}=H,Q=F.isDark,q=P.config,$=(q.bgColor??(Q?[0.11,0.11,0.12]:[0.98,0.98,0.98])).map((K)=>Math.round(K*255)).join(","),D=Q?`rgba(${$},0.92)`:"rgba(255,255,255,0.95)",O=Q?"rgba(255,255,255,0.14)":"rgba(0,0,0,0.10)",T=q.textColor??(Q?"#c0c0c0":"#333333"),w=Q?"#777":"#aaa",k=q.fontFamily??V,M=q.statsPrecision??2,E=q.formatValue??((K)=>K.toFixed(M)),G=q.statsPosition??"top-left";if(j.style.display="block",j.style.position="absolute",j.style.pointerEvents="auto",j.style.zIndex="15",j.style.background=D,j.style.border=`1px solid ${O}`,j.style.borderRadius="6px",j.style.padding="7px 10px",j.style.fontFamily=k,j.style.fontSize="11px",j.style.color=T,j.style.minWidth="100px",j.style.userSelect="none",!H.dragOffset){let K=N,Y=6;if(H.customPos)j.style.top=`${H.customPos.y}px`,j.style.left=`${H.customPos.x}px`,j.style.right="auto",j.style.bottom="auto";else{if(j.style.right="auto",j.style.bottom="auto",j.style.top="auto",j.style.left="auto",G==="top-left")j.style.top=`${K.top+6}px`,j.style.left=`${K.left+6}px`;if(G==="top-right")j.style.top=`${K.top+6}px`,j.style.right=`${K.right+6}px`,j.style.left="auto";if(G==="bottom-left")j.style.bottom=`${K.bottom+6}px`,j.style.left=`${K.left+6}px`,j.style.top="auto";if(G==="bottom-right")j.style.bottom=`${K.bottom+6}px`,j.style.right=`${K.right+6}px`,j.style.top="auto",j.style.left="auto"}}if(H.collapsed){z.innerHTML=`<span style="color:${w};font-size:10px;font-weight:600;letter-spacing:.04em;cursor:grab">STATS ▼</span>`,Z.innerHTML="";return}let{bounds:L,view:R}=P,S=L.maxX-L.minX,U=L.minX+R.panX*S,X=U+S/R.zoomX,_=[];for(let K of P.series){let Y=0,B=K.rawX.length;while(Y<B){let W=Y+B>>1;if(K.rawX[W]<U)Y=W+1;else B=W}let x=Y;Y=0,B=K.rawX.length;while(Y<B){let W=Y+B>>1;if(K.rawX[W]<=X)Y=W+1;else B=W}let b=Y;for(let W=x;W<b;W++)_.push(K.rawY[W])}let C=p(_);if(!C){j.style.display="none";return}z.innerHTML=`<div style="margin-bottom:4px"><span style="color:${w};font-size:10px;font-weight:600;letter-spacing:.04em;cursor:grab">STATS ▲</span></div>`,Z.innerHTML=`
|
|
2
|
+
<div style="display:grid;grid-template-columns:auto auto;gap:1px 10px">
|
|
3
|
+
<span style="color:${w}">min</span><span>${E(C.min)}</span>
|
|
4
|
+
<span style="color:${w}">max</span><span>${E(C.max)}</span>
|
|
5
|
+
<span style="color:${w}">avg</span><span>${E(C.mean)}</span>
|
|
6
|
+
<span style="color:${w}">σ</span><span>${E(C.stddev)}</span>
|
|
7
|
+
<span style="color:${w}">n</span><span>${C.count.toLocaleString()}</span>
|
|
8
|
+
</div>`}var u={name:"stats",install(P,H){let j=new AbortController,z=document.createElement("div");z.style.cssText="position:absolute;pointer-events:auto;z-index:15;";let Z=document.createElement("div"),Q=document.createElement("div");z.appendChild(Z),z.appendChild(Q),H.appendChild(z);let q={overlay:z,header:Z,body:Q,collapsed:!1,abort:j,dragOffset:null,customPos:null,tiltAngle:0,tiltVelocity:0,tiltRafId:null};I.set(P,q),Z.addEventListener("click",()=>{q.collapsed=!q.collapsed,A(P,q)},{signal:j.signal}),z.addEventListener("pointerdown",(J)=>{if(J.stopPropagation(),!q.customPos)q.customPos={x:z.offsetLeft,y:z.offsetTop},z.style.left=q.customPos.x+"px",z.style.top=q.customPos.y+"px",z.style.right="auto",z.style.bottom="auto";if(q.dragOffset={x:0,y:0},q.tiltRafId!==null)cancelAnimationFrame(q.tiltRafId),q.tiltRafId=null;z.setPointerCapture(J.pointerId),z.style.cursor="grabbing"},{signal:j.signal}),z.addEventListener("pointermove",(J)=>{if(!q.dragOffset||!q.customPos)return;let $=Math.max(0,Math.min(q.customPos.x+J.movementX,H.clientWidth-z.offsetWidth)),D=Math.max(0,Math.min(q.customPos.y+J.movementY,H.clientHeight-z.offsetHeight));q.customPos={x:$,y:D},z.style.left=$+"px",z.style.top=D+"px",q.tiltVelocity=q.tiltVelocity*0.6+J.movementX*0.4,q.tiltAngle=Math.max(-15,Math.min(15,q.tiltVelocity*1.5)),z.style.transform=`rotate(${q.tiltAngle}deg)`},{signal:j.signal}),z.addEventListener("pointerup",()=>{q.dragOffset=null,z.style.cursor="";let J=()=>{if(q.tiltAngle*=0.78,q.tiltVelocity*=0.78,Math.abs(q.tiltAngle)>0.05)z.style.transform=`rotate(${q.tiltAngle}deg)`,q.tiltRafId=requestAnimationFrame(J);else q.tiltAngle=0,q.tiltVelocity=0,z.style.transform="",q.tiltRafId=null};q.tiltRafId=requestAnimationFrame(J)},{signal:j.signal})},afterDraw(P,H){let j=I.get(H);if(!j)return;A(H,j)},uninstall(P){let H=I.get(P);if(H){if(H.tiltRafId!==null)cancelAnimationFrame(H.tiltRafId);H.abort.abort(),H.overlay.remove(),I.delete(P)}}};export{u as statsPlugin};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
dataToScreen
|
|
3
|
+
} from "../../chunk-mmsy3yqt.js";
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_FONT
|
|
6
|
+
} from "../../chunk-1ngxm8t2.js";
|
|
7
|
+
import {
|
|
8
|
+
MARGIN
|
|
9
|
+
} from "../../chunk-831dem4f.js";
|
|
10
|
+
import {
|
|
11
|
+
ChartManager
|
|
12
|
+
} from "../../chunk-n8ew0z0e.js";
|
|
13
|
+
import"../../chunk-93yrr7er.js";
|
|
14
|
+
import"../../chunk-5gtx3pza.js";
|
|
15
|
+
|
|
16
|
+
// src/plugins/experimental/threshold.ts
|
|
17
|
+
var thresholdPlugin = {
|
|
18
|
+
name: "threshold",
|
|
19
|
+
beforeDraw(ctx, chart) {
|
|
20
|
+
const cfg = chart.config;
|
|
21
|
+
const thresholds = cfg.thresholds;
|
|
22
|
+
if (!thresholds?.length)
|
|
23
|
+
return;
|
|
24
|
+
const w = chart.width;
|
|
25
|
+
const h = chart.height;
|
|
26
|
+
const m = MARGIN;
|
|
27
|
+
for (const threshold of thresholds) {
|
|
28
|
+
if (!threshold.fillAbove && !threshold.fillBelow)
|
|
29
|
+
continue;
|
|
30
|
+
const sy = dataToScreen(0, threshold.y, chart, w, h).y;
|
|
31
|
+
ctx.save();
|
|
32
|
+
ctx.beginPath();
|
|
33
|
+
ctx.rect(m.left, m.top, w - m.left - m.right, h - m.top - m.bottom);
|
|
34
|
+
ctx.clip();
|
|
35
|
+
if (threshold.fillAbove) {
|
|
36
|
+
ctx.fillStyle = threshold.fillAbove;
|
|
37
|
+
ctx.fillRect(m.left, m.top, w - m.left - m.right, sy - m.top);
|
|
38
|
+
}
|
|
39
|
+
if (threshold.fillBelow) {
|
|
40
|
+
ctx.fillStyle = threshold.fillBelow;
|
|
41
|
+
ctx.fillRect(m.left, sy, w - m.left - m.right, h - m.bottom - sy);
|
|
42
|
+
}
|
|
43
|
+
ctx.restore();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
afterDraw(ctx, chart) {
|
|
47
|
+
const cfg = chart.config;
|
|
48
|
+
const thresholds = cfg.thresholds;
|
|
49
|
+
if (!thresholds?.length)
|
|
50
|
+
return;
|
|
51
|
+
const w = chart.width;
|
|
52
|
+
const h = chart.height;
|
|
53
|
+
const m = MARGIN;
|
|
54
|
+
const dark = ChartManager.isDark;
|
|
55
|
+
const fontFamily = cfg.fontFamily ?? DEFAULT_FONT;
|
|
56
|
+
for (const threshold of thresholds) {
|
|
57
|
+
const sy = dataToScreen(0, threshold.y, chart, w, h).y;
|
|
58
|
+
if (sy < m.top || sy > h - m.bottom)
|
|
59
|
+
continue;
|
|
60
|
+
ctx.save();
|
|
61
|
+
ctx.strokeStyle = threshold.color;
|
|
62
|
+
ctx.lineWidth = threshold.lineWidth ?? 1.5;
|
|
63
|
+
ctx.setLineDash(threshold.dash ?? [5, 3]);
|
|
64
|
+
ctx.beginPath();
|
|
65
|
+
ctx.moveTo(m.left, sy);
|
|
66
|
+
ctx.lineTo(w - m.right, sy);
|
|
67
|
+
ctx.stroke();
|
|
68
|
+
ctx.restore();
|
|
69
|
+
if (threshold.label) {
|
|
70
|
+
ctx.save();
|
|
71
|
+
ctx.font = `600 10px ${fontFamily}`;
|
|
72
|
+
const tw = ctx.measureText(threshold.label).width;
|
|
73
|
+
const pw = tw + 10;
|
|
74
|
+
const ph = 17;
|
|
75
|
+
const px = w - m.right - pw - 4;
|
|
76
|
+
const py = sy - ph / 2;
|
|
77
|
+
ctx.beginPath();
|
|
78
|
+
ctx.roundRect(px, py, pw, ph, 3);
|
|
79
|
+
ctx.fillStyle = dark ? "rgba(20,20,22,0.88)" : "rgba(255,255,255,0.92)";
|
|
80
|
+
ctx.fill();
|
|
81
|
+
ctx.strokeStyle = threshold.color;
|
|
82
|
+
ctx.lineWidth = 1;
|
|
83
|
+
ctx.setLineDash([]);
|
|
84
|
+
ctx.stroke();
|
|
85
|
+
ctx.fillStyle = threshold.color;
|
|
86
|
+
ctx.textAlign = "left";
|
|
87
|
+
ctx.textBaseline = "middle";
|
|
88
|
+
ctx.fillText(threshold.label, px + 5, sy);
|
|
89
|
+
ctx.restore();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
export {
|
|
95
|
+
thresholdPlugin
|
|
96
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as d}from"../../chunk-cbydth3q.js";import{l as C}from"../../chunk-cvtt04m6.js";import{o as g}from"../../chunk-0eh4rzy9.js";import{q as y}from"../../chunk-50bcv2hw.js";import"../../chunk-wdfq2fpx.js";import"../../chunk-bbyt23tw.js";var S={name:"threshold",beforeDraw(e,l){let h=l.config.thresholds;if(!h?.length)return;let{width:r,height:n}=l,o=g;for(let t of h){if(!t.fillAbove&&!t.fillBelow)continue;let f=d(0,t.y,l,r,n).y;if(e.save(),e.beginPath(),e.rect(o.left,o.top,r-o.left-o.right,n-o.top-o.bottom),e.clip(),t.fillAbove)e.fillStyle=t.fillAbove,e.fillRect(o.left,o.top,r-o.left-o.right,f-o.top);if(t.fillBelow)e.fillStyle=t.fillBelow,e.fillRect(o.left,f,r-o.left-o.right,n-o.bottom-f);e.restore()}},afterDraw(e,l){let a=l.config,h=a.thresholds;if(!h?.length)return;let{width:r,height:n}=l,o=g,t=y.isDark,f=a.fontFamily??C;for(let i of h){let s=d(0,i.y,l,r,n).y;if(s<o.top||s>n-o.bottom)continue;if(e.save(),e.strokeStyle=i.color,e.lineWidth=i.lineWidth??1.5,e.setLineDash(i.dash??[5,3]),e.beginPath(),e.moveTo(o.left,s),e.lineTo(r-o.right,s),e.stroke(),e.restore(),i.label){e.save(),e.font=`600 10px ${f}`;let m=e.measureText(i.label).width+10,p=17,b=r-o.right-m-4,u=s-p/2;e.beginPath(),e.roundRect(b,u,m,p,3),e.fillStyle=t?"rgba(20,20,22,0.88)":"rgba(255,255,255,0.92)",e.fill(),e.strokeStyle=i.color,e.lineWidth=1,e.setLineDash([]),e.stroke(),e.fillStyle=i.color,e.textAlign="left",e.textBaseline="middle",e.fillText(i.label,b+5,s),e.restore()}}}};export{S as thresholdPlugin};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import {
|
|
2
|
+
dataToScreen,
|
|
3
|
+
screenToData
|
|
4
|
+
} from "../../chunk-mmsy3yqt.js";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_FONT
|
|
7
|
+
} from "../../chunk-1ngxm8t2.js";
|
|
8
|
+
import {
|
|
9
|
+
MARGIN
|
|
10
|
+
} from "../../chunk-831dem4f.js";
|
|
11
|
+
import {
|
|
12
|
+
ChartManager
|
|
13
|
+
} from "../../chunk-n8ew0z0e.js";
|
|
14
|
+
import"../../chunk-93yrr7er.js";
|
|
15
|
+
import"../../chunk-5gtx3pza.js";
|
|
16
|
+
|
|
17
|
+
// src/plugins/experimental/tooltip-pin.ts
|
|
18
|
+
var states = new WeakMap;
|
|
19
|
+
var MAX_PIN_PX = 30;
|
|
20
|
+
function findNearestPin(chart, screenX, screenY, width, height) {
|
|
21
|
+
if (chart.series.length === 0)
|
|
22
|
+
return null;
|
|
23
|
+
const { x: dataX, y: dataY } = screenToData(screenX, screenY, chart, width, height);
|
|
24
|
+
let bestSi = -1;
|
|
25
|
+
let bestIdx = -1;
|
|
26
|
+
let bestDx = Infinity;
|
|
27
|
+
let bestDy = Infinity;
|
|
28
|
+
for (let s = 0;s < chart.series.length; s++) {
|
|
29
|
+
const sr2 = chart.series[s];
|
|
30
|
+
const n = sr2.rawX.length;
|
|
31
|
+
if (n === 0)
|
|
32
|
+
continue;
|
|
33
|
+
let lo = 0, hi = n - 1;
|
|
34
|
+
while (lo < hi) {
|
|
35
|
+
const mid = lo + hi >> 1;
|
|
36
|
+
if (sr2.rawX[mid] < dataX)
|
|
37
|
+
lo = mid + 1;
|
|
38
|
+
else
|
|
39
|
+
hi = mid;
|
|
40
|
+
}
|
|
41
|
+
let idx = lo;
|
|
42
|
+
if (lo > 0 && Math.abs(sr2.rawX[lo - 1] - dataX) < Math.abs(sr2.rawX[lo] - dataX)) {
|
|
43
|
+
idx = lo - 1;
|
|
44
|
+
}
|
|
45
|
+
const dx = Math.abs(sr2.rawX[idx] - dataX);
|
|
46
|
+
const dy = Math.abs(sr2.rawY[idx] - dataY);
|
|
47
|
+
if (dx < bestDx || dx === bestDx && dy < bestDy) {
|
|
48
|
+
bestDx = dx;
|
|
49
|
+
bestDy = dy;
|
|
50
|
+
bestSi = s;
|
|
51
|
+
bestIdx = idx;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (bestSi === -1)
|
|
55
|
+
return null;
|
|
56
|
+
const sr = chart.series[bestSi];
|
|
57
|
+
const { x: candidateSx, y: candidateSy } = dataToScreen(sr.rawX[bestIdx], sr.rawY[bestIdx], chart, width, height);
|
|
58
|
+
if (Math.hypot(candidateSx - screenX, candidateSy - screenY) > MAX_PIN_PX)
|
|
59
|
+
return null;
|
|
60
|
+
return {
|
|
61
|
+
dataX: sr.rawX[bestIdx],
|
|
62
|
+
dataY: sr.rawY[bestIdx],
|
|
63
|
+
seriesIndex: bestSi,
|
|
64
|
+
seriesLabel: sr.label,
|
|
65
|
+
color: sr.color
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
var tooltipPinPlugin = {
|
|
69
|
+
name: "tooltip-pin",
|
|
70
|
+
install(chart, el) {
|
|
71
|
+
const ac = new AbortController;
|
|
72
|
+
const state = { pins: [], abort: ac };
|
|
73
|
+
states.set(chart, state);
|
|
74
|
+
el.addEventListener("click", (e) => {
|
|
75
|
+
if (chart.dragging)
|
|
76
|
+
return;
|
|
77
|
+
const r = el.getBoundingClientRect();
|
|
78
|
+
const sx = e.clientX - r.left;
|
|
79
|
+
const sy = e.clientY - r.top;
|
|
80
|
+
for (let i = state.pins.length - 1;i >= 0; i--) {
|
|
81
|
+
const pin = state.pins[i];
|
|
82
|
+
const { x: pinSx, y: pinSy } = dataToScreen(pin.dataX, pin.dataY, chart, r.width, r.height);
|
|
83
|
+
if (Math.hypot(pinSx - sx, pinSy - sy) < 20) {
|
|
84
|
+
state.pins.splice(i, 1);
|
|
85
|
+
e.preventDefault();
|
|
86
|
+
ChartManager.drawChart(chart);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const nearest = findNearestPin(chart, sx, sy, r.width, r.height);
|
|
91
|
+
if (!nearest)
|
|
92
|
+
return;
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
const cfg = chart.config;
|
|
95
|
+
const maxPins = cfg.pinMax ?? 5;
|
|
96
|
+
if (state.pins.length >= maxPins)
|
|
97
|
+
state.pins.shift();
|
|
98
|
+
state.pins.push(nearest);
|
|
99
|
+
ChartManager.drawChart(chart);
|
|
100
|
+
}, { signal: ac.signal });
|
|
101
|
+
},
|
|
102
|
+
afterDraw(ctx, chart) {
|
|
103
|
+
const state = states.get(chart);
|
|
104
|
+
if (!state || state.pins.length === 0)
|
|
105
|
+
return;
|
|
106
|
+
const w = chart.width;
|
|
107
|
+
const h = chart.height;
|
|
108
|
+
const m = MARGIN;
|
|
109
|
+
const dark = ChartManager.isDark;
|
|
110
|
+
const cfg = chart.config;
|
|
111
|
+
const formatX = cfg.formatX ?? String;
|
|
112
|
+
const formatY = cfg.formatY ?? String;
|
|
113
|
+
const fontFamily = cfg.fontFamily ?? DEFAULT_FONT;
|
|
114
|
+
ctx.save();
|
|
115
|
+
ctx.font = `500 10px ${fontFamily}`;
|
|
116
|
+
for (const pin of state.pins) {
|
|
117
|
+
const { x: pinSx, y: pinSy } = dataToScreen(pin.dataX, pin.dataY, chart, w, h);
|
|
118
|
+
const colRgb = `${Math.round(pin.color.r * 255)},${Math.round(pin.color.g * 255)},${Math.round(pin.color.b * 255)}`;
|
|
119
|
+
const col = `rgb(${colRgb})`;
|
|
120
|
+
ctx.save();
|
|
121
|
+
ctx.setLineDash([4, 3]);
|
|
122
|
+
ctx.strokeStyle = `rgba(${colRgb},0.4)`;
|
|
123
|
+
ctx.lineWidth = 1;
|
|
124
|
+
ctx.beginPath();
|
|
125
|
+
ctx.moveTo(pinSx, m.top);
|
|
126
|
+
ctx.lineTo(pinSx, h - m.bottom);
|
|
127
|
+
ctx.stroke();
|
|
128
|
+
ctx.restore();
|
|
129
|
+
ctx.beginPath();
|
|
130
|
+
ctx.arc(pinSx, pinSy, 5, 0, Math.PI * 2);
|
|
131
|
+
ctx.fillStyle = col;
|
|
132
|
+
ctx.fill();
|
|
133
|
+
ctx.strokeStyle = dark ? "rgba(0,0,0,0.5)" : "rgba(255,255,255,0.8)";
|
|
134
|
+
ctx.lineWidth = 1.5;
|
|
135
|
+
ctx.stroke();
|
|
136
|
+
const xLabel = formatX(pin.dataX);
|
|
137
|
+
const yLabel = `${pin.seriesLabel}: ${formatY(pin.dataY)}`;
|
|
138
|
+
ctx.font = `500 10px ${fontFamily}`;
|
|
139
|
+
const cardW = Math.max(ctx.measureText(xLabel).width, ctx.measureText(yLabel).width) + 20;
|
|
140
|
+
const cardH = 14 + 2 * 17;
|
|
141
|
+
let bx = pinSx + 10;
|
|
142
|
+
let by = pinSy - cardH - 8;
|
|
143
|
+
if (bx + cardW > w)
|
|
144
|
+
bx = pinSx - cardW - 10;
|
|
145
|
+
by = Math.max(m.top + 4, Math.min(h - m.bottom - cardH - 4, by));
|
|
146
|
+
ctx.beginPath();
|
|
147
|
+
ctx.roundRect(bx, by, cardW, cardH, 5);
|
|
148
|
+
ctx.fillStyle = dark ? "rgba(28,28,30,0.94)" : "rgba(255,255,255,0.96)";
|
|
149
|
+
ctx.fill();
|
|
150
|
+
ctx.strokeStyle = `rgba(${colRgb},0.4)`;
|
|
151
|
+
ctx.lineWidth = 1.5;
|
|
152
|
+
ctx.stroke();
|
|
153
|
+
ctx.fillStyle = col;
|
|
154
|
+
ctx.beginPath();
|
|
155
|
+
ctx.roundRect(bx, by, cardW, 3, [5, 5, 0, 0]);
|
|
156
|
+
ctx.fill();
|
|
157
|
+
ctx.font = `500 10px ${fontFamily}`;
|
|
158
|
+
ctx.textAlign = "left";
|
|
159
|
+
ctx.textBaseline = "middle";
|
|
160
|
+
ctx.fillStyle = dark ? "#888" : "#999";
|
|
161
|
+
ctx.fillText(xLabel, bx + 10, by + 10);
|
|
162
|
+
ctx.fillStyle = dark ? "#eee" : "#1a1a1a";
|
|
163
|
+
ctx.fillText(yLabel, bx + 10, by + 27);
|
|
164
|
+
}
|
|
165
|
+
ctx.restore();
|
|
166
|
+
},
|
|
167
|
+
uninstall(chart) {
|
|
168
|
+
const state = states.get(chart);
|
|
169
|
+
if (state) {
|
|
170
|
+
state.abort.abort();
|
|
171
|
+
states.delete(chart);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
export {
|
|
176
|
+
tooltipPinPlugin
|
|
177
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as X,k as $}from"../../chunk-cbydth3q.js";import{l as I}from"../../chunk-cvtt04m6.js";import{o as Y}from"../../chunk-0eh4rzy9.js";import{q as c}from"../../chunk-50bcv2hw.js";import"../../chunk-wdfq2fpx.js";import"../../chunk-bbyt23tw.js";var M=new WeakMap,k=30;function D(t,i,d,o,r){if(t.series.length===0)return null;let{x:e,y:p}=$(i,d,t,o,r),a=-1,l=-1,C=1/0,h=1/0;for(let g=0;g<t.series.length;g++){let m=t.series[g],S=m.rawX.length;if(S===0)continue;let s=0,y=S-1;while(s<y){let T=s+y>>1;if(m.rawX[T]<e)s=T+1;else y=T}let P=s;if(s>0&&Math.abs(m.rawX[s-1]-e)<Math.abs(m.rawX[s]-e))P=s-1;let b=Math.abs(m.rawX[P]-e),u=Math.abs(m.rawY[P]-p);if(b<C||b===C&&u<h)C=b,h=u,a=g,l=P}if(a===-1)return null;let n=t.series[a],{x:f,y:w}=X(n.rawX[l],n.rawY[l],t,o,r);if(Math.hypot(f-i,w-d)>k)return null;return{dataX:n.rawX[l],dataY:n.rawY[l],seriesIndex:a,seriesLabel:n.label,color:n.color}}var F={name:"tooltip-pin",install(t,i){let d=new AbortController,o={pins:[],abort:d};M.set(t,o),i.addEventListener("click",(r)=>{if(t.dragging)return;let e=i.getBoundingClientRect(),p=r.clientX-e.left,a=r.clientY-e.top;for(let n=o.pins.length-1;n>=0;n--){let f=o.pins[n],{x:w,y:g}=X(f.dataX,f.dataY,t,e.width,e.height);if(Math.hypot(w-p,g-a)<20){o.pins.splice(n,1),r.preventDefault(),c.drawChart(t);return}}let l=D(t,p,a,e.width,e.height);if(!l)return;r.preventDefault();let h=t.config.pinMax??5;if(o.pins.length>=h)o.pins.shift();o.pins.push(l),c.drawChart(t)},{signal:d.signal})},afterDraw(t,i){let d=M.get(i);if(!d||d.pins.length===0)return;let{width:o,height:r}=i,e=Y,p=c.isDark,a=i.config,l=a.formatX??String,C=a.formatY??String,h=a.fontFamily??I;t.save(),t.font=`500 10px ${h}`;for(let n of d.pins){let{x:f,y:w}=X(n.dataX,n.dataY,i,o,r),g=`${Math.round(n.color.r*255)},${Math.round(n.color.g*255)},${Math.round(n.color.b*255)}`,m=`rgb(${g})`;t.save(),t.setLineDash([4,3]),t.strokeStyle=`rgba(${g},0.4)`,t.lineWidth=1,t.beginPath(),t.moveTo(f,e.top),t.lineTo(f,r-e.bottom),t.stroke(),t.restore(),t.beginPath(),t.arc(f,w,5,0,Math.PI*2),t.fillStyle=m,t.fill(),t.strokeStyle=p?"rgba(0,0,0,0.5)":"rgba(255,255,255,0.8)",t.lineWidth=1.5,t.stroke();let S=l(n.dataX),s=`${n.seriesLabel}: ${C(n.dataY)}`;t.font=`500 10px ${h}`;let y=Math.max(t.measureText(S).width,t.measureText(s).width)+20,P=48,b=f+10,u=w-P-8;if(b+y>o)b=f-y-10;u=Math.max(e.top+4,Math.min(r-e.bottom-P-4,u)),t.beginPath(),t.roundRect(b,u,y,P,5),t.fillStyle=p?"rgba(28,28,30,0.94)":"rgba(255,255,255,0.96)",t.fill(),t.strokeStyle=`rgba(${g},0.4)`,t.lineWidth=1.5,t.stroke(),t.fillStyle=m,t.beginPath(),t.roundRect(b,u,y,3,[5,5,0,0]),t.fill(),t.font=`500 10px ${h}`,t.textAlign="left",t.textBaseline="middle",t.fillStyle=p?"#888":"#999",t.fillText(S,b+10,u+10),t.fillStyle=p?"#eee":"#1a1a1a",t.fillText(s,b+10,u+27)}t.restore()},uninstall(t){let i=M.get(t);if(i)i.abort.abort(),M.delete(t)}};export{F as tooltipPinPlugin};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_FONT
|
|
3
|
+
} from "../../chunk-1ngxm8t2.js";
|
|
4
|
+
import {
|
|
5
|
+
MARGIN
|
|
6
|
+
} from "../../chunk-831dem4f.js";
|
|
7
|
+
import {
|
|
8
|
+
ChartManager
|
|
9
|
+
} from "../../chunk-n8ew0z0e.js";
|
|
10
|
+
import"../../chunk-93yrr7er.js";
|
|
11
|
+
import"../../chunk-5gtx3pza.js";
|
|
12
|
+
|
|
13
|
+
// src/plugins/experimental/watermark.ts
|
|
14
|
+
var watermarkPlugin = {
|
|
15
|
+
name: "watermark",
|
|
16
|
+
beforeDraw(ctx, chart) {
|
|
17
|
+
const cfg = chart.config;
|
|
18
|
+
const text = cfg.watermarkText;
|
|
19
|
+
if (!text)
|
|
20
|
+
return;
|
|
21
|
+
const { width: w, height: h } = chart;
|
|
22
|
+
const m = MARGIN;
|
|
23
|
+
const chartW = w - m.left - m.right;
|
|
24
|
+
const chartH = h - m.top - m.bottom;
|
|
25
|
+
const position = cfg.watermarkPosition ?? "center";
|
|
26
|
+
const opacity = cfg.watermarkOpacity ?? 0.07;
|
|
27
|
+
const fontSize = cfg.watermarkFontSize ?? Math.max(12, Math.round(Math.min(chartW, chartH) * 0.06));
|
|
28
|
+
const dark = ChartManager.isDark;
|
|
29
|
+
const color = cfg.watermarkColor ?? (dark ? "#ffffff" : "#000000");
|
|
30
|
+
const fontFamily = cfg.fontFamily ?? DEFAULT_FONT;
|
|
31
|
+
const rotation = cfg.watermarkRotation ?? (position === "center" ? -30 : 0);
|
|
32
|
+
const pad = 16;
|
|
33
|
+
let x;
|
|
34
|
+
let y;
|
|
35
|
+
ctx.save();
|
|
36
|
+
ctx.globalAlpha = opacity;
|
|
37
|
+
ctx.font = `bold ${fontSize}px ${fontFamily}`;
|
|
38
|
+
ctx.fillStyle = color;
|
|
39
|
+
ctx.textBaseline = "middle";
|
|
40
|
+
switch (position) {
|
|
41
|
+
case "center":
|
|
42
|
+
x = m.left + chartW / 2;
|
|
43
|
+
y = m.top + chartH / 2;
|
|
44
|
+
ctx.textAlign = "center";
|
|
45
|
+
break;
|
|
46
|
+
case "top-left":
|
|
47
|
+
x = m.left + pad;
|
|
48
|
+
y = m.top + pad + fontSize / 2;
|
|
49
|
+
ctx.textAlign = "left";
|
|
50
|
+
break;
|
|
51
|
+
case "top-right":
|
|
52
|
+
x = w - m.right - pad;
|
|
53
|
+
y = m.top + pad + fontSize / 2;
|
|
54
|
+
ctx.textAlign = "right";
|
|
55
|
+
break;
|
|
56
|
+
case "bottom-left":
|
|
57
|
+
x = m.left + pad;
|
|
58
|
+
y = h - m.bottom - pad - fontSize / 2;
|
|
59
|
+
ctx.textAlign = "left";
|
|
60
|
+
break;
|
|
61
|
+
case "bottom-right":
|
|
62
|
+
x = w - m.right - pad;
|
|
63
|
+
y = h - m.bottom - pad - fontSize / 2;
|
|
64
|
+
ctx.textAlign = "right";
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
ctx.translate(x, y);
|
|
68
|
+
if (rotation !== 0)
|
|
69
|
+
ctx.rotate(rotation * Math.PI / 180);
|
|
70
|
+
ctx.fillText(text, 0, 0);
|
|
71
|
+
ctx.restore();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export {
|
|
75
|
+
watermarkPlugin
|
|
76
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{l as w}from"../../chunk-cvtt04m6.js";import{o as c}from"../../chunk-0eh4rzy9.js";import{q as b}from"../../chunk-50bcv2hw.js";import"../../chunk-wdfq2fpx.js";import"../../chunk-bbyt23tw.js";var W={name:"watermark",beforeDraw(t,l){let o=l.config,f=o.watermarkText;if(!f)return;let{width:m,height:s}=l,r=c,g=m-r.left-r.right,k=s-r.top-r.bottom,p=o.watermarkPosition??"center",u=o.watermarkOpacity??0.07,i=o.watermarkFontSize??Math.max(12,Math.round(Math.min(g,k)*0.06)),y=b.isDark,d=o.watermarkColor??(y?"#ffffff":"#000000"),P=o.fontFamily??w,h=o.watermarkRotation??(p==="center"?-30:0),e=16,a,n;switch(t.save(),t.globalAlpha=u,t.font=`bold ${i}px ${P}`,t.fillStyle=d,t.textBaseline="middle",p){case"center":a=r.left+g/2,n=r.top+k/2,t.textAlign="center";break;case"top-left":a=r.left+e,n=r.top+e+i/2,t.textAlign="left";break;case"top-right":a=m-r.right-e,n=r.top+e+i/2,t.textAlign="right";break;case"bottom-left":a=r.left+e,n=s-r.bottom-e-i/2,t.textAlign="left";break;case"bottom-right":a=m-r.right-e,n=s-r.bottom-e-i/2,t.textAlign="right";break}if(t.translate(a,n),h!==0)t.rotate(h*Math.PI/180);t.fillText(f,0,0),t.restore()}};export{W as watermarkPlugin};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/plugins/hover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAiB,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/plugins/hover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAiB,SAAS,EAAE,MAAM,aAAa,CAAC;AAyEzE,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAED,OAAO,QAAQ,aAAa,CAAC;IAC3B,UAAU,mBAAmB;QAC3B,KAAK,EAAE,WAAW,CAAC;KACpB;CACF;AAiCD,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,WAAW,CAkPhD,CAAC"}
|