@operato/scene-scichart 7.0.7 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/db.sqlite +0 -0
  3. package/dist/charts/axis-synchronizer.d.ts +10 -0
  4. package/dist/charts/axis-synchronizer.js +32 -0
  5. package/dist/charts/axis-synchronizer.js.map +1 -0
  6. package/dist/charts/ox-scichart-multiple.d.ts +40 -0
  7. package/dist/charts/ox-scichart-multiple.js +272 -0
  8. package/dist/charts/ox-scichart-multiple.js.map +1 -0
  9. package/dist/charts/ox-scichart.d.ts +1 -1
  10. package/dist/charts/ox-scichart.js.map +1 -1
  11. package/dist/charts/scichart-builder.d.ts +10 -1
  12. package/dist/charts/scichart-builder.js +80 -8
  13. package/dist/charts/scichart-builder.js.map +1 -1
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +1 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/scichart-multiple-timeseries.d.ts +14 -0
  18. package/dist/scichart-multiple-timeseries.js +60 -0
  19. package/dist/scichart-multiple-timeseries.js.map +1 -0
  20. package/dist/scichart-timeseries.d.ts +2 -11
  21. package/dist/scichart-timeseries.js +2 -42
  22. package/dist/scichart-timeseries.js.map +1 -1
  23. package/dist/templates/index.js +2 -1
  24. package/dist/templates/index.js.map +1 -1
  25. package/dist/templates/scichart-multiple-timeseries.d.ts +53 -0
  26. package/dist/templates/scichart-multiple-timeseries.js +81 -0
  27. package/dist/templates/scichart-multiple-timeseries.js.map +1 -0
  28. package/helps/scene/component/scichart-multiple-timeseries.md +23 -0
  29. package/helps/scene/component/scichart-timeseries.md +18 -0
  30. package/icons/scichart-multiple-timeseries.png +0 -0
  31. package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +11 -6
  32. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +18 -23
  33. package/logs/{application-2024-07-13-21.log → application-2024-07-28-03.log} +8 -8
  34. package/logs/{application-2024-07-13-20.log → application-2024-07-28-17.log} +32 -36
  35. package/logs/application-2024-07-28-18.log +210 -0
  36. package/logs/connections-2024-07-23-14.log +50 -0
  37. package/logs/connections-2024-07-25-23.log +50 -0
  38. package/logs/connections-2024-07-26-18.log +50 -0
  39. package/logs/connections-2024-07-28-03.log +50 -0
  40. package/logs/connections-2024-07-28-17.log +200 -0
  41. package/logs/connections-2024-07-28-18.log +100 -0
  42. package/package.json +2 -2
  43. package/schema.graphql +112 -0
  44. package/src/charts/axis-synchronizer.ts +37 -0
  45. package/src/charts/ox-scichart-multiple.ts +334 -0
  46. package/src/charts/ox-scichart.ts +1 -1
  47. package/src/charts/scichart-builder.ts +109 -8
  48. package/src/index.ts +1 -0
  49. package/src/scichart-multiple-timeseries.ts +74 -0
  50. package/src/scichart-timeseries.ts +3 -54
  51. package/src/templates/index.ts +2 -1
  52. package/src/templates/scichart-multiple-timeseries.ts +87 -0
  53. package/things-scene.config.js +0 -2
  54. package/translations/en.json +3 -1
  55. package/translations/ja.json +3 -1
  56. package/translations/ko.json +3 -1
  57. package/translations/ms.json +3 -1
  58. package/translations/zh.json +3 -1
  59. package/tsconfig.tsbuildinfo +1 -1
  60. package/cache/translations/system/en.json +0 -1
  61. package/cache/translations/system/ko.json +0 -1
  62. package/logs/connections-2024-07-08-22.log +0 -50
  63. package/logs/connections-2024-07-08-23.log +0 -100
  64. package/logs/connections-2024-07-09-15.log +0 -100
  65. package/logs/connections-2024-07-10-00.log +0 -50
  66. package/logs/connections-2024-07-10-10.log +0 -50
  67. package/logs/connections-2024-07-13-20.log +0 -200
  68. package/logs/connections-2024-07-13-21.log +0 -50
