@rm-graph/core 0.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/README.md +65 -0
- package/dist/chunk-KATRK3C3.js +336 -0
- package/dist/chunk-KATRK3C3.js.map +1 -0
- package/dist/chunk-Q2ZHY445.mjs +328 -0
- package/dist/chunk-Q2ZHY445.mjs.map +1 -0
- package/dist/index-DWzDIVQ9.d.mts +404 -0
- package/dist/index-DWzDIVQ9.d.ts +404 -0
- package/dist/index.d.mts +556 -0
- package/dist/index.d.ts +556 -0
- package/dist/index.js +1655 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1600 -0
- package/dist/index.mjs.map +1 -0
- package/dist/themes/index.d.mts +1 -0
- package/dist/themes/index.d.ts +1 -0
- package/dist/themes/index.js +32 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/themes/index.mjs +3 -0
- package/dist/themes/index.mjs.map +1 -0
- package/package.json +54 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1655 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkKATRK3C3_js = require('./chunk-KATRK3C3.js');
|
|
4
|
+
var scichart = require('scichart');
|
|
5
|
+
|
|
6
|
+
// src/utils/helpers.ts
|
|
7
|
+
function generateId(prefix = "chart") {
|
|
8
|
+
return `${prefix}-${Math.random().toString(36).substring(2, 11)}`;
|
|
9
|
+
}
|
|
10
|
+
function parseSize(value, fallback) {
|
|
11
|
+
if (value === void 0) return fallback;
|
|
12
|
+
if (typeof value === "number") return value;
|
|
13
|
+
if (value.endsWith("%")) {
|
|
14
|
+
return fallback;
|
|
15
|
+
}
|
|
16
|
+
const parsed = parseInt(value, 10);
|
|
17
|
+
return isNaN(parsed) ? fallback : parsed;
|
|
18
|
+
}
|
|
19
|
+
function normalizeDataPoints(data) {
|
|
20
|
+
if (data.length === 0) return [];
|
|
21
|
+
if (typeof data[0] === "object" && "x" in data[0]) {
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
return data.map((y, index) => ({
|
|
25
|
+
x: index,
|
|
26
|
+
y
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
function extractXValues(data) {
|
|
30
|
+
return data.map((point) => {
|
|
31
|
+
if (typeof point.x === "number") return point.x;
|
|
32
|
+
if (point.x instanceof Date) return point.x.getTime();
|
|
33
|
+
return 0;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function extractYValues(data) {
|
|
37
|
+
return data.map((point) => point.y);
|
|
38
|
+
}
|
|
39
|
+
function deepMerge(target, source) {
|
|
40
|
+
const result = { ...target };
|
|
41
|
+
for (const key in source) {
|
|
42
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
43
|
+
const sourceValue = source[key];
|
|
44
|
+
const targetValue = target[key];
|
|
45
|
+
if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
46
|
+
result[key] = deepMerge(
|
|
47
|
+
targetValue,
|
|
48
|
+
sourceValue
|
|
49
|
+
);
|
|
50
|
+
} else if (sourceValue !== void 0) {
|
|
51
|
+
result[key] = sourceValue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
function debounce(fn, delay) {
|
|
58
|
+
let timeoutId = null;
|
|
59
|
+
return (...args) => {
|
|
60
|
+
if (timeoutId) {
|
|
61
|
+
clearTimeout(timeoutId);
|
|
62
|
+
}
|
|
63
|
+
timeoutId = setTimeout(() => {
|
|
64
|
+
fn(...args);
|
|
65
|
+
timeoutId = null;
|
|
66
|
+
}, delay);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function throttle(fn, limit) {
|
|
70
|
+
let inThrottle = false;
|
|
71
|
+
return (...args) => {
|
|
72
|
+
if (!inThrottle) {
|
|
73
|
+
fn(...args);
|
|
74
|
+
inThrottle = true;
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
inThrottle = false;
|
|
77
|
+
}, limit);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function calculateDataRange(series) {
|
|
82
|
+
let xMin = Infinity;
|
|
83
|
+
let xMax = -Infinity;
|
|
84
|
+
let yMin = Infinity;
|
|
85
|
+
let yMax = -Infinity;
|
|
86
|
+
for (const s of series) {
|
|
87
|
+
const normalized = normalizeDataPoints(s.data);
|
|
88
|
+
for (const point of normalized) {
|
|
89
|
+
const x = typeof point.x === "number" ? point.x : 0;
|
|
90
|
+
xMin = Math.min(xMin, x);
|
|
91
|
+
xMax = Math.max(xMax, x);
|
|
92
|
+
yMin = Math.min(yMin, point.y);
|
|
93
|
+
yMax = Math.max(yMax, point.y);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
xMin: xMin === Infinity ? 0 : xMin,
|
|
98
|
+
xMax: xMax === -Infinity ? 100 : xMax,
|
|
99
|
+
yMin: yMin === Infinity ? 0 : yMin,
|
|
100
|
+
yMax: yMax === -Infinity ? 100 : yMax
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function formatNumber(value, precision = 2) {
|
|
104
|
+
if (Math.abs(value) >= 1e9) {
|
|
105
|
+
return (value / 1e9).toFixed(precision) + "B";
|
|
106
|
+
}
|
|
107
|
+
if (Math.abs(value) >= 1e6) {
|
|
108
|
+
return (value / 1e6).toFixed(precision) + "M";
|
|
109
|
+
}
|
|
110
|
+
if (Math.abs(value) >= 1e3) {
|
|
111
|
+
return (value / 1e3).toFixed(precision) + "K";
|
|
112
|
+
}
|
|
113
|
+
return value.toFixed(precision);
|
|
114
|
+
}
|
|
115
|
+
function clamp(value, min, max) {
|
|
116
|
+
return Math.min(Math.max(value, min), max);
|
|
117
|
+
}
|
|
118
|
+
function lerp(start, end, t) {
|
|
119
|
+
return start + (end - start) * clamp(t, 0, 1);
|
|
120
|
+
}
|
|
121
|
+
function hexToRgba(hex, alpha = 1) {
|
|
122
|
+
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
123
|
+
if (!result) return hex;
|
|
124
|
+
const r = parseInt(result[1], 16);
|
|
125
|
+
const g = parseInt(result[2], 16);
|
|
126
|
+
const b = parseInt(result[3], 16);
|
|
127
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/charts/BaseChart.ts
|
|
131
|
+
var BaseChart = class {
|
|
132
|
+
constructor(config) {
|
|
133
|
+
this.container = null;
|
|
134
|
+
this.surface = null;
|
|
135
|
+
this.isInitialized = false;
|
|
136
|
+
this.isDestroyed = false;
|
|
137
|
+
// Event handlers
|
|
138
|
+
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
139
|
+
// Resize observer
|
|
140
|
+
this.resizeObserver = null;
|
|
141
|
+
this.id = config.id ?? generateId("chart");
|
|
142
|
+
this.config = config;
|
|
143
|
+
this.theme = chunkKATRK3C3_js.ThemeManager.getInstance().resolveTheme(config.theme);
|
|
144
|
+
this.debouncedResize = debounce(() => this.handleResize(), 100);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Initialize the chart in the given container
|
|
148
|
+
*/
|
|
149
|
+
async init(container) {
|
|
150
|
+
if (this.isDestroyed) {
|
|
151
|
+
throw new Error("Cannot initialize a destroyed chart");
|
|
152
|
+
}
|
|
153
|
+
if (typeof container === "string") {
|
|
154
|
+
const el = document.getElementById(container);
|
|
155
|
+
if (!el) {
|
|
156
|
+
throw new Error(`Container element "${container}" not found`);
|
|
157
|
+
}
|
|
158
|
+
this.container = el;
|
|
159
|
+
} else {
|
|
160
|
+
this.container = container;
|
|
161
|
+
}
|
|
162
|
+
this.setupContainer();
|
|
163
|
+
this.configureSciChartDefaults();
|
|
164
|
+
await this.createSurface();
|
|
165
|
+
this.setupResizeObserver();
|
|
166
|
+
this.isInitialized = true;
|
|
167
|
+
this.emit("rendered", { chartId: this.id, renderTime: performance.now() });
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Setup container element
|
|
171
|
+
*/
|
|
172
|
+
setupContainer() {
|
|
173
|
+
if (!this.container) return;
|
|
174
|
+
const { width, height } = this.config;
|
|
175
|
+
if (width) {
|
|
176
|
+
this.container.style.width = typeof width === "number" ? `${width}px` : width;
|
|
177
|
+
}
|
|
178
|
+
if (height) {
|
|
179
|
+
this.container.style.height = typeof height === "number" ? `${height}px` : height;
|
|
180
|
+
}
|
|
181
|
+
const computedStyle = window.getComputedStyle(this.container);
|
|
182
|
+
if (computedStyle.position === "static") {
|
|
183
|
+
this.container.style.position = "relative";
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Configure SciChart library defaults
|
|
188
|
+
*/
|
|
189
|
+
configureSciChartDefaults() {
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Update chart options
|
|
193
|
+
*/
|
|
194
|
+
setOptions(options) {
|
|
195
|
+
this.config = { ...this.config, ...options };
|
|
196
|
+
if (options.theme) {
|
|
197
|
+
this.theme = chunkKATRK3C3_js.ThemeManager.getInstance().resolveTheme(options.theme);
|
|
198
|
+
this.applyTheme();
|
|
199
|
+
}
|
|
200
|
+
this.update();
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Apply current theme to the chart
|
|
204
|
+
*/
|
|
205
|
+
applyTheme() {
|
|
206
|
+
if (!this.surface) return;
|
|
207
|
+
this.surface.background = this.theme.backgroundColor ?? "#ffffff";
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Set up resize observer for responsive charts
|
|
211
|
+
*/
|
|
212
|
+
setupResizeObserver() {
|
|
213
|
+
if (!this.container || typeof ResizeObserver === "undefined") return;
|
|
214
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
215
|
+
this.debouncedResize();
|
|
216
|
+
});
|
|
217
|
+
this.resizeObserver.observe(this.container);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Handle container resize
|
|
221
|
+
*/
|
|
222
|
+
handleResize() {
|
|
223
|
+
if (!this.surface || !this.container) return;
|
|
224
|
+
const { width, height } = this.container.getBoundingClientRect();
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Manually resize the chart
|
|
228
|
+
*/
|
|
229
|
+
resize(width, height) {
|
|
230
|
+
if (!this.container) return;
|
|
231
|
+
if (width !== void 0) {
|
|
232
|
+
this.container.style.width = `${width}px`;
|
|
233
|
+
}
|
|
234
|
+
if (height !== void 0) {
|
|
235
|
+
this.container.style.height = `${height}px`;
|
|
236
|
+
}
|
|
237
|
+
this.handleResize();
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Export chart as image
|
|
241
|
+
*/
|
|
242
|
+
async exportImage(format = "png") {
|
|
243
|
+
if (!this.surface) {
|
|
244
|
+
throw new Error("Chart not initialized");
|
|
245
|
+
}
|
|
246
|
+
const canvas = this.container?.querySelector("canvas");
|
|
247
|
+
if (!canvas) {
|
|
248
|
+
throw new Error("Canvas not found");
|
|
249
|
+
}
|
|
250
|
+
const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
|
|
251
|
+
return canvas.toDataURL(mimeType);
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Add event listener
|
|
255
|
+
*/
|
|
256
|
+
on(event, handler) {
|
|
257
|
+
if (!this.eventHandlers.has(event)) {
|
|
258
|
+
this.eventHandlers.set(event, /* @__PURE__ */ new Set());
|
|
259
|
+
}
|
|
260
|
+
this.eventHandlers.get(event).add(handler);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Remove event listener
|
|
264
|
+
*/
|
|
265
|
+
off(event, handler) {
|
|
266
|
+
const handlers = this.eventHandlers.get(event);
|
|
267
|
+
if (handlers) {
|
|
268
|
+
handlers.delete(handler);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Emit an event
|
|
273
|
+
*/
|
|
274
|
+
emit(event, data) {
|
|
275
|
+
const handlers = this.eventHandlers.get(event);
|
|
276
|
+
if (handlers) {
|
|
277
|
+
handlers.forEach((handler) => handler(data));
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Destroy the chart and clean up resources
|
|
282
|
+
*/
|
|
283
|
+
destroy() {
|
|
284
|
+
if (this.isDestroyed) return;
|
|
285
|
+
if (this.resizeObserver) {
|
|
286
|
+
this.resizeObserver.disconnect();
|
|
287
|
+
this.resizeObserver = null;
|
|
288
|
+
}
|
|
289
|
+
this.eventHandlers.clear();
|
|
290
|
+
if (this.surface) {
|
|
291
|
+
this.surface.delete();
|
|
292
|
+
this.surface = null;
|
|
293
|
+
}
|
|
294
|
+
if (this.container) {
|
|
295
|
+
this.container.innerHTML = "";
|
|
296
|
+
}
|
|
297
|
+
this.isDestroyed = true;
|
|
298
|
+
this.isInitialized = false;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Get current configuration
|
|
302
|
+
*/
|
|
303
|
+
getConfig() {
|
|
304
|
+
return { ...this.config };
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get current theme
|
|
308
|
+
*/
|
|
309
|
+
getTheme() {
|
|
310
|
+
return { ...this.theme };
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Check if chart is initialized
|
|
314
|
+
*/
|
|
315
|
+
isReady() {
|
|
316
|
+
return this.isInitialized && !this.isDestroyed;
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
function getSciChartTheme(themeName) {
|
|
320
|
+
switch (themeName) {
|
|
321
|
+
case "light":
|
|
322
|
+
return new scichart.SciChartJSLightTheme();
|
|
323
|
+
case "dark":
|
|
324
|
+
case "modern":
|
|
325
|
+
case "midnight":
|
|
326
|
+
default:
|
|
327
|
+
return new scichart.SciChartJSDarkTheme();
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
var LineChart = class extends BaseChart {
|
|
331
|
+
constructor(config) {
|
|
332
|
+
super(config);
|
|
333
|
+
this.dataSeries = /* @__PURE__ */ new Map();
|
|
334
|
+
this.renderableSeries = [];
|
|
335
|
+
this.wasmContext = null;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Create the SciChart surface for line chart
|
|
339
|
+
*/
|
|
340
|
+
async createSurface() {
|
|
341
|
+
if (!this.container) {
|
|
342
|
+
throw new Error("Container not set");
|
|
343
|
+
}
|
|
344
|
+
const sciChartTheme = getSciChartTheme(this.config.theme);
|
|
345
|
+
if (!this.container.id) {
|
|
346
|
+
this.container.id = this.id;
|
|
347
|
+
}
|
|
348
|
+
const { sciChartSurface, wasmContext } = await scichart.SciChartSurface.create(
|
|
349
|
+
this.container,
|
|
350
|
+
{
|
|
351
|
+
theme: sciChartTheme
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
this.surface = sciChartSurface;
|
|
355
|
+
this.wasmContext = wasmContext;
|
|
356
|
+
const xAxis = new scichart.NumericAxis(wasmContext, {
|
|
357
|
+
axisTitle: this.config.xAxis?.title,
|
|
358
|
+
drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? true,
|
|
359
|
+
drawMinorGridLines: false,
|
|
360
|
+
axisTitleStyle: {
|
|
361
|
+
fontSize: 14,
|
|
362
|
+
fontFamily: this.theme.fontFamily,
|
|
363
|
+
color: this.theme.axis?.titleColor
|
|
364
|
+
},
|
|
365
|
+
labelStyle: {
|
|
366
|
+
fontSize: 12,
|
|
367
|
+
fontFamily: this.theme.fontFamily,
|
|
368
|
+
color: this.theme.axis?.labelColor
|
|
369
|
+
},
|
|
370
|
+
majorGridLineStyle: {
|
|
371
|
+
color: this.theme.axis?.gridLineColor ?? "#e9ecef",
|
|
372
|
+
strokeThickness: 1
|
|
373
|
+
},
|
|
374
|
+
axisBorder: {
|
|
375
|
+
color: this.theme.axis?.lineColor ?? "#dee2e6"
|
|
376
|
+
},
|
|
377
|
+
autoRange: scichart.EAutoRange.Always
|
|
378
|
+
});
|
|
379
|
+
const yAxis = new scichart.NumericAxis(wasmContext, {
|
|
380
|
+
axisTitle: this.config.yAxis?.title,
|
|
381
|
+
drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? true,
|
|
382
|
+
drawMinorGridLines: false,
|
|
383
|
+
axisTitleStyle: {
|
|
384
|
+
fontSize: 14,
|
|
385
|
+
fontFamily: this.theme.fontFamily,
|
|
386
|
+
color: this.theme.axis?.titleColor
|
|
387
|
+
},
|
|
388
|
+
labelStyle: {
|
|
389
|
+
fontSize: 12,
|
|
390
|
+
fontFamily: this.theme.fontFamily,
|
|
391
|
+
color: this.theme.axis?.labelColor
|
|
392
|
+
},
|
|
393
|
+
majorGridLineStyle: {
|
|
394
|
+
color: this.theme.axis?.gridLineColor ?? "#e9ecef",
|
|
395
|
+
strokeThickness: 1
|
|
396
|
+
},
|
|
397
|
+
axisBorder: {
|
|
398
|
+
color: this.theme.axis?.lineColor ?? "#dee2e6"
|
|
399
|
+
},
|
|
400
|
+
autoRange: scichart.EAutoRange.Always
|
|
401
|
+
});
|
|
402
|
+
if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
|
|
403
|
+
xAxis.visibleRange = new scichart.NumberRange(this.config.xAxis.min, this.config.xAxis.max);
|
|
404
|
+
xAxis.autoRange = scichart.EAutoRange.Never;
|
|
405
|
+
}
|
|
406
|
+
if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
|
|
407
|
+
yAxis.visibleRange = new scichart.NumberRange(this.config.yAxis.min, this.config.yAxis.max);
|
|
408
|
+
yAxis.autoRange = scichart.EAutoRange.Never;
|
|
409
|
+
}
|
|
410
|
+
sciChartSurface.xAxes.add(xAxis);
|
|
411
|
+
sciChartSurface.yAxes.add(yAxis);
|
|
412
|
+
if (this.config.tooltip?.enabled !== false) {
|
|
413
|
+
sciChartSurface.chartModifiers.add(
|
|
414
|
+
new scichart.RolloverModifier({
|
|
415
|
+
showTooltip: true,
|
|
416
|
+
showAxisLabel: true
|
|
417
|
+
})
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
sciChartSurface.chartModifiers.add(new scichart.ZoomPanModifier());
|
|
421
|
+
sciChartSurface.chartModifiers.add(new scichart.MouseWheelZoomModifier());
|
|
422
|
+
this.addSeries(this.config.series);
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Add series to the chart
|
|
426
|
+
*/
|
|
427
|
+
addSeries(seriesConfigs) {
|
|
428
|
+
if (!this.surface || !this.wasmContext) return;
|
|
429
|
+
const wasmContext = this.wasmContext;
|
|
430
|
+
const colorPalette = this.theme.colorPalette ?? [];
|
|
431
|
+
seriesConfigs.forEach((seriesConfig, index) => {
|
|
432
|
+
const data = normalizeDataPoints(seriesConfig.data);
|
|
433
|
+
const xValues = extractXValues(data);
|
|
434
|
+
const yValues = extractYValues(data);
|
|
435
|
+
const dataSeries = new scichart.XyDataSeries(wasmContext, {
|
|
436
|
+
xValues,
|
|
437
|
+
yValues,
|
|
438
|
+
dataSeriesName: seriesConfig.name
|
|
439
|
+
});
|
|
440
|
+
this.dataSeries.set(seriesConfig.name, dataSeries);
|
|
441
|
+
const color = seriesConfig.color ?? colorPalette[index % colorPalette.length] ?? "#6366f1";
|
|
442
|
+
const lineSeries = new scichart.FastLineRenderableSeries(wasmContext);
|
|
443
|
+
lineSeries.dataSeries = dataSeries;
|
|
444
|
+
lineSeries.stroke = color;
|
|
445
|
+
lineSeries.strokeThickness = this.config.lineWidth ?? 2;
|
|
446
|
+
if (this.config.showPoints) {
|
|
447
|
+
lineSeries.pointMarker = new scichart.EllipsePointMarker(wasmContext, {
|
|
448
|
+
width: this.config.pointSize ?? 8,
|
|
449
|
+
height: this.config.pointSize ?? 8,
|
|
450
|
+
fill: color,
|
|
451
|
+
stroke: color,
|
|
452
|
+
strokeThickness: 0
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
if (this.config.animation !== false) {
|
|
456
|
+
lineSeries.animation = new scichart.SweepAnimation({
|
|
457
|
+
duration: typeof this.config.animation === "object" ? this.config.animation.duration ?? 500 : 500
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
this.renderableSeries.push(lineSeries);
|
|
461
|
+
this.surface.renderableSeries.add(lineSeries);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Set new data for the chart
|
|
466
|
+
*/
|
|
467
|
+
setData(data) {
|
|
468
|
+
if (!this.surface) {
|
|
469
|
+
this.config.series = data;
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
this.clearSeries();
|
|
473
|
+
this.config.series = data;
|
|
474
|
+
this.addSeries(data);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Update specific series data
|
|
478
|
+
*/
|
|
479
|
+
updateSeriesData(seriesName, data) {
|
|
480
|
+
const dataSeries = this.dataSeries.get(seriesName);
|
|
481
|
+
if (!dataSeries) {
|
|
482
|
+
console.warn(`Series "${seriesName}" not found`);
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
const normalized = normalizeDataPoints(data);
|
|
486
|
+
const xValues = extractXValues(normalized);
|
|
487
|
+
const yValues = extractYValues(normalized);
|
|
488
|
+
dataSeries.clear();
|
|
489
|
+
dataSeries.appendRange(xValues, yValues);
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Append data to a series
|
|
493
|
+
*/
|
|
494
|
+
appendData(seriesName, data) {
|
|
495
|
+
const dataSeries = this.dataSeries.get(seriesName);
|
|
496
|
+
if (!dataSeries) {
|
|
497
|
+
console.warn(`Series "${seriesName}" not found`);
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
const points = Array.isArray(data) ? data : [data];
|
|
501
|
+
const normalized = normalizeDataPoints(points);
|
|
502
|
+
const xValues = extractXValues(normalized);
|
|
503
|
+
const yValues = extractYValues(normalized);
|
|
504
|
+
dataSeries.appendRange(xValues, yValues);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Clear all series
|
|
508
|
+
*/
|
|
509
|
+
clearSeries() {
|
|
510
|
+
if (!this.surface) return;
|
|
511
|
+
this.renderableSeries.forEach((series) => {
|
|
512
|
+
this.surface.renderableSeries.remove(series);
|
|
513
|
+
series.delete();
|
|
514
|
+
});
|
|
515
|
+
this.renderableSeries = [];
|
|
516
|
+
this.dataSeries.forEach((ds) => ds.delete());
|
|
517
|
+
this.dataSeries.clear();
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Update chart
|
|
521
|
+
*/
|
|
522
|
+
update() {
|
|
523
|
+
if (!this.surface) return;
|
|
524
|
+
this.applyTheme();
|
|
525
|
+
this.surface.invalidateElement();
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Apply theme to line chart
|
|
529
|
+
*/
|
|
530
|
+
applyTheme() {
|
|
531
|
+
super.applyTheme();
|
|
532
|
+
if (!this.surface) return;
|
|
533
|
+
const colorPalette = this.theme.colorPalette ?? [];
|
|
534
|
+
this.renderableSeries.forEach((series, index) => {
|
|
535
|
+
const originalColor = this.config.series[index]?.color;
|
|
536
|
+
if (!originalColor) {
|
|
537
|
+
series.stroke = colorPalette[index % colorPalette.length];
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Destroy and clean up
|
|
543
|
+
*/
|
|
544
|
+
destroy() {
|
|
545
|
+
this.clearSeries();
|
|
546
|
+
super.destroy();
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
async function createLineChart(container, config) {
|
|
550
|
+
const chart = new LineChart(config);
|
|
551
|
+
await chart.init(container);
|
|
552
|
+
return chart;
|
|
553
|
+
}
|
|
554
|
+
function getSciChartTheme2(themeName) {
|
|
555
|
+
switch (themeName) {
|
|
556
|
+
case "light":
|
|
557
|
+
return new scichart.SciChartJSLightTheme();
|
|
558
|
+
case "dark":
|
|
559
|
+
case "modern":
|
|
560
|
+
case "midnight":
|
|
561
|
+
default:
|
|
562
|
+
return new scichart.SciChartJSDarkTheme();
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
var BarChart = class extends BaseChart {
|
|
566
|
+
constructor(config) {
|
|
567
|
+
super(config);
|
|
568
|
+
this.dataSeries = /* @__PURE__ */ new Map();
|
|
569
|
+
this.renderableSeries = [];
|
|
570
|
+
this.wasmContext = null;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Create the SciChart surface for bar chart
|
|
574
|
+
*/
|
|
575
|
+
async createSurface() {
|
|
576
|
+
if (!this.container) {
|
|
577
|
+
throw new Error("Container not set");
|
|
578
|
+
}
|
|
579
|
+
const sciChartTheme = getSciChartTheme2(this.config.theme);
|
|
580
|
+
if (!this.container.id) {
|
|
581
|
+
this.container.id = this.id;
|
|
582
|
+
}
|
|
583
|
+
const { sciChartSurface, wasmContext } = await scichart.SciChartSurface.create(
|
|
584
|
+
this.container,
|
|
585
|
+
{
|
|
586
|
+
theme: sciChartTheme
|
|
587
|
+
}
|
|
588
|
+
);
|
|
589
|
+
this.surface = sciChartSurface;
|
|
590
|
+
this.wasmContext = wasmContext;
|
|
591
|
+
const xAxis = new scichart.NumericAxis(wasmContext, {
|
|
592
|
+
axisTitle: this.config.xAxis?.title,
|
|
593
|
+
drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? false,
|
|
594
|
+
drawMinorGridLines: false,
|
|
595
|
+
axisTitleStyle: {
|
|
596
|
+
fontSize: 14,
|
|
597
|
+
fontFamily: this.theme.fontFamily,
|
|
598
|
+
color: this.theme.axis?.titleColor
|
|
599
|
+
},
|
|
600
|
+
labelStyle: {
|
|
601
|
+
fontSize: 12,
|
|
602
|
+
fontFamily: this.theme.fontFamily,
|
|
603
|
+
color: this.theme.axis?.labelColor
|
|
604
|
+
},
|
|
605
|
+
autoRange: scichart.EAutoRange.Always
|
|
606
|
+
});
|
|
607
|
+
const yAxis = new scichart.NumericAxis(wasmContext, {
|
|
608
|
+
axisTitle: this.config.yAxis?.title,
|
|
609
|
+
drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? true,
|
|
610
|
+
drawMinorGridLines: false,
|
|
611
|
+
axisTitleStyle: {
|
|
612
|
+
fontSize: 14,
|
|
613
|
+
fontFamily: this.theme.fontFamily,
|
|
614
|
+
color: this.theme.axis?.titleColor
|
|
615
|
+
},
|
|
616
|
+
labelStyle: {
|
|
617
|
+
fontSize: 12,
|
|
618
|
+
fontFamily: this.theme.fontFamily,
|
|
619
|
+
color: this.theme.axis?.labelColor
|
|
620
|
+
},
|
|
621
|
+
autoRange: scichart.EAutoRange.Always,
|
|
622
|
+
growBy: new scichart.NumberRange(0, 0.1)
|
|
623
|
+
// Add 10% padding at top
|
|
624
|
+
});
|
|
625
|
+
if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
|
|
626
|
+
xAxis.visibleRange = new scichart.NumberRange(this.config.xAxis.min, this.config.xAxis.max);
|
|
627
|
+
xAxis.autoRange = scichart.EAutoRange.Never;
|
|
628
|
+
}
|
|
629
|
+
if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
|
|
630
|
+
yAxis.visibleRange = new scichart.NumberRange(this.config.yAxis.min, this.config.yAxis.max);
|
|
631
|
+
yAxis.autoRange = scichart.EAutoRange.Never;
|
|
632
|
+
}
|
|
633
|
+
sciChartSurface.xAxes.add(xAxis);
|
|
634
|
+
sciChartSurface.yAxes.add(yAxis);
|
|
635
|
+
if (this.config.tooltip?.enabled !== false) {
|
|
636
|
+
sciChartSurface.chartModifiers.add(
|
|
637
|
+
new scichart.RolloverModifier({
|
|
638
|
+
showTooltip: true,
|
|
639
|
+
showAxisLabel: true
|
|
640
|
+
})
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
sciChartSurface.chartModifiers.add(new scichart.ZoomPanModifier());
|
|
644
|
+
this.addSeries(this.config.series);
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Add series to the chart
|
|
648
|
+
*/
|
|
649
|
+
addSeries(seriesConfigs) {
|
|
650
|
+
if (!this.surface || !this.wasmContext) return;
|
|
651
|
+
const wasmContext = this.wasmContext;
|
|
652
|
+
const colorPalette = this.theme.colorPalette ?? [];
|
|
653
|
+
const seriesCount = seriesConfigs.length;
|
|
654
|
+
const dataPointWidth = this.config.barWidth ?? 0.7;
|
|
655
|
+
seriesConfigs.forEach((seriesConfig, index) => {
|
|
656
|
+
const data = normalizeDataPoints(seriesConfig.data);
|
|
657
|
+
let xValues = extractXValues(data);
|
|
658
|
+
if (!this.config.stacked && seriesCount > 1) {
|
|
659
|
+
const offset = (index - (seriesCount - 1) / 2) * (dataPointWidth / seriesCount);
|
|
660
|
+
xValues = xValues.map((x) => x + offset);
|
|
661
|
+
}
|
|
662
|
+
const yValues = extractYValues(data);
|
|
663
|
+
const dataSeries = new scichart.XyDataSeries(wasmContext, {
|
|
664
|
+
xValues,
|
|
665
|
+
yValues,
|
|
666
|
+
dataSeriesName: seriesConfig.name
|
|
667
|
+
});
|
|
668
|
+
this.dataSeries.set(seriesConfig.name, dataSeries);
|
|
669
|
+
const color = seriesConfig.color ?? colorPalette[index % colorPalette.length] ?? "#6366f1";
|
|
670
|
+
const columnSeries = new scichart.FastColumnRenderableSeries(wasmContext);
|
|
671
|
+
columnSeries.dataSeries = dataSeries;
|
|
672
|
+
columnSeries.fill = color;
|
|
673
|
+
columnSeries.stroke = color;
|
|
674
|
+
columnSeries.strokeThickness = 0;
|
|
675
|
+
columnSeries.dataPointWidth = this.config.stacked ? dataPointWidth : dataPointWidth / seriesCount;
|
|
676
|
+
columnSeries.cornerRadius = this.config.borderRadius ?? 0;
|
|
677
|
+
if (this.config.animation !== false) {
|
|
678
|
+
columnSeries.animation = new scichart.WaveAnimation({
|
|
679
|
+
duration: typeof this.config.animation === "object" ? this.config.animation.duration ?? 500 : 500
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
columnSeries.fillLinearGradient = new scichart.GradientParams(
|
|
683
|
+
new scichart.Point(0, 0),
|
|
684
|
+
new scichart.Point(0, 1),
|
|
685
|
+
[
|
|
686
|
+
{ color, offset: 0 },
|
|
687
|
+
{ color: hexToRgba(color, 0.7), offset: 1 }
|
|
688
|
+
]
|
|
689
|
+
);
|
|
690
|
+
this.renderableSeries.push(columnSeries);
|
|
691
|
+
this.surface.renderableSeries.add(columnSeries);
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
/**
|
|
695
|
+
* Set new data for the chart
|
|
696
|
+
*/
|
|
697
|
+
setData(data) {
|
|
698
|
+
if (!this.surface) {
|
|
699
|
+
this.config.series = data;
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
this.clearSeries();
|
|
703
|
+
this.config.series = data;
|
|
704
|
+
this.addSeries(data);
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Update specific series data
|
|
708
|
+
*/
|
|
709
|
+
updateSeriesData(seriesName, data) {
|
|
710
|
+
const dataSeries = this.dataSeries.get(seriesName);
|
|
711
|
+
if (!dataSeries) {
|
|
712
|
+
console.warn(`Series "${seriesName}" not found`);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
const normalized = normalizeDataPoints(data);
|
|
716
|
+
const xValues = extractXValues(normalized);
|
|
717
|
+
const yValues = extractYValues(normalized);
|
|
718
|
+
dataSeries.clear();
|
|
719
|
+
dataSeries.appendRange(xValues, yValues);
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Clear all series
|
|
723
|
+
*/
|
|
724
|
+
clearSeries() {
|
|
725
|
+
if (!this.surface) return;
|
|
726
|
+
this.renderableSeries.forEach((series) => {
|
|
727
|
+
this.surface.renderableSeries.remove(series);
|
|
728
|
+
series.delete();
|
|
729
|
+
});
|
|
730
|
+
this.renderableSeries = [];
|
|
731
|
+
this.dataSeries.forEach((ds) => ds.delete());
|
|
732
|
+
this.dataSeries.clear();
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Update chart
|
|
736
|
+
*/
|
|
737
|
+
update() {
|
|
738
|
+
if (!this.surface) return;
|
|
739
|
+
this.applyTheme();
|
|
740
|
+
this.surface.invalidateElement();
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Destroy and clean up
|
|
744
|
+
*/
|
|
745
|
+
destroy() {
|
|
746
|
+
this.clearSeries();
|
|
747
|
+
super.destroy();
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
async function createBarChart(container, config) {
|
|
751
|
+
const chart = new BarChart(config);
|
|
752
|
+
await chart.init(container);
|
|
753
|
+
return chart;
|
|
754
|
+
}
|
|
755
|
+
function getSciChartTheme3(themeName) {
|
|
756
|
+
switch (themeName) {
|
|
757
|
+
case "light":
|
|
758
|
+
return new scichart.SciChartJSLightTheme();
|
|
759
|
+
case "dark":
|
|
760
|
+
case "modern":
|
|
761
|
+
case "midnight":
|
|
762
|
+
default:
|
|
763
|
+
return new scichart.SciChartJSDarkTheme();
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
var AreaChart = class extends BaseChart {
|
|
767
|
+
constructor(config) {
|
|
768
|
+
super(config);
|
|
769
|
+
this.dataSeries = /* @__PURE__ */ new Map();
|
|
770
|
+
this.renderableSeries = [];
|
|
771
|
+
this.wasmContext = null;
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Create the SciChart surface for area chart
|
|
775
|
+
*/
|
|
776
|
+
async createSurface() {
|
|
777
|
+
if (!this.container) {
|
|
778
|
+
throw new Error("Container not set");
|
|
779
|
+
}
|
|
780
|
+
const sciChartTheme = getSciChartTheme3(this.config.theme);
|
|
781
|
+
if (!this.container.id) {
|
|
782
|
+
this.container.id = this.id;
|
|
783
|
+
}
|
|
784
|
+
const { sciChartSurface, wasmContext } = await scichart.SciChartSurface.create(
|
|
785
|
+
this.container,
|
|
786
|
+
{
|
|
787
|
+
theme: sciChartTheme
|
|
788
|
+
}
|
|
789
|
+
);
|
|
790
|
+
this.surface = sciChartSurface;
|
|
791
|
+
this.wasmContext = wasmContext;
|
|
792
|
+
const xAxis = new scichart.NumericAxis(wasmContext, {
|
|
793
|
+
axisTitle: this.config.xAxis?.title,
|
|
794
|
+
drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? true,
|
|
795
|
+
drawMinorGridLines: false,
|
|
796
|
+
axisTitleStyle: {
|
|
797
|
+
fontSize: 14,
|
|
798
|
+
fontFamily: this.theme.fontFamily,
|
|
799
|
+
color: this.theme.axis?.titleColor
|
|
800
|
+
},
|
|
801
|
+
labelStyle: {
|
|
802
|
+
fontSize: 12,
|
|
803
|
+
fontFamily: this.theme.fontFamily,
|
|
804
|
+
color: this.theme.axis?.labelColor
|
|
805
|
+
},
|
|
806
|
+
autoRange: scichart.EAutoRange.Always
|
|
807
|
+
});
|
|
808
|
+
const yAxis = new scichart.NumericAxis(wasmContext, {
|
|
809
|
+
axisTitle: this.config.yAxis?.title,
|
|
810
|
+
drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? true,
|
|
811
|
+
drawMinorGridLines: false,
|
|
812
|
+
axisTitleStyle: {
|
|
813
|
+
fontSize: 14,
|
|
814
|
+
fontFamily: this.theme.fontFamily,
|
|
815
|
+
color: this.theme.axis?.titleColor
|
|
816
|
+
},
|
|
817
|
+
labelStyle: {
|
|
818
|
+
fontSize: 12,
|
|
819
|
+
fontFamily: this.theme.fontFamily,
|
|
820
|
+
color: this.theme.axis?.labelColor
|
|
821
|
+
},
|
|
822
|
+
autoRange: scichart.EAutoRange.Always,
|
|
823
|
+
growBy: new scichart.NumberRange(0, 0.1)
|
|
824
|
+
});
|
|
825
|
+
if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
|
|
826
|
+
xAxis.visibleRange = new scichart.NumberRange(this.config.xAxis.min, this.config.xAxis.max);
|
|
827
|
+
xAxis.autoRange = scichart.EAutoRange.Never;
|
|
828
|
+
}
|
|
829
|
+
if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
|
|
830
|
+
yAxis.visibleRange = new scichart.NumberRange(this.config.yAxis.min, this.config.yAxis.max);
|
|
831
|
+
yAxis.autoRange = scichart.EAutoRange.Never;
|
|
832
|
+
}
|
|
833
|
+
sciChartSurface.xAxes.add(xAxis);
|
|
834
|
+
sciChartSurface.yAxes.add(yAxis);
|
|
835
|
+
if (this.config.tooltip?.enabled !== false) {
|
|
836
|
+
sciChartSurface.chartModifiers.add(
|
|
837
|
+
new scichart.RolloverModifier({
|
|
838
|
+
showTooltip: true,
|
|
839
|
+
showAxisLabel: true
|
|
840
|
+
})
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
sciChartSurface.chartModifiers.add(new scichart.ZoomPanModifier());
|
|
844
|
+
sciChartSurface.chartModifiers.add(new scichart.MouseWheelZoomModifier());
|
|
845
|
+
this.addSeries(this.config.series);
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Add series to the chart
|
|
849
|
+
*/
|
|
850
|
+
addSeries(seriesConfigs) {
|
|
851
|
+
if (!this.surface || !this.wasmContext) return;
|
|
852
|
+
const wasmContext = this.wasmContext;
|
|
853
|
+
const colorPalette = this.theme.colorPalette ?? [];
|
|
854
|
+
const fillOpacity = this.config.fillOpacity ?? 0.5;
|
|
855
|
+
seriesConfigs.forEach((seriesConfig, index) => {
|
|
856
|
+
const data = normalizeDataPoints(seriesConfig.data);
|
|
857
|
+
const xValues = extractXValues(data);
|
|
858
|
+
const yValues = extractYValues(data);
|
|
859
|
+
const dataSeries = new scichart.XyDataSeries(wasmContext, {
|
|
860
|
+
xValues,
|
|
861
|
+
yValues,
|
|
862
|
+
dataSeriesName: seriesConfig.name
|
|
863
|
+
});
|
|
864
|
+
this.dataSeries.set(seriesConfig.name, dataSeries);
|
|
865
|
+
const color = seriesConfig.color ?? colorPalette[index % colorPalette.length] ?? "#6366f1";
|
|
866
|
+
const areaSeries = new scichart.FastMountainRenderableSeries(wasmContext, {
|
|
867
|
+
dataSeries,
|
|
868
|
+
stroke: color,
|
|
869
|
+
strokeThickness: this.config.lineWidth ?? 2,
|
|
870
|
+
fill: hexToRgba(color, fillOpacity),
|
|
871
|
+
...this.config.animation !== false && {
|
|
872
|
+
animation: new scichart.SweepAnimation({
|
|
873
|
+
duration: typeof this.config.animation === "object" ? this.config.animation.duration ?? 500 : 500
|
|
874
|
+
})
|
|
875
|
+
}
|
|
876
|
+
});
|
|
877
|
+
areaSeries.fillLinearGradient = new scichart.GradientParams(
|
|
878
|
+
new scichart.Point(0, 0),
|
|
879
|
+
new scichart.Point(0, 1),
|
|
880
|
+
[
|
|
881
|
+
{ color: hexToRgba(color, fillOpacity), offset: 0 },
|
|
882
|
+
{ color: hexToRgba(color, 0.05), offset: 1 }
|
|
883
|
+
]
|
|
884
|
+
);
|
|
885
|
+
this.renderableSeries.push(areaSeries);
|
|
886
|
+
this.surface.renderableSeries.add(areaSeries);
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Set new data for the chart
|
|
891
|
+
*/
|
|
892
|
+
setData(data) {
|
|
893
|
+
if (!this.surface) {
|
|
894
|
+
this.config.series = data;
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
this.clearSeries();
|
|
898
|
+
this.config.series = data;
|
|
899
|
+
this.addSeries(data);
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Update specific series data
|
|
903
|
+
*/
|
|
904
|
+
updateSeriesData(seriesName, data) {
|
|
905
|
+
const dataSeries = this.dataSeries.get(seriesName);
|
|
906
|
+
if (!dataSeries) {
|
|
907
|
+
console.warn(`Series "${seriesName}" not found`);
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
const normalized = normalizeDataPoints(data);
|
|
911
|
+
const xValues = extractXValues(normalized);
|
|
912
|
+
const yValues = extractYValues(normalized);
|
|
913
|
+
dataSeries.clear();
|
|
914
|
+
dataSeries.appendRange(xValues, yValues);
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Clear all series
|
|
918
|
+
*/
|
|
919
|
+
clearSeries() {
|
|
920
|
+
if (!this.surface) return;
|
|
921
|
+
this.renderableSeries.forEach((series) => {
|
|
922
|
+
this.surface.renderableSeries.remove(series);
|
|
923
|
+
series.delete();
|
|
924
|
+
});
|
|
925
|
+
this.renderableSeries = [];
|
|
926
|
+
this.dataSeries.forEach((ds) => ds.delete());
|
|
927
|
+
this.dataSeries.clear();
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Update chart
|
|
931
|
+
*/
|
|
932
|
+
update() {
|
|
933
|
+
if (!this.surface) return;
|
|
934
|
+
this.applyTheme();
|
|
935
|
+
this.surface.invalidateElement();
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Destroy and clean up
|
|
939
|
+
*/
|
|
940
|
+
destroy() {
|
|
941
|
+
this.clearSeries();
|
|
942
|
+
super.destroy();
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
async function createAreaChart(container, config) {
|
|
946
|
+
const chart = new AreaChart(config);
|
|
947
|
+
await chart.init(container);
|
|
948
|
+
return chart;
|
|
949
|
+
}
|
|
950
|
+
function getSciChartTheme4(themeName) {
|
|
951
|
+
switch (themeName) {
|
|
952
|
+
case "light":
|
|
953
|
+
return new scichart.SciChartJSLightTheme();
|
|
954
|
+
case "dark":
|
|
955
|
+
case "modern":
|
|
956
|
+
case "midnight":
|
|
957
|
+
default:
|
|
958
|
+
return new scichart.SciChartJSDarkTheme();
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
var defaultColorStops = [
|
|
962
|
+
{ offset: 0, color: "#000080" },
|
|
963
|
+
// Dark blue
|
|
964
|
+
{ offset: 0.2, color: "#0000ff" },
|
|
965
|
+
// Blue
|
|
966
|
+
{ offset: 0.4, color: "#00ffff" },
|
|
967
|
+
// Cyan
|
|
968
|
+
{ offset: 0.6, color: "#00ff00" },
|
|
969
|
+
// Green
|
|
970
|
+
{ offset: 0.8, color: "#ffff00" },
|
|
971
|
+
// Yellow
|
|
972
|
+
{ offset: 1, color: "#ff0000" }
|
|
973
|
+
// Red
|
|
974
|
+
];
|
|
975
|
+
var HeatmapChart = class extends BaseChart {
|
|
976
|
+
constructor(config) {
|
|
977
|
+
super(config);
|
|
978
|
+
this.heatmapDataSeries = null;
|
|
979
|
+
this.heatmapSeries = null;
|
|
980
|
+
this.wasmContext = null;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Create the SciChart surface for heatmap chart
|
|
984
|
+
*/
|
|
985
|
+
async createSurface() {
|
|
986
|
+
if (!this.container) {
|
|
987
|
+
throw new Error("Container not set");
|
|
988
|
+
}
|
|
989
|
+
const sciChartTheme = getSciChartTheme4(this.config.theme);
|
|
990
|
+
if (!this.container.id) {
|
|
991
|
+
this.container.id = this.id;
|
|
992
|
+
}
|
|
993
|
+
const { sciChartSurface, wasmContext } = await scichart.SciChartSurface.create(
|
|
994
|
+
this.container,
|
|
995
|
+
{
|
|
996
|
+
theme: sciChartTheme
|
|
997
|
+
}
|
|
998
|
+
);
|
|
999
|
+
this.surface = sciChartSurface;
|
|
1000
|
+
this.wasmContext = wasmContext;
|
|
1001
|
+
const xAxis = new scichart.NumericAxis(wasmContext, {
|
|
1002
|
+
axisTitle: this.config.xAxis?.title,
|
|
1003
|
+
drawMajorGridLines: this.config.xAxis?.gridLines?.show ?? false,
|
|
1004
|
+
drawMinorGridLines: false,
|
|
1005
|
+
axisTitleStyle: {
|
|
1006
|
+
fontSize: 14,
|
|
1007
|
+
fontFamily: this.theme.fontFamily,
|
|
1008
|
+
color: this.theme.axis?.titleColor
|
|
1009
|
+
},
|
|
1010
|
+
labelStyle: {
|
|
1011
|
+
fontSize: 12,
|
|
1012
|
+
fontFamily: this.theme.fontFamily,
|
|
1013
|
+
color: this.theme.axis?.labelColor
|
|
1014
|
+
},
|
|
1015
|
+
autoRange: scichart.EAutoRange.Always
|
|
1016
|
+
});
|
|
1017
|
+
const yAxis = new scichart.NumericAxis(wasmContext, {
|
|
1018
|
+
axisTitle: this.config.yAxis?.title,
|
|
1019
|
+
drawMajorGridLines: this.config.yAxis?.gridLines?.show ?? false,
|
|
1020
|
+
drawMinorGridLines: false,
|
|
1021
|
+
axisTitleStyle: {
|
|
1022
|
+
fontSize: 14,
|
|
1023
|
+
fontFamily: this.theme.fontFamily,
|
|
1024
|
+
color: this.theme.axis?.titleColor
|
|
1025
|
+
},
|
|
1026
|
+
labelStyle: {
|
|
1027
|
+
fontSize: 12,
|
|
1028
|
+
fontFamily: this.theme.fontFamily,
|
|
1029
|
+
color: this.theme.axis?.labelColor
|
|
1030
|
+
},
|
|
1031
|
+
autoRange: scichart.EAutoRange.Always
|
|
1032
|
+
});
|
|
1033
|
+
if (this.config.xAxis?.min !== void 0 && this.config.xAxis?.max !== void 0) {
|
|
1034
|
+
xAxis.visibleRange = new scichart.NumberRange(this.config.xAxis.min, this.config.xAxis.max);
|
|
1035
|
+
xAxis.autoRange = scichart.EAutoRange.Never;
|
|
1036
|
+
}
|
|
1037
|
+
if (this.config.yAxis?.min !== void 0 && this.config.yAxis?.max !== void 0) {
|
|
1038
|
+
yAxis.visibleRange = new scichart.NumberRange(this.config.yAxis.min, this.config.yAxis.max);
|
|
1039
|
+
yAxis.autoRange = scichart.EAutoRange.Never;
|
|
1040
|
+
}
|
|
1041
|
+
sciChartSurface.xAxes.add(xAxis);
|
|
1042
|
+
sciChartSurface.yAxes.add(yAxis);
|
|
1043
|
+
if (this.config.tooltip?.enabled !== false) {
|
|
1044
|
+
sciChartSurface.chartModifiers.add(
|
|
1045
|
+
new scichart.RolloverModifier({
|
|
1046
|
+
showTooltip: true,
|
|
1047
|
+
showAxisLabel: true
|
|
1048
|
+
})
|
|
1049
|
+
);
|
|
1050
|
+
}
|
|
1051
|
+
sciChartSurface.chartModifiers.add(new scichart.ZoomPanModifier());
|
|
1052
|
+
sciChartSurface.chartModifiers.add(new scichart.MouseWheelZoomModifier());
|
|
1053
|
+
this.addHeatmapData(this.config.zValues);
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1056
|
+
* Add heatmap data to the chart
|
|
1057
|
+
*/
|
|
1058
|
+
addHeatmapData(zValues) {
|
|
1059
|
+
if (!this.surface || !this.wasmContext) return;
|
|
1060
|
+
const wasmContext = this.wasmContext;
|
|
1061
|
+
let min = this.config.colorMin;
|
|
1062
|
+
let max = this.config.colorMax;
|
|
1063
|
+
if (min === void 0 || max === void 0) {
|
|
1064
|
+
const flatValues = zValues.flat();
|
|
1065
|
+
min = min ?? Math.min(...flatValues);
|
|
1066
|
+
max = max ?? Math.max(...flatValues);
|
|
1067
|
+
}
|
|
1068
|
+
this.heatmapDataSeries = new scichart.UniformHeatmapDataSeries(wasmContext, {
|
|
1069
|
+
zValues,
|
|
1070
|
+
xStart: this.config.xStart ?? 0,
|
|
1071
|
+
xStep: this.config.xStep ?? 1,
|
|
1072
|
+
yStart: this.config.yStart ?? 0,
|
|
1073
|
+
yStep: this.config.yStep ?? 1
|
|
1074
|
+
});
|
|
1075
|
+
const colorStops = this.config.colorStops ?? defaultColorStops;
|
|
1076
|
+
this.heatmapSeries = new scichart.UniformHeatmapRenderableSeries(wasmContext, {
|
|
1077
|
+
dataSeries: this.heatmapDataSeries,
|
|
1078
|
+
colorMap: new scichart.HeatmapColorMap({
|
|
1079
|
+
minimum: min,
|
|
1080
|
+
maximum: max,
|
|
1081
|
+
gradientStops: colorStops
|
|
1082
|
+
})
|
|
1083
|
+
});
|
|
1084
|
+
this.surface.renderableSeries.add(this.heatmapSeries);
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Set new data for the chart (for heatmap, this updates zValues)
|
|
1088
|
+
*/
|
|
1089
|
+
setData(_data) {
|
|
1090
|
+
console.warn("HeatmapChart.setData() - use setZValues() for updating heatmap data");
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Set new z-values for the heatmap
|
|
1094
|
+
*/
|
|
1095
|
+
setZValues(zValues) {
|
|
1096
|
+
if (!this.surface) {
|
|
1097
|
+
this.config.zValues = zValues;
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
this.clearHeatmap();
|
|
1101
|
+
this.config.zValues = zValues;
|
|
1102
|
+
this.addHeatmapData(zValues);
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Update specific cell values
|
|
1106
|
+
*/
|
|
1107
|
+
updateCell(x, y, value) {
|
|
1108
|
+
if (this.heatmapDataSeries) {
|
|
1109
|
+
this.heatmapDataSeries.setZValue(x, y, value);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Clear heatmap data
|
|
1114
|
+
*/
|
|
1115
|
+
clearHeatmap() {
|
|
1116
|
+
if (!this.surface) return;
|
|
1117
|
+
if (this.heatmapSeries) {
|
|
1118
|
+
this.surface.renderableSeries.remove(this.heatmapSeries);
|
|
1119
|
+
this.heatmapSeries.delete();
|
|
1120
|
+
this.heatmapSeries = null;
|
|
1121
|
+
}
|
|
1122
|
+
if (this.heatmapDataSeries) {
|
|
1123
|
+
this.heatmapDataSeries.delete();
|
|
1124
|
+
this.heatmapDataSeries = null;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Update chart
|
|
1129
|
+
*/
|
|
1130
|
+
update() {
|
|
1131
|
+
if (!this.surface) return;
|
|
1132
|
+
this.applyTheme();
|
|
1133
|
+
this.surface.invalidateElement();
|
|
1134
|
+
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Destroy and clean up
|
|
1137
|
+
*/
|
|
1138
|
+
destroy() {
|
|
1139
|
+
this.clearHeatmap();
|
|
1140
|
+
super.destroy();
|
|
1141
|
+
}
|
|
1142
|
+
};
|
|
1143
|
+
async function createHeatmapChart(container, config) {
|
|
1144
|
+
const chart = new HeatmapChart(config);
|
|
1145
|
+
await chart.init(container);
|
|
1146
|
+
return chart;
|
|
1147
|
+
}
|
|
1148
|
+
var defaultColorStops2 = [
|
|
1149
|
+
{ offset: 0, color: "#1e3a8a" },
|
|
1150
|
+
// Dark blue
|
|
1151
|
+
{ offset: 0.25, color: "#3b82f6" },
|
|
1152
|
+
// Blue
|
|
1153
|
+
{ offset: 0.5, color: "#22c55e" },
|
|
1154
|
+
// Green
|
|
1155
|
+
{ offset: 0.75, color: "#eab308" },
|
|
1156
|
+
// Yellow
|
|
1157
|
+
{ offset: 1, color: "#ef4444" }
|
|
1158
|
+
// Red
|
|
1159
|
+
];
|
|
1160
|
+
var Surface3DChart = class {
|
|
1161
|
+
constructor(config) {
|
|
1162
|
+
this.container = null;
|
|
1163
|
+
this.surface = null;
|
|
1164
|
+
this.wasmContext = null;
|
|
1165
|
+
this.dataSeries = null;
|
|
1166
|
+
this.meshSeries = null;
|
|
1167
|
+
this.isDestroyed = false;
|
|
1168
|
+
this.id = config.id ?? generateId("chart3d");
|
|
1169
|
+
this.config = config;
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Initialize the chart in the given container
|
|
1173
|
+
*/
|
|
1174
|
+
async init(container) {
|
|
1175
|
+
if (this.isDestroyed) {
|
|
1176
|
+
throw new Error("Cannot initialize a destroyed chart");
|
|
1177
|
+
}
|
|
1178
|
+
if (typeof container === "string") {
|
|
1179
|
+
const el = document.getElementById(container);
|
|
1180
|
+
if (!el) {
|
|
1181
|
+
throw new Error(`Container element "${container}" not found`);
|
|
1182
|
+
}
|
|
1183
|
+
this.container = el;
|
|
1184
|
+
} else {
|
|
1185
|
+
this.container = container;
|
|
1186
|
+
}
|
|
1187
|
+
if (!this.container.id) {
|
|
1188
|
+
this.container.id = this.id;
|
|
1189
|
+
}
|
|
1190
|
+
await this.createSurface();
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Create the SciChart 3D surface
|
|
1194
|
+
*/
|
|
1195
|
+
async createSurface() {
|
|
1196
|
+
if (!this.container) {
|
|
1197
|
+
throw new Error("Container not set");
|
|
1198
|
+
}
|
|
1199
|
+
const { sciChart3DSurface, wasmContext } = await scichart.SciChart3DSurface.create(
|
|
1200
|
+
this.container.id
|
|
1201
|
+
);
|
|
1202
|
+
this.surface = sciChart3DSurface;
|
|
1203
|
+
this.wasmContext = wasmContext;
|
|
1204
|
+
sciChart3DSurface.xAxis = new scichart.NumericAxis3D(wasmContext, {
|
|
1205
|
+
axisTitle: "X"
|
|
1206
|
+
});
|
|
1207
|
+
sciChart3DSurface.yAxis = new scichart.NumericAxis3D(wasmContext, {
|
|
1208
|
+
axisTitle: "Y"
|
|
1209
|
+
});
|
|
1210
|
+
sciChart3DSurface.zAxis = new scichart.NumericAxis3D(wasmContext, {
|
|
1211
|
+
axisTitle: "Z"
|
|
1212
|
+
});
|
|
1213
|
+
sciChart3DSurface.chartModifiers.add(new scichart.MouseWheelZoomModifier3D());
|
|
1214
|
+
sciChart3DSurface.chartModifiers.add(new scichart.OrbitModifier3D());
|
|
1215
|
+
const cameraPos = this.config.cameraPosition ?? { x: 300, y: 300, z: 300 };
|
|
1216
|
+
sciChart3DSurface.camera = new scichart.CameraController(wasmContext, {
|
|
1217
|
+
position: new scichart.Vector3(cameraPos.x, cameraPos.y, cameraPos.z),
|
|
1218
|
+
target: new scichart.Vector3(0, 0, 0)
|
|
1219
|
+
});
|
|
1220
|
+
this.addSurfaceData(this.config.yValues);
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Add surface data to the chart
|
|
1224
|
+
*/
|
|
1225
|
+
addSurfaceData(yValues) {
|
|
1226
|
+
if (!this.surface || !this.wasmContext) return;
|
|
1227
|
+
const wasmContext = this.wasmContext;
|
|
1228
|
+
const zSize = yValues.length;
|
|
1229
|
+
const xSize = yValues[0]?.length ?? 0;
|
|
1230
|
+
let min = Infinity;
|
|
1231
|
+
let max = -Infinity;
|
|
1232
|
+
for (let z = 0; z < zSize; z++) {
|
|
1233
|
+
for (let x = 0; x < xSize; x++) {
|
|
1234
|
+
const y = yValues[z][x];
|
|
1235
|
+
min = Math.min(min, y);
|
|
1236
|
+
max = Math.max(max, y);
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
this.dataSeries = new scichart.UniformGridDataSeries3D(wasmContext, {
|
|
1240
|
+
yValues,
|
|
1241
|
+
xStep: this.config.xStep ?? 1,
|
|
1242
|
+
zStep: this.config.zStep ?? 1
|
|
1243
|
+
});
|
|
1244
|
+
const colorStops = this.config.colorStops ?? defaultColorStops2;
|
|
1245
|
+
const colorPalette = new scichart.GradientColorPalette(wasmContext, {
|
|
1246
|
+
gradientStops: colorStops
|
|
1247
|
+
});
|
|
1248
|
+
this.meshSeries = new scichart.SurfaceMeshRenderableSeries3D(wasmContext, {
|
|
1249
|
+
dataSeries: this.dataSeries,
|
|
1250
|
+
minimum: this.config.colorMin ?? min,
|
|
1251
|
+
maximum: this.config.colorMax ?? max,
|
|
1252
|
+
opacity: this.config.opacity ?? 1,
|
|
1253
|
+
cellHardnessFactor: 0,
|
|
1254
|
+
// Smooth interpolation between cells
|
|
1255
|
+
stroke: "transparent",
|
|
1256
|
+
// No wireframe stroke
|
|
1257
|
+
strokeThickness: 0,
|
|
1258
|
+
contourStroke: "transparent",
|
|
1259
|
+
// No contour lines
|
|
1260
|
+
contourStrokeThickness: 0,
|
|
1261
|
+
drawSkirt: true,
|
|
1262
|
+
// Draw skirt for solid appearance
|
|
1263
|
+
drawMeshAs: scichart.EDrawMeshAs.SOLID_MESH,
|
|
1264
|
+
// Solid filled surface
|
|
1265
|
+
lightingFactor: 0.8,
|
|
1266
|
+
meshColorPalette: colorPalette,
|
|
1267
|
+
shininess: 10
|
|
1268
|
+
});
|
|
1269
|
+
this.surface.renderableSeries.add(this.meshSeries);
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Set new Y values for the surface
|
|
1273
|
+
*/
|
|
1274
|
+
setYValues(yValues) {
|
|
1275
|
+
if (!this.surface) {
|
|
1276
|
+
this.config.yValues = yValues;
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
this.clearSurface();
|
|
1280
|
+
this.config.yValues = yValues;
|
|
1281
|
+
this.addSurfaceData(yValues);
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Set new data (alias for setYValues for consistency)
|
|
1285
|
+
*/
|
|
1286
|
+
setData(_data) {
|
|
1287
|
+
console.warn("Surface3DChart.setData() - use setYValues() for updating surface data");
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Update chart options
|
|
1291
|
+
*/
|
|
1292
|
+
setOptions(options) {
|
|
1293
|
+
this.config = { ...this.config, ...options };
|
|
1294
|
+
if (options.cameraPosition && this.surface && this.wasmContext) {
|
|
1295
|
+
const pos = options.cameraPosition;
|
|
1296
|
+
this.surface.camera = new scichart.CameraController(this.wasmContext, {
|
|
1297
|
+
position: new scichart.Vector3(pos.x, pos.y, pos.z),
|
|
1298
|
+
target: new scichart.Vector3(0, 0, 0)
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Clear surface data
|
|
1304
|
+
*/
|
|
1305
|
+
clearSurface() {
|
|
1306
|
+
if (!this.surface) return;
|
|
1307
|
+
if (this.meshSeries) {
|
|
1308
|
+
this.surface.renderableSeries.remove(this.meshSeries);
|
|
1309
|
+
this.meshSeries.delete();
|
|
1310
|
+
this.meshSeries = null;
|
|
1311
|
+
}
|
|
1312
|
+
if (this.dataSeries) {
|
|
1313
|
+
this.dataSeries.delete();
|
|
1314
|
+
this.dataSeries = null;
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Destroy and clean up
|
|
1319
|
+
*/
|
|
1320
|
+
destroy() {
|
|
1321
|
+
if (this.isDestroyed) return;
|
|
1322
|
+
this.clearSurface();
|
|
1323
|
+
if (this.surface) {
|
|
1324
|
+
this.surface.delete();
|
|
1325
|
+
this.surface = null;
|
|
1326
|
+
}
|
|
1327
|
+
this.isDestroyed = true;
|
|
1328
|
+
}
|
|
1329
|
+
/**
|
|
1330
|
+
* Get current configuration
|
|
1331
|
+
*/
|
|
1332
|
+
getConfig() {
|
|
1333
|
+
return { ...this.config };
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
* Check if chart is ready (initialized and not destroyed)
|
|
1337
|
+
*/
|
|
1338
|
+
isReady() {
|
|
1339
|
+
return this.surface !== null && !this.isDestroyed;
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
async function createSurface3DChart(container, config) {
|
|
1343
|
+
const chart = new Surface3DChart(config);
|
|
1344
|
+
await chart.init(container);
|
|
1345
|
+
return chart;
|
|
1346
|
+
}
|
|
1347
|
+
var Column3DChart = class {
|
|
1348
|
+
constructor(config) {
|
|
1349
|
+
this.container = null;
|
|
1350
|
+
this.surface = null;
|
|
1351
|
+
this.wasmContext = null;
|
|
1352
|
+
this.dataSeries = null;
|
|
1353
|
+
this.columnSeries = null;
|
|
1354
|
+
this.isDestroyed = false;
|
|
1355
|
+
this.id = config.id ?? generateId("column3d");
|
|
1356
|
+
this.config = config;
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* Initialize the chart in the given container
|
|
1360
|
+
*/
|
|
1361
|
+
async init(container) {
|
|
1362
|
+
if (this.isDestroyed) {
|
|
1363
|
+
throw new Error("Cannot initialize a destroyed chart");
|
|
1364
|
+
}
|
|
1365
|
+
if (typeof container === "string") {
|
|
1366
|
+
const el = document.getElementById(container);
|
|
1367
|
+
if (!el) {
|
|
1368
|
+
throw new Error(`Container element "${container}" not found`);
|
|
1369
|
+
}
|
|
1370
|
+
this.container = el;
|
|
1371
|
+
} else {
|
|
1372
|
+
this.container = container;
|
|
1373
|
+
}
|
|
1374
|
+
if (!this.container.id) {
|
|
1375
|
+
this.container.id = this.id;
|
|
1376
|
+
}
|
|
1377
|
+
await this.createSurface();
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* Create the SciChart 3D surface
|
|
1381
|
+
*/
|
|
1382
|
+
async createSurface() {
|
|
1383
|
+
if (!this.container) {
|
|
1384
|
+
throw new Error("Container not set");
|
|
1385
|
+
}
|
|
1386
|
+
const { sciChart3DSurface, wasmContext } = await scichart.SciChart3DSurface.create(
|
|
1387
|
+
this.container.id,
|
|
1388
|
+
{
|
|
1389
|
+
isZYPlaneVisible: false
|
|
1390
|
+
}
|
|
1391
|
+
);
|
|
1392
|
+
this.surface = sciChart3DSurface;
|
|
1393
|
+
this.wasmContext = wasmContext;
|
|
1394
|
+
const cameraPos = this.config.cameraPosition ?? { x: -250, y: 450, z: 280 };
|
|
1395
|
+
const cameraTarget = this.config.cameraTarget ?? { x: 0, y: 0, z: 0 };
|
|
1396
|
+
sciChart3DSurface.camera = new scichart.CameraController(wasmContext, {
|
|
1397
|
+
position: new scichart.Vector3(cameraPos.x, cameraPos.y, cameraPos.z),
|
|
1398
|
+
target: new scichart.Vector3(cameraTarget.x, cameraTarget.y, cameraTarget.z)
|
|
1399
|
+
});
|
|
1400
|
+
sciChart3DSurface.chartModifiers.add(
|
|
1401
|
+
new scichart.OrbitModifier3D(),
|
|
1402
|
+
new scichart.MouseWheelZoomModifier3D()
|
|
1403
|
+
);
|
|
1404
|
+
const xRange = this.config.xRange ?? { min: 0, max: 360 };
|
|
1405
|
+
const yRange = this.config.yRange ?? { min: 0, max: 5e3 };
|
|
1406
|
+
const zRange = this.config.zRange ?? { min: 0, max: 50 };
|
|
1407
|
+
const baseAxisOptions = {
|
|
1408
|
+
drawMinorGridLines: false,
|
|
1409
|
+
majorGridLineStyle: { color: "#7e7e7e" },
|
|
1410
|
+
planeBorderThickness: 3
|
|
1411
|
+
};
|
|
1412
|
+
sciChart3DSurface.xAxis = new scichart.NumericAxis3D(wasmContext, {
|
|
1413
|
+
...baseAxisOptions,
|
|
1414
|
+
axisTitle: this.config.xAxisTitle ?? "Phase Angle (\xB0)",
|
|
1415
|
+
autoTicks: false,
|
|
1416
|
+
visibleRange: new scichart.NumberRange(xRange.min, xRange.max),
|
|
1417
|
+
majorDelta: 45,
|
|
1418
|
+
minorDelta: 15,
|
|
1419
|
+
flippedCoordinates: true,
|
|
1420
|
+
axisBandsFill: "#d2d2d2"
|
|
1421
|
+
});
|
|
1422
|
+
sciChart3DSurface.yAxis = new scichart.NumericAxis3D(wasmContext, {
|
|
1423
|
+
...baseAxisOptions,
|
|
1424
|
+
axisTitle: this.config.yAxisTitle ?? "Amplitude (mVp)",
|
|
1425
|
+
visibleRange: new scichart.NumberRange(yRange.min, yRange.max),
|
|
1426
|
+
axisBandsFill: "#b1b1b1"
|
|
1427
|
+
});
|
|
1428
|
+
sciChart3DSurface.zAxis = new scichart.NumericAxis3D(wasmContext, {
|
|
1429
|
+
...baseAxisOptions,
|
|
1430
|
+
axisTitle: this.config.zAxisTitle ?? "Cycle",
|
|
1431
|
+
majorDelta: 10,
|
|
1432
|
+
minorDelta: 5,
|
|
1433
|
+
visibleRange: new scichart.NumberRange(zRange.min, zRange.max),
|
|
1434
|
+
axisBandsFill: "#d0d0d0",
|
|
1435
|
+
labelPrecision: 0
|
|
1436
|
+
});
|
|
1437
|
+
this.addColumnData(this.config.data);
|
|
1438
|
+
if (this.config.showSineWave !== false) {
|
|
1439
|
+
this.addSineWave();
|
|
1440
|
+
}
|
|
1441
|
+
this.addTooltip();
|
|
1442
|
+
}
|
|
1443
|
+
/**
|
|
1444
|
+
* Add column data to the chart
|
|
1445
|
+
*/
|
|
1446
|
+
addColumnData(data) {
|
|
1447
|
+
if (!this.surface || !this.wasmContext) return;
|
|
1448
|
+
const wasmContext = this.wasmContext;
|
|
1449
|
+
this.dataSeries = new scichart.XyzDataSeries3D(wasmContext);
|
|
1450
|
+
data.forEach(([x, y, z]) => {
|
|
1451
|
+
this.dataSeries.append(x, y, z);
|
|
1452
|
+
});
|
|
1453
|
+
this.columnSeries = new scichart.ColumnRenderableSeries3D(wasmContext, {
|
|
1454
|
+
dataSeries: this.dataSeries,
|
|
1455
|
+
fill: this.config.barFill ?? "#52aaf2",
|
|
1456
|
+
stroke: this.config.barStroke ?? "#52aaf2",
|
|
1457
|
+
opacity: this.config.barOpacity ?? 0.95,
|
|
1458
|
+
dataPointWidthX: this.config.barWidthX ?? 8,
|
|
1459
|
+
dataPointWidthZ: this.config.barWidthZ ?? 8
|
|
1460
|
+
});
|
|
1461
|
+
this.surface.renderableSeries.add(this.columnSeries);
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Add sine wave reference line on back plane
|
|
1465
|
+
*/
|
|
1466
|
+
addSineWave() {
|
|
1467
|
+
if (!this.surface || !this.wasmContext) return;
|
|
1468
|
+
const wasmContext = this.wasmContext;
|
|
1469
|
+
const sineData = new scichart.XyzDataSeries3D(wasmContext);
|
|
1470
|
+
const backPlaneZ = 0;
|
|
1471
|
+
const center = this.config.sineWaveCenter ?? 2e3;
|
|
1472
|
+
const amplitude = this.config.sineWaveAmplitude ?? 2e3;
|
|
1473
|
+
for (let deg = 0; deg <= 360; deg += 5) {
|
|
1474
|
+
const rad = deg * Math.PI / 180;
|
|
1475
|
+
const y = center + amplitude * Math.sin(rad);
|
|
1476
|
+
sineData.append(deg, y, backPlaneZ);
|
|
1477
|
+
}
|
|
1478
|
+
const sineSeries = new scichart.PointLineRenderableSeries3D(wasmContext, {
|
|
1479
|
+
dataSeries: sineData,
|
|
1480
|
+
stroke: "black",
|
|
1481
|
+
strokeThickness: 3,
|
|
1482
|
+
opacity: 1
|
|
1483
|
+
});
|
|
1484
|
+
this.surface.renderableSeries.add(sineSeries);
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
* Add tooltip modifier
|
|
1488
|
+
*/
|
|
1489
|
+
addTooltip() {
|
|
1490
|
+
if (!this.surface) return;
|
|
1491
|
+
const xTitle = this.config.xAxisTitle ?? "Phase Angle";
|
|
1492
|
+
const yTitle = this.config.yAxisTitle ?? "Amplitude";
|
|
1493
|
+
const zTitle = this.config.zAxisTitle ?? "Cycle";
|
|
1494
|
+
const tooltipModifier = new scichart.TooltipModifier3D({
|
|
1495
|
+
tooltipDataTemplate: (seriesInfo) => {
|
|
1496
|
+
const valuesWithLabels = [];
|
|
1497
|
+
if (seriesInfo && seriesInfo.isHit) {
|
|
1498
|
+
valuesWithLabels.push(`${xTitle}: ${seriesInfo.xValue}`);
|
|
1499
|
+
valuesWithLabels.push(`${yTitle}: ${seriesInfo.yValue}`);
|
|
1500
|
+
valuesWithLabels.push(`${zTitle}: ${seriesInfo.zValue}`);
|
|
1501
|
+
}
|
|
1502
|
+
return valuesWithLabels;
|
|
1503
|
+
}
|
|
1504
|
+
});
|
|
1505
|
+
this.surface.chartModifiers.add(tooltipModifier);
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Set new data for the chart
|
|
1509
|
+
*/
|
|
1510
|
+
setData(data) {
|
|
1511
|
+
if (!this.dataSeries) {
|
|
1512
|
+
this.config.data = data;
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1515
|
+
this.dataSeries.clear();
|
|
1516
|
+
data.forEach(([x, y, z]) => {
|
|
1517
|
+
this.dataSeries.append(x, y, z);
|
|
1518
|
+
});
|
|
1519
|
+
if (this.surface) {
|
|
1520
|
+
this.surface.invalidateElement();
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
/**
|
|
1524
|
+
* Update camera position
|
|
1525
|
+
*/
|
|
1526
|
+
setCameraPosition(position, target) {
|
|
1527
|
+
if (!this.surface || !this.wasmContext) return;
|
|
1528
|
+
this.surface.camera.position = new scichart.Vector3(position.x, position.y, position.z);
|
|
1529
|
+
if (target) {
|
|
1530
|
+
this.surface.camera.target = new scichart.Vector3(target.x, target.y, target.z);
|
|
1531
|
+
}
|
|
1532
|
+
this.surface.invalidateElement();
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Update chart options
|
|
1536
|
+
*/
|
|
1537
|
+
setOptions(options) {
|
|
1538
|
+
this.config = { ...this.config, ...options };
|
|
1539
|
+
if (options.cameraPosition && this.surface && this.wasmContext) {
|
|
1540
|
+
const pos = options.cameraPosition;
|
|
1541
|
+
const target = options.cameraTarget ?? { x: 0, y: 0, z: 0 };
|
|
1542
|
+
this.setCameraPosition(pos, target);
|
|
1543
|
+
}
|
|
1544
|
+
if (options.barFill || options.barStroke || options.barOpacity) {
|
|
1545
|
+
if (this.columnSeries) {
|
|
1546
|
+
if (options.barFill) this.columnSeries.fill = options.barFill;
|
|
1547
|
+
if (options.barStroke) this.columnSeries.stroke = options.barStroke;
|
|
1548
|
+
if (options.barOpacity !== void 0) this.columnSeries.opacity = options.barOpacity;
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Get the SciChart surface for advanced operations
|
|
1554
|
+
*/
|
|
1555
|
+
getSurface() {
|
|
1556
|
+
return this.surface;
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Destroy and clean up
|
|
1560
|
+
*/
|
|
1561
|
+
destroy() {
|
|
1562
|
+
if (this.isDestroyed) return;
|
|
1563
|
+
if (this.surface) {
|
|
1564
|
+
this.surface.delete();
|
|
1565
|
+
this.surface = null;
|
|
1566
|
+
}
|
|
1567
|
+
this.isDestroyed = true;
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Get current configuration
|
|
1571
|
+
*/
|
|
1572
|
+
getConfig() {
|
|
1573
|
+
return { ...this.config };
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Check if chart is ready (initialized and not destroyed)
|
|
1577
|
+
*/
|
|
1578
|
+
isReady() {
|
|
1579
|
+
return this.surface !== null && !this.isDestroyed;
|
|
1580
|
+
}
|
|
1581
|
+
};
|
|
1582
|
+
async function createColumn3DChart(container, config) {
|
|
1583
|
+
const chart = new Column3DChart(config);
|
|
1584
|
+
await chart.init(container);
|
|
1585
|
+
return chart;
|
|
1586
|
+
}
|
|
1587
|
+
var VERSION = "0.1.0";
|
|
1588
|
+
function configureSciChart(options) {
|
|
1589
|
+
if (options.wasmUrl || options.dataUrl) {
|
|
1590
|
+
const { SciChartSurface: SciChartSurface6 } = chunkKATRK3C3_js.__require("scichart");
|
|
1591
|
+
SciChartSurface6.configure({
|
|
1592
|
+
wasmUrl: options.wasmUrl,
|
|
1593
|
+
dataUrl: options.dataUrl
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
Object.defineProperty(exports, "ThemeManager", {
|
|
1599
|
+
enumerable: true,
|
|
1600
|
+
get: function () { return chunkKATRK3C3_js.ThemeManager; }
|
|
1601
|
+
});
|
|
1602
|
+
Object.defineProperty(exports, "darkTheme", {
|
|
1603
|
+
enumerable: true,
|
|
1604
|
+
get: function () { return chunkKATRK3C3_js.darkTheme; }
|
|
1605
|
+
});
|
|
1606
|
+
Object.defineProperty(exports, "getThemeManager", {
|
|
1607
|
+
enumerable: true,
|
|
1608
|
+
get: function () { return chunkKATRK3C3_js.getThemeManager; }
|
|
1609
|
+
});
|
|
1610
|
+
Object.defineProperty(exports, "lightTheme", {
|
|
1611
|
+
enumerable: true,
|
|
1612
|
+
get: function () { return chunkKATRK3C3_js.lightTheme; }
|
|
1613
|
+
});
|
|
1614
|
+
Object.defineProperty(exports, "midnightTheme", {
|
|
1615
|
+
enumerable: true,
|
|
1616
|
+
get: function () { return chunkKATRK3C3_js.midnightTheme; }
|
|
1617
|
+
});
|
|
1618
|
+
Object.defineProperty(exports, "modernTheme", {
|
|
1619
|
+
enumerable: true,
|
|
1620
|
+
get: function () { return chunkKATRK3C3_js.modernTheme; }
|
|
1621
|
+
});
|
|
1622
|
+
Object.defineProperty(exports, "SciChartSurface", {
|
|
1623
|
+
enumerable: true,
|
|
1624
|
+
get: function () { return scichart.SciChartSurface; }
|
|
1625
|
+
});
|
|
1626
|
+
exports.AreaChart = AreaChart;
|
|
1627
|
+
exports.BarChart = BarChart;
|
|
1628
|
+
exports.BaseChart = BaseChart;
|
|
1629
|
+
exports.Column3DChart = Column3DChart;
|
|
1630
|
+
exports.HeatmapChart = HeatmapChart;
|
|
1631
|
+
exports.LineChart = LineChart;
|
|
1632
|
+
exports.Surface3DChart = Surface3DChart;
|
|
1633
|
+
exports.VERSION = VERSION;
|
|
1634
|
+
exports.calculateDataRange = calculateDataRange;
|
|
1635
|
+
exports.clamp = clamp;
|
|
1636
|
+
exports.configureSciChart = configureSciChart;
|
|
1637
|
+
exports.createAreaChart = createAreaChart;
|
|
1638
|
+
exports.createBarChart = createBarChart;
|
|
1639
|
+
exports.createColumn3DChart = createColumn3DChart;
|
|
1640
|
+
exports.createHeatmapChart = createHeatmapChart;
|
|
1641
|
+
exports.createLineChart = createLineChart;
|
|
1642
|
+
exports.createSurface3DChart = createSurface3DChart;
|
|
1643
|
+
exports.debounce = debounce;
|
|
1644
|
+
exports.deepMerge = deepMerge;
|
|
1645
|
+
exports.extractXValues = extractXValues;
|
|
1646
|
+
exports.extractYValues = extractYValues;
|
|
1647
|
+
exports.formatNumber = formatNumber;
|
|
1648
|
+
exports.generateId = generateId;
|
|
1649
|
+
exports.hexToRgba = hexToRgba;
|
|
1650
|
+
exports.lerp = lerp;
|
|
1651
|
+
exports.normalizeDataPoints = normalizeDataPoints;
|
|
1652
|
+
exports.parseSize = parseSize;
|
|
1653
|
+
exports.throttle = throttle;
|
|
1654
|
+
//# sourceMappingURL=index.js.map
|
|
1655
|
+
//# sourceMappingURL=index.js.map
|