@@ -0,0 +1,334 @@
1
+ import { LitElement, html, css } from 'lit'
2
+ import { property, query, customElement } from 'lit/decorators.js'
3
+ import { keyed } from 'lit/directives/keyed.js'
4
+
5
+ import { buildSciChart, buildSciChartOverview } from './scichart-builder'
6
+ import { AxisSynchroniser } from './axis-synchronizer'
7
+ import { NumberRange, SciChartVerticalGroup } from 'scichart'
8
+
9
+ import { ScrollbarStyles } from '@operato/styles'
10
+
11
+ @customElement('ox-scichart-multiple')
12
+ export class OxSciChartMultiple extends LitElement {
13
+ @property({ type: Object }) config: OperatoChart.ChartConfig | null = null
14
+ @property({ type: Array }) data: { [attr: string]: any }[] = []
15
+ @property({ type: Array }) visibleSeries: string[] = []
16
+ @property({ type: Boolean, attribute: 'show-overview' }) showOverview: boolean = true
17
+
18
+ private synchronizer: AxisSynchroniser = new AxisSynchroniser(new NumberRange(200, 500))
19
+ private verticalGroup: SciChartVerticalGroup = new SciChartVerticalGroup()
20
+
21
+ private isInitializing: boolean = false
22
+ private overviewChart: any = null
23
+ private overviewDataSeries: any[] = []
24
+ private groupCharts: {
25
+ dataKey: string
26
+ sciChartSurface: any
27
+ dataSeries: any[]
28
+ }[] = []
29
+
30
+ /*
31
+ [주의]
32
+ ox-scichart container의 id를 글로벌 유니크하게 해야한다.
33
+ SciChart가 특별히 container의 id를 기반으로 하위 컴포넌트를 구성하고 있기 때문이다.
34
+ shadowDom 안에 있는 container 이더라도, 글로벌 유니크한 id를 제공해야 한다.
35
+ 그렇지 않으면, 단 하나의 차트만 제대로 렌더링된다.
36
+ */
37
+ private containerId: string = 'ox-scichart-multiple' + ++OxSciChartMultiple.idx
38
+
39
+ @query('.overview') overviewContainer!: HTMLDivElement
40
+
41
+ static idx: number = 0
42
+
43
+ static styles = [
44
+ ScrollbarStyles,
45
+ css`
46
+ :host {
47
+ display: flex;
48
+ flex-direction: column;
49
+
50
+ width: 100%;
51
+ height: 100%;
52
+ }
53
+
54
+ .overview {
55
+ height: 80px;
56
+ }
57
+
58
+ #chart-group {
59
+ flex: 1;
60
+
61
+ display: flex;
62
+ flex-direction: column;
63
+ overflow-y: auto;
64
+ }
65
+
66
+ .grouped-chart {
67
+ flex: 1;
68
+
69
+ min-height: 25%;
70
+ }
71
+
72
+ [hidden] {
73
+ display: none;
74
+ }
75
+ `
76
+ ]
77
+
78
+ async initializeSciChart() {
79
+ this.cleanup()
80
+
81
+ const { chart, dataSeries } =
82
+ (await buildSciChartOverview(this.config, this.overviewContainer, {}, this.synchronizer)) || {}
83
+
84
+ this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
85
+
86
+ this.overviewChart = chart
87
+ this.overviewDataSeries = dataSeries!
88
+ }
89
+
90
+ async updated(changedProperties: Map<string | number | symbol, unknown>) {
91
+ var needDataUpdate = false
92
+
93
+ if (changedProperties.has('config') && this.config) {
94
+ this.isInitializing = true
95
+ await this.initializeSciChart()
96
+ this.isInitializing = false
97
+ needDataUpdate = true
98
+ }
99
+
100
+ if (changedProperties.has('visibleSeries')) {
101
+ if (this.isInitializing) {
102
+ await this.ensureInitialization()
103
+ }
104
+ await this.updateSeries(this.visibleSeries, changedProperties.get('visibleSeries') as string[])
105
+ needDataUpdate = true
106
+ }
107
+
108
+ if (changedProperties.has('data')) {
109
+ needDataUpdate = true
110
+ }
111
+
112
+ if (needDataUpdate) {
113
+ await this.updateDataSeries()
114
+ }
115
+ }
116
+
117
+ private async ensureInitialization() {
118
+ while (this.isInitializing) {
119
+ await new Promise(resolve => setTimeout(resolve, 100)) // Check every 100ms
120
+ }
121
+ }
122
+
123
+ cleanup() {
124
+ this.cleanupGroup()
125
+
126
+ if (this.overviewChart) {
127
+ this.overviewChart.sciChartSurface?.delete()
128
+ this.overviewChart = null
129
+ }
130
+ }
131
+
132
+ cleanupGroup() {
133
+ this.groupCharts.forEach(chart => {
134
+ if (chart.sciChartSurface) {
135
+ this.synchronizer.removeAxis(chart.sciChartSurface.xAxes.get(0))
136
+ this.verticalGroup.removeSurface(chart.sciChartSurface)
137
+ chart.sciChartSurface.delete()
138
+ }
139
+ })
140
+
141
+ this.groupCharts.length = 0
142
+ }
143
+
144
+ async updateDataSeries() {
145
+ const { config, data } = this
146
+ const { datasets = [], labelDataKey: attrX } = config?.data || {}
147
+
148
+ if (!(data instanceof Array) || !attrX) {
149
+ return []
150
+ }
151
+
152
+ const newData = this.dataSet
153
+
154
+ ;(this.groupCharts || []).forEach(({ dataKey, sciChartSurface, dataSeries }) => {
155
+ dataSeries.forEach(ds => ds.clear())
156
+ const dataSet = newData.filter((data, index) => dataKey == datasets[index].dataKey!)
157
+
158
+ dataSet.forEach((data, index) => {
159
+ dataSeries[index].appendRange(
160
+ data.map(d => d.xValue),
161
+ data.map(d => d.yValue)
162
+ )
163
+ })
164
+
165
+ sciChartSurface.zoomExtents()
166
+ sciChartSurface.invalidateElement()
167
+ })
168
+
169
+ this.overviewDataSeries.forEach(ds => ds.clear())
170
+
171
+ newData.forEach((data, index) => {
172
+ if (this.visibleSeries.includes(datasets[index].dataKey!)) {
173
+ this.overviewDataSeries[index].appendRange(
174
+ data.map(d => d.xValue),
175
+ data.map(d => d.yValue)
176
+ )
177
+ }
178
+ })
179
+
180
+ this.overviewChart?.sciChartSurface.zoomExtents()
181
+ this.overviewChart?.sciChartSurface.invalidateElement()
182
+ }
183
+
184
+ get dataSet(): { xValue: number; yValue: number }[][] {
185
+ const { config, data } = this
186
+ const { datasets = [], labelDataKey: attrX } = config?.data || {}
187
+
188
+ if (!(data instanceof Array) || !attrX) {
189
+ return []
190
+ }
191
+
192
+ return datasets.map(dataset => {
193
+ return data
194
+ .map(item => {
195
+ if (!item || typeof item !== 'object') {
196
+ return
197
+ }
198
+
199
+ const xValue = new Date(item[attrX])
200
+ if (isNaN(xValue.getTime())) {
201
+ console.error('Invalid date:', item[attrX])
202
+ return
203
+ }
204
+
205
+ return {
206
+ xValue: xValue.getTime() / 1000,
207
+ yValue: item[dataset.dataKey!]
208
+ }
209
+ })
210
+ .filter(Boolean) as { xValue: number; yValue: number }[]
211
+ })
212
+ }
213
+
214
+ render() {
215
+ const { datasets = [] } = this.config?.data || {}
216
+
217
+ return html`
218
+ <div id=${this.containerId + '-overview'} class="overview" ?hidden=${!this.showOverview}></div>
219
+ <div id="chart-group">
220
+ ${datasets.map(({ dataKey }) =>
221
+ keyed(
222
+ dataKey,
223
+ html`
224
+ <div
225
+ id=${this.containerId + '-' + dataKey}
226
+ class="grouped-chart"
227
+ ?hidden=${!this.visibleSeries.includes(dataKey!)}
228
+ ></div>
229
+ `
230
+ )
231
+ )}
232
+ </div>
233
+ `
234
+ }
235
+
236
+ async buildChartGroup() {
237
+ this.cleanupGroup()
238
+
239
+ const { config } = this
240
+ const { datasets = [] } = config?.data || {}
241
+
242
+ await Promise.all(
243
+ datasets
244
+ .filter(dataset => this.visibleSeries.includes(dataset.dataKey!))
245
+ .map(async dataset => {
246
+ await this.addChart(dataset.dataKey!)
247
+ })
248
+ )
249
+ }
250
+
251
+ async updateSeries(after: string[], before: string[]) {
252
+ /* 기존 시리즈와 새로운 시리즈의 차이를 비교해서, before에는 있는데, after에는 없으면 await removeChart(string)를 호출하고, after에는 있는데, before에는 없으면, addChart(string) 한다. */
253
+ // before에는 있는데 after에는 없는 시리즈를 제거합니다.
254
+ for (const series of before || []) {
255
+ if (!after.includes(series)) {
256
+ await this.removeChart(series)
257
+ }
258
+ }
259
+
260
+ // after에는 있는데 before에는 없는 시리즈를 추가합니다.
261
+ for (const series of after || []) {
262
+ if (!before || !before.includes(series)) {
263
+ await this.addChart(series)
264
+ }
265
+ }
266
+ }
267
+
268
+ async addChart(dataKey: string) {
269
+ const groupedChart = {
270
+ dataKey: '',
271
+ sciChartSurface: undefined,
272
+ dataSeries: [] as any[]
273
+ }
274
+
275
+ const { data } = this
276
+ const { datasets = [] } = this.config?.data || {}
277
+
278
+ const config = {
279
+ ...this.config,
280
+ data: {
281
+ ...data,
282
+ datasets: datasets.filter(dataset => dataset.dataKey == dataKey)
283
+ }
284
+ }
285
+
286
+ const container = this.renderRoot.querySelector(`#${this.containerId + '-' + dataKey}`)
287
+ var { chart, dataSeries } = (await buildSciChart(
288
+ config,
289
+ container,
290
+ { fontSize: undefined, fontFamily: undefined, fontColor: undefined },
291
+ this.containerId
292
+ ))!
293
+
294
+ this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
295
+ this.synchronizer.addAxis(chart.sciChartSurface.xAxes.get(0))
296
+
297
+ groupedChart.dataKey = config.data.datasets[0]!.dataKey!
298
+ groupedChart.sciChartSurface = chart.sciChartSurface
299
+ groupedChart.dataSeries = dataSeries
300
+
301
+ this.groupCharts = this.groupSorter([...this.groupCharts, groupedChart])
302
+ }
303
+
304
+ removeChart(dataKey: string) {
305
+ const index = this.groupCharts.findIndex((chart: any) => chart.dataKey == dataKey)
306
+ const [groupedChart] = this.groupCharts.splice(index, 1)
307
+
308
+ if (!groupedChart) {
309
+ return
310
+ }
311
+
312
+ this.verticalGroup.removeSurface(groupedChart.sciChartSurface)
313
+ this.synchronizer.removeAxis(groupedChart.sciChartSurface.xAxes.get(0))
314
+
315
+ groupedChart.sciChartSurface.delete()
316
+ groupedChart.sciChartSurface = undefined
317
+
318
+ this.groupCharts = this.groupSorter(this.groupCharts)
319
+ }
320
+
321
+ groupSorter(group: any[]) {
322
+ return group.sort(
323
+ (a, b) =>
324
+ this.visibleSeries.findIndex((s: any) => s.dataKey == a.dataKey) -
325
+ this.visibleSeries.findIndex((s: any) => s.dataKey == b.dataKey)
326
+ )
327
+ }
328
+ }
329
+
330
+ declare global {
331
+ interface HTMLElementTagNameMap {
332
+ 'ox-scichart-multiple': OxSciChartMultiple
333
+ }
334
+ }
@@ -7,7 +7,7 @@ export class OxSciChart extends LitElement {
7
7
  @property({ type: Object }) config: OperatoChart.ChartConfig | null = null
8
8
  @property({ type: Array }) data: { [attr: string]: any }[] = []
9
9
 
10
- private chart: any = null
10
+ public chart: any = null
11
11
  private dataSeries: any[] = []
12
12
  /*
13
13
  [주의]
@@ -1,5 +1,4 @@
1
1
  import { TinyColor } from '@ctrl/tinycolor'
2
- import { format as formatText } from '@operato/utils/format.js'
3
2
  import {
4
3
  SciChartSurface,
5
4
  SciChartJSLightTheme,
@@ -16,6 +15,7 @@ import {
16
15
  DateTimeNumericAxis,
17
16
  EAutoRange,
18
17
  EAxisAlignment,
18
+ EExecuteOn,
19
19
  ECoordinateMode,
20
20
  EHorizontalAnchorPoint,
21
21
  EVerticalAnchorPoint,
@@ -41,8 +41,11 @@ import {
41
41
  LineAnnotation,
42
42
  BoxAnnotation,
43
43
  HorizontalLineAnnotation,
44
- VerticalLineAnnotation
44
+ VerticalLineAnnotation,
45
+ OverviewRangeSelectionModifier,
46
+ ENumericFormat
45
47
  } from 'scichart'
48
+ import { AxisSynchroniser } from './axis-synchronizer'
46
49
 
47
50
  SciChartSurface.UseCommunityLicense()
48
51
 
@@ -57,6 +60,11 @@ const POINT_MARKER_SIZE = 10
57
60
  const STROKE_THICKNESS = 2
58
61
  const ANIMATION_DURATION = 1000
59
62
 
63
+ function getLocalTimeOffset() {
64
+ const now = new Date()
65
+ return now.getTimezoneOffset() * -60
66
+ }
67
+
60
68
  function getBaseColorFromTheme(theme?: 'light' | 'dark' | 'auto') {
61
69
  return new TinyColor(theme == 'dark' ? '#fff' : '#000')
62
70
  }
@@ -106,7 +114,8 @@ function createAxis(
106
114
  isXAxis: boolean,
107
115
  fontColor: string,
108
116
  fontFamily?: string,
109
- fontSize?: number
117
+ fontSize?: number,
118
+ options?: any
110
119
  ) {
111
120
  const { axisTitle, ticks } = axis
112
121
  const {
@@ -136,11 +145,24 @@ function createAxis(
136
145
  fontFamily,
137
146
  fontSize,
138
147
  color: textStrokeColor
139
- }
148
+ },
149
+ ...options
140
150
  }
141
151
 
152
+ const labelProvider = new SmartDateLabelProvider({
153
+ labelFormat: ENumericFormat.Date_HHMMSS,
154
+ showWiderDateOnFirstLabel: true,
155
+ showYearOnWiderDate: true,
156
+ dateOffset: getLocalTimeOffset()
157
+ })
158
+
159
+ labelProvider.cursorNumericFormat = ENumericFormat.Date_DDMMHHMM
160
+
142
161
  return isXAxis
143
- ? new DateTimeNumericAxis(wasmContext, { ...axisOptions, labelProvider: new SmartDateLabelProvider() })
162
+ ? new DateTimeNumericAxis(wasmContext, {
163
+ ...axisOptions,
164
+ labelProvider
165
+ })
144
166
  : new NumericAxis(wasmContext, { ...axisOptions, id: index !== 0 ? `yAxis${index}` : undefined })
145
167
  }
146
168
 
@@ -212,7 +234,8 @@ function createSeries(
212
234
  export async function buildSciChart(
213
235
  config: OperatoChart.ChartConfig | undefined | null,
214
236
  container: any,
215
- { fontSize, fontFamily, fontColor }: { fontSize?: number; fontFamily?: string; fontColor?: string }
237
+ { fontSize, fontFamily, fontColor }: { fontSize?: number; fontFamily?: string; fontColor?: string },
238
+ grouped?: string
216
239
  ): Promise<{ chart: any; dataSeries: any[] } | undefined> {
217
240
  if (!config) return
218
241
 
@@ -269,7 +292,8 @@ export async function buildSciChart(
269
292
  if (tooltip) {
270
293
  const rolloverModifier = new RolloverModifier({
271
294
  showTooltip: true,
272
- showAxisLabel: true
295
+ showAxisLabel: true,
296
+ modifierGroup: grouped
273
297
  })
274
298
 
275
299
  sciChartSurface.chartModifiers.add(rolloverModifier)
@@ -377,7 +401,7 @@ export async function buildSciChart(
377
401
 
378
402
  // 줌인/줌아웃 모디파이어 추가
379
403
  sciChartSurface.chartModifiers.add(
380
- // new RubberBandXyZoomModifier(),
404
+ new RubberBandXyZoomModifier({ executeOn: EExecuteOn.MouseRightButton, modifierGroup: grouped }),
381
405
  // new ZoomPanModifier({ xyDirection: EXyDirection.XDirection }),
382
406
  new ZoomPanModifier(),
383
407
  new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }),
@@ -406,3 +430,80 @@ export async function buildSciChart(
406
430
 
407
431
  return { chart, dataSeries: dataSeriesArray }
408
432
  }
433
+
434
+ export async function buildSciChartOverview(
435
+ config: OperatoChart.ChartConfig | undefined | null,
436
+ container: any,
437
+ { fontSize, fontFamily, fontColor }: { fontSize?: number; fontFamily?: string; fontColor?: string },
438
+ axisSynchroniser: AxisSynchroniser
439
+ ): Promise<{ chart: any; dataSeries: any[] } | undefined> {
440
+ if (!config) return
441
+
442
+ const { type: chartType, options, data: fromData } = config
443
+ const { datasets = [] } = fromData || {}
444
+ var { theme, animation, scales: fromScales, stacked, multiAxis } = options || {}
445
+
446
+ var baseColor = getBaseColorFromTheme(theme)
447
+
448
+ if (theme === 'auto') {
449
+ theme = getThemeFromBrowser()
450
+ }
451
+
452
+ fontColor = fontColor || baseColor.clone().toString()
453
+
454
+ const { xAxes = [], yAxes = [] } = fromScales || {}
455
+
456
+ // Instead we create a normal chart and then manually add the OverviewRangeSelectionModifier and bind it to the axisSynchroniser
457
+ const chart = await SciChartSurface.create(container, {
458
+ theme: theme == 'dark' ? new SciChartJSDarkv2Theme() : new SciChartJSLightTheme()
459
+ })
460
+ const { sciChartSurface, wasmContext } = chart
461
+
462
+ // X 축 설정
463
+ xAxes.forEach((axis, index) => {
464
+ const xAxis = createAxis(wasmContext, axis, index, true, fontColor, fontFamily, fontSize)
465
+ sciChartSurface.xAxes.add(xAxis)
466
+ })
467
+
468
+ // Y 축 설정
469
+ ;(multiAxis ? yAxes : [yAxes[0]]).forEach((axis, index) => {
470
+ const yAxis = createAxis(wasmContext, axis, index, false, fontColor, fontFamily, fontSize, {
471
+ drawLabels: false,
472
+ drawMajorTicks: false,
473
+ drawMinorTicks: false,
474
+ drawMajorGridLines: false,
475
+ drawMinorGridLines: false
476
+ })
477
+ sciChartSurface.yAxes.add(yAxis)
478
+ })
479
+
480
+ const rangeSelectionModifier = new OverviewRangeSelectionModifier()
481
+ // When the range selection is moved, updated the linked charts
482
+ rangeSelectionModifier.onSelectedAreaChanged = (selectedRange?: NumberRange) => {
483
+ if (!selectedRange!.equals(axisSynchroniser.visibleRange)) {
484
+ axisSynchroniser.publishChange({ visibleRange: selectedRange! })
485
+ }
486
+ }
487
+
488
+ rangeSelectionModifier.selectedArea = axisSynchroniser.visibleRange
489
+ sciChartSurface.chartModifiers.add(rangeSelectionModifier)
490
+
491
+ // When charts are moved, update the range selection
492
+ axisSynchroniser.visibleRangeChanged.subscribe(({ visibleRange }: any) => {
493
+ const updatedSelectedRange = visibleRange.clip(sciChartSurface.xAxes.get(0).visibleRange)
494
+ const shouldUpdateSelectedRange = !updatedSelectedRange.equals(rangeSelectionModifier.selectedArea)
495
+ if (shouldUpdateSelectedRange) {
496
+ rangeSelectionModifier.selectedArea = updatedSelectedRange
497
+ }
498
+ })
499
+
500
+ const dataSeriesArray = datasets.map((dataset, index) => {
501
+ const yAxisId = dataset.yAxisID == 'right' && multiAxis ? 'yAxis1' : undefined
502
+ const { series, dataSeries } = createSeries(wasmContext, dataset, index, !!stacked, !!animation, yAxisId)
503
+
504
+ sciChartSurface.renderableSeries.add(series)
505
+ return dataSeries
506
+ })
507
+
508
+ return { chart, dataSeries: dataSeriesArray }
509
+ }
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { default as scichartTimeseries } from './scichart-timeseries'
2
+ export { default as scichartMultipleTimeseries } from './scichart-multiple-timeseries'
@@ -0,0 +1,74 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ const NATURE: ComponentNature = {
6
+ mutable: false,
7
+ resizable: true,
8
+ rotatable: true,
9
+ properties: [
10
+ {
11
+ type: 'boolean',
12
+ label: 'show-overview',
13
+ name: 'showOverview'
14
+ },
15
+ {
16
+ type: 'scichart',
17
+ label: '',
18
+ name: 'chart'
19
+ }
20
+ ],
21
+ 'value-property': 'visibleSeries',
22
+ help: 'scene/component/scichart-multiple-timeseries'
23
+ }
24
+
25
+ import './charts/ox-scichart-multiple'
26
+
27
+ import { Component, HTMLOverlayContainer, Properties, ComponentNature, error } from '@hatiolab/things-scene'
28
+
29
+ import { OxSciChartMultiple } from './charts/ox-scichart-multiple'
30
+
31
+ export default class ScichartMultipleTimeseries extends HTMLOverlayContainer {
32
+ static get nature() {
33
+ return NATURE
34
+ }
35
+
36
+ async oncreate_element(scichart: OxSciChartMultiple) {}
37
+
38
+ dispose() {
39
+ super.dispose()
40
+ }
41
+
42
+ setElementProperties(scichart: OxSciChartMultiple) {
43
+ const { data, chart, showOverview, visibleSeries } = this.state
44
+
45
+ scichart.config = chart
46
+ scichart.data = data
47
+ scichart.showOverview = showOverview
48
+ scichart.visibleSeries = visibleSeries || []
49
+ }
50
+
51
+ reposition() {
52
+ super.reposition()
53
+ }
54
+
55
+ get tagName() {
56
+ return 'ox-scichart-multiple'
57
+ }
58
+
59
+ get visibleSeries() {
60
+ const { visibleSeries } = this.state
61
+ return visibleSeries || []
62
+ }
63
+
64
+ set visibleSeries(visibleSeries: string[]) {
65
+ this.setState('visibleSeries', visibleSeries)
66
+ ;(this.element as OxSciChartMultiple).visibleSeries = visibleSeries
67
+ }
68
+
69
+ async onchangeData(after: Properties, before: Properties): Promise<void> {
70
+ ;(this.element as OxSciChartMultiple).data = this.data
71
+ }
72
+ }
73
+
74
+ Component.register('scichart-multiple-timeseries', ScichartMultipleTimeseries)
@@ -2,7 +2,7 @@
2
2
  * Copyright © HatioLab Inc. All rights reserved.
3
3
  */
4
4
 
5
- const NATURE = {
5
+ const NATURE: ComponentNature = {
6
6
  mutable: false,
7
7
  resizable: true,
8
8
  rotatable: true,
@@ -12,7 +12,8 @@ const NATURE = {
12
12
  label: '',
13
13
  name: 'chart'
14
14
  }
15
- ]
15
+ ],
16
+ help: 'scene/component/scichart-timeseries'
16
17
  }
17
18
 
18
19
  import './charts/ox-scichart'
@@ -43,58 +44,6 @@ export default class ScichartTimeSeries extends HTMLOverlayContainer {
43
44
  super.reposition()
44
45
  }
45
46
 
46
- // get dataSet(): { xValue: number; yValue: number }[] {
47
- // var { attrX, attrY, data } = this.state
48
-
49
- // if (!(data instanceof Array)) {
50
- // return []
51
- // }
52
-
53
- // return data
54
- // .map((item, i) => {
55
- // if (!item || typeof item !== 'object') {
56
- // return
57
- // }
58
-
59
- // console.log('Data item:', item) // 데이터 항목을 로그로 출력
60
- // const xValue = new Date(item[attrX])
61
- // console.log('Parsed Date:', xValue) // 파싱된 날짜를 로그로 출력
62
- // if (isNaN(xValue.getTime())) {
63
- // console.error('Invalid date:', item[attrX]) // 유효하지 않은 날짜를 로그로 출력
64
- // return
65
- // }
66
-
67
- // return {
68
- // xValue: xValue.getTime() / 1000, // 타임스탬프를 초 단위로 변환
69
- // yValue: item[attrY]
70
- // }
71
- // })
72
- // .filter(Boolean) as { xValue: number; yValue: number }[]
73
- // }
74
-
75
- // async onchangeData(after: Properties, before: Properties): Promise<void> {
76
- // console.log('onchangeData called') // 데이터 변경 시 로그 출력
77
- // this.updateDataSeries()
78
- // this.surface?.sciChartSurface.zoomExtents()
79
- // }
80
-
81
- // updateDataSeries() {
82
- // if (!this.dataSeries) return
83
-
84
- // this.dataSeries.clear()
85
- // const newData = this.dataSet
86
-
87
- // console.log('Updating data series with:', newData) // 새 데이터 로그 출력
88
-
89
- // this.dataSeries.appendRange(
90
- // newData.map(d => d.xValue), // Date 객체를 타임스탬프로 변환
91
- // newData.map(d => d.yValue)
92
- // )
93
-
94
- // this.surface?.sciChartSurface.zoomExtents() // 데이터 변경 후 영역 조정
95
- // this.surface?.sciChartSurface.invalidateElement() // 차트를 다시 그리도록 요청
96
- // }
97
-
98
47
  get tagName() {
99
48
  return 'ox-scichart'
100
49
  }
@@ -1,3 +1,4 @@
1
1
  import scichartTimeseries from './scichart-timeseries'
2
+ import scichartMultipleTimeseries from './scichart-multiple-timeseries'
2
3
 
3
- export default [scichartTimeseries]
4
+ export default [scichartTimeseries, scichartMultipleTimeseries]