@operato/scene-scichart 8.0.0-beta.1 → 8.0.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/package.json +6 -6
- package/CHANGELOG.md +0 -278
- package/db.sqlite +0 -0
- package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +0 -15
- package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +0 -15
- package/logs/application-2024-09-10-23.log +0 -105
- package/logs/connections-2024-09-10-23.log +0 -50
- package/schema.graphql +0 -4455
- package/src/charts/axis-synchronizer.ts +0 -37
- package/src/charts/ox-scichart-multiple.ts +0 -579
- package/src/charts/ox-scichart.ts +0 -155
- package/src/charts/scichart-builder.ts +0 -630
- package/src/editors/index.ts +0 -8
- package/src/groups/index.ts +0 -0
- package/src/index.ts +0 -2
- package/src/scichart-multiple-timeseries.ts +0 -69
- package/src/scichart-timeseries.ts +0 -51
- package/src/templates/index.ts +0 -4
- package/src/templates/scichart-multiple-timeseries.ts +0 -87
- package/src/templates/scichart-timeseries.ts +0 -73
- package/tsconfig.json +0 -23
- package/tsconfig.tsbuildinfo +0 -1
@@ -1,37 +0,0 @@
|
|
1
|
-
import { AxisBase2D, EventHandler, NumberRange, VisibleRangeChangedArgs } from 'scichart'
|
2
|
-
|
3
|
-
export class AxisSynchroniser {
|
4
|
-
public visibleRange: NumberRange
|
5
|
-
private axes: AxisBase2D[] = []
|
6
|
-
public visibleRangeChanged: EventHandler<VisibleRangeChangedArgs> = new EventHandler<VisibleRangeChangedArgs>()
|
7
|
-
|
8
|
-
public constructor(initialRange: NumberRange, axes?: AxisBase2D[]) {
|
9
|
-
this.visibleRange = initialRange
|
10
|
-
this.publishChange = this.publishChange.bind(this)
|
11
|
-
if (axes) {
|
12
|
-
axes.forEach(a => this.addAxis(a))
|
13
|
-
}
|
14
|
-
}
|
15
|
-
|
16
|
-
public publishChange(data?: VisibleRangeChangedArgs) {
|
17
|
-
this.visibleRange = data!.visibleRange
|
18
|
-
this.axes.forEach(a => (a.visibleRange = this.visibleRange))
|
19
|
-
this.visibleRangeChanged.raiseEvent(data)
|
20
|
-
}
|
21
|
-
|
22
|
-
public addAxis(axis: AxisBase2D) {
|
23
|
-
if (!this.axes.includes(axis)) {
|
24
|
-
this.axes.push(axis)
|
25
|
-
axis.visibleRange = this.visibleRange
|
26
|
-
axis.visibleRangeChanged.subscribe(this.publishChange)
|
27
|
-
}
|
28
|
-
}
|
29
|
-
|
30
|
-
public removeAxis(axis: AxisBase2D) {
|
31
|
-
const index = this.axes.findIndex(a => a === axis)
|
32
|
-
if (index >= 0) {
|
33
|
-
this.axes.splice(index, 1)
|
34
|
-
axis.visibleRangeChanged.unsubscribe(this.publishChange)
|
35
|
-
}
|
36
|
-
}
|
37
|
-
}
|
@@ -1,579 +0,0 @@
|
|
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 {
|
6
|
-
calculatePrecision,
|
7
|
-
buildSciChart,
|
8
|
-
buildSciChartOverview,
|
9
|
-
convertColor,
|
10
|
-
DEFAULT_COLOR
|
11
|
-
} from './scichart-builder'
|
12
|
-
import { AxisSynchroniser } from './axis-synchronizer'
|
13
|
-
import {
|
14
|
-
EAutoRange,
|
15
|
-
FastLineRenderableSeries,
|
16
|
-
NumberRange,
|
17
|
-
NumericAxis,
|
18
|
-
scaleAxes,
|
19
|
-
SciChartVerticalGroup,
|
20
|
-
XyDataSeries
|
21
|
-
} from 'scichart'
|
22
|
-
|
23
|
-
import { ScrollbarStyles } from '@operato/styles'
|
24
|
-
|
25
|
-
@customElement('ox-scichart-multiple')
|
26
|
-
export class OxSciChartMultiple extends LitElement {
|
27
|
-
@property({ type: Object }) config: OperatoChart.ChartConfig | null = null
|
28
|
-
@property({ type: Array }) data: { [attr: string]: any }[] = []
|
29
|
-
@property({ type: Array }) visibleSeries: string[] = []
|
30
|
-
@property({ type: Boolean, attribute: 'show-overview' }) showOverview: boolean = true
|
31
|
-
|
32
|
-
private synchronizer: AxisSynchroniser = new AxisSynchroniser(new NumberRange(200, 500))
|
33
|
-
private verticalGroup: SciChartVerticalGroup = new SciChartVerticalGroup()
|
34
|
-
|
35
|
-
private overviewChart: any = null
|
36
|
-
private overviewDataSeries: any[] = []
|
37
|
-
private groupCharts: {
|
38
|
-
dataKey: string
|
39
|
-
sciChartSurface: any
|
40
|
-
dataSeries: any[]
|
41
|
-
}[] = []
|
42
|
-
|
43
|
-
private initializationQueue: Promise<void> = Promise.resolve()
|
44
|
-
|
45
|
-
/*
|
46
|
-
[주의]
|
47
|
-
ox-scichart container의 id를 글로벌 유니크하게 해야한다.
|
48
|
-
SciChart가 특별히 container의 id를 기반으로 하위 컴포넌트를 구성하고 있기 때문이다.
|
49
|
-
shadowDom 안에 있는 container 이더라도, 글로벌 유니크한 id를 제공해야 한다.
|
50
|
-
그렇지 않으면, 단 하나의 차트만 제대로 렌더링된다.
|
51
|
-
*/
|
52
|
-
private containerId: string = 'ox-scichart-multiple' + ++OxSciChartMultiple.idx
|
53
|
-
|
54
|
-
@query('.overview') overviewContainer!: HTMLDivElement
|
55
|
-
|
56
|
-
static idx: number = 0
|
57
|
-
|
58
|
-
static styles = [
|
59
|
-
ScrollbarStyles,
|
60
|
-
css`
|
61
|
-
:host {
|
62
|
-
display: flex;
|
63
|
-
flex-direction: column;
|
64
|
-
|
65
|
-
width: 100%;
|
66
|
-
height: 100%;
|
67
|
-
}
|
68
|
-
|
69
|
-
.overview {
|
70
|
-
height: 80px;
|
71
|
-
}
|
72
|
-
|
73
|
-
#chart-group {
|
74
|
-
flex: 1;
|
75
|
-
|
76
|
-
display: flex;
|
77
|
-
flex-direction: column;
|
78
|
-
overflow-y: auto;
|
79
|
-
}
|
80
|
-
|
81
|
-
.grouped-chart {
|
82
|
-
flex: 1;
|
83
|
-
|
84
|
-
min-height: 25%;
|
85
|
-
}
|
86
|
-
|
87
|
-
[hidden] {
|
88
|
-
display: none;
|
89
|
-
}
|
90
|
-
`
|
91
|
-
]
|
92
|
-
|
93
|
-
async initializeSciChart() {
|
94
|
-
this.cleanup()
|
95
|
-
await this.createOverviewChart()
|
96
|
-
}
|
97
|
-
|
98
|
-
dispose() {
|
99
|
-
// 그룹 차트 자원 해제
|
100
|
-
this.groupCharts.forEach(chart => {
|
101
|
-
if (chart.sciChartSurface) {
|
102
|
-
this.synchronizer.removeAxis(chart.sciChartSurface.xAxes.get(0))
|
103
|
-
this.verticalGroup.removeSurface(chart.sciChartSurface)
|
104
|
-
|
105
|
-
// 각 데이터 시리즈 명시적으로 해제
|
106
|
-
chart.dataSeries.forEach(ds => ds.delete())
|
107
|
-
|
108
|
-
// 차트 삭제
|
109
|
-
chart.sciChartSurface.delete()
|
110
|
-
}
|
111
|
-
})
|
112
|
-
|
113
|
-
// 오버뷰 차트 자원 해제
|
114
|
-
if (this.overviewChart) {
|
115
|
-
this.overviewChart.sciChartSurface.renderableSeries.clear()
|
116
|
-
this.overviewDataSeries.forEach(ds => ds.delete())
|
117
|
-
this.overviewChart.sciChartSurface.delete()
|
118
|
-
this.overviewDataSeries.length = 0
|
119
|
-
}
|
120
|
-
|
121
|
-
// 사용된 그룹, 오버뷰 데이터 초기화
|
122
|
-
this.groupCharts.length = 0
|
123
|
-
this.overviewChart = null
|
124
|
-
}
|
125
|
-
|
126
|
-
async createOverviewChart() {
|
127
|
-
const { chart, dataSeries } =
|
128
|
-
(await buildSciChartOverview(
|
129
|
-
{
|
130
|
-
...this.config,
|
131
|
-
data: { datasets: [] }
|
132
|
-
},
|
133
|
-
this.overviewContainer,
|
134
|
-
{},
|
135
|
-
this.synchronizer
|
136
|
-
)) || {}
|
137
|
-
|
138
|
-
this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
|
139
|
-
|
140
|
-
this.overviewChart = chart
|
141
|
-
this.overviewDataSeries = dataSeries!
|
142
|
-
}
|
143
|
-
|
144
|
-
async updated(changedProperties: Map<string | number | symbol, unknown>) {
|
145
|
-
this.initializationQueue = this.initializationQueue
|
146
|
-
.then(async () => {
|
147
|
-
let needUpdateDataSeries = false
|
148
|
-
let needBuildChartGroup = false
|
149
|
-
|
150
|
-
if (changedProperties.has('config') && this.config) {
|
151
|
-
await this.initializeSciChart()
|
152
|
-
needBuildChartGroup = true
|
153
|
-
needUpdateDataSeries = true
|
154
|
-
}
|
155
|
-
|
156
|
-
if (changedProperties.has('visibleSeries')) {
|
157
|
-
await this.updateSeries(this.visibleSeries, changedProperties.get('visibleSeries') as string[])
|
158
|
-
/* [중요] buildChartGroup 을 visibleSeries 수정때마다 하는 이유는, render() 의 캐시 컨트롤이 안되기 때문이다. 가급적 시도하지 말라. */
|
159
|
-
needBuildChartGroup = true
|
160
|
-
needUpdateDataSeries = true
|
161
|
-
}
|
162
|
-
|
163
|
-
if (changedProperties.has('data')) {
|
164
|
-
needUpdateDataSeries = true
|
165
|
-
}
|
166
|
-
|
167
|
-
if (needBuildChartGroup) {
|
168
|
-
await this.buildChartGroup()
|
169
|
-
}
|
170
|
-
|
171
|
-
if (needUpdateDataSeries) {
|
172
|
-
await this.updateDataSeries()
|
173
|
-
}
|
174
|
-
})
|
175
|
-
.catch((error: any) => {
|
176
|
-
console.error('Error in updated queue:', error)
|
177
|
-
})
|
178
|
-
}
|
179
|
-
|
180
|
-
cleanup() {
|
181
|
-
this.cleanupGroup()
|
182
|
-
this.cleanupOverview()
|
183
|
-
}
|
184
|
-
|
185
|
-
cleanupGroup() {
|
186
|
-
this.groupCharts.forEach(chart => {
|
187
|
-
if (chart.sciChartSurface) {
|
188
|
-
this.synchronizer.removeAxis(chart.sciChartSurface.xAxes.get(0))
|
189
|
-
this.verticalGroup.removeSurface(chart.sciChartSurface)
|
190
|
-
chart.sciChartSurface.delete()
|
191
|
-
}
|
192
|
-
})
|
193
|
-
|
194
|
-
this.groupCharts.length = 0
|
195
|
-
}
|
196
|
-
|
197
|
-
cleanupOverview() {
|
198
|
-
if (this.overviewChart) {
|
199
|
-
this.overviewChart.sciChartSurface.renderableSeries.clear()
|
200
|
-
this.overviewDataSeries.forEach(ds => ds.delete())
|
201
|
-
this.overviewDataSeries.length = 0
|
202
|
-
}
|
203
|
-
|
204
|
-
this.overviewChart = null
|
205
|
-
}
|
206
|
-
|
207
|
-
async updateDataSeries() {
|
208
|
-
const { config, data } = this
|
209
|
-
const { datasets = [], labelDataKey: attrX } = config?.data || {}
|
210
|
-
|
211
|
-
if (!(data instanceof Array) || !attrX) {
|
212
|
-
return []
|
213
|
-
}
|
214
|
-
|
215
|
-
const newData = this.dataSet
|
216
|
-
|
217
|
-
this.groupCharts.forEach(({ dataKey, sciChartSurface, dataSeries }) => {
|
218
|
-
try {
|
219
|
-
// dataKey로 시작하는 모든 시리즈를 업데이트
|
220
|
-
const relatedDatasets = datasets.filter(dataset => dataset.dataKey?.startsWith(dataKey))
|
221
|
-
|
222
|
-
// 각 relatedDatasets에 대해 해당하는 dataSeries를 업데이트
|
223
|
-
dataSeries.forEach((ds, index) => {
|
224
|
-
ds.clear()
|
225
|
-
|
226
|
-
const relatedDataset = relatedDatasets[index]
|
227
|
-
if (relatedDataset) {
|
228
|
-
const filteredData = newData[datasets.findIndex(ds => ds.dataKey === relatedDataset.dataKey)].filter(
|
229
|
-
d => typeof d.yValue === 'number'
|
230
|
-
)
|
231
|
-
|
232
|
-
if (filteredData.length > 0) {
|
233
|
-
ds.appendRange(
|
234
|
-
filteredData.map(d => d.xValue),
|
235
|
-
filteredData.map(d => d.yValue)
|
236
|
-
)
|
237
|
-
}
|
238
|
-
}
|
239
|
-
})
|
240
|
-
|
241
|
-
sciChartSurface.zoomExtents()
|
242
|
-
sciChartSurface.invalidateElement()
|
243
|
-
} catch (error) {
|
244
|
-
console.error('Error updating data series:', error)
|
245
|
-
}
|
246
|
-
})
|
247
|
-
|
248
|
-
try {
|
249
|
-
// Overview 차트 데이터 업데이트
|
250
|
-
this.overviewDataSeries.forEach((ds, index) => {
|
251
|
-
const visibleKey = this.visibleSeries[index]
|
252
|
-
const dataset = datasets.find(dataset => dataset.dataKey === visibleKey)
|
253
|
-
if (!dataset) {
|
254
|
-
return
|
255
|
-
}
|
256
|
-
|
257
|
-
const dataIndex = datasets.findIndex(ds => ds.dataKey === dataset.dataKey)
|
258
|
-
const filteredData = newData[dataIndex]?.filter(d => typeof d.yValue === 'number') || []
|
259
|
-
|
260
|
-
ds.clear()
|
261
|
-
if (filteredData.length > 0) {
|
262
|
-
ds.appendRange(
|
263
|
-
filteredData.map(d => d.xValue),
|
264
|
-
filteredData.map(d => d.yValue)
|
265
|
-
)
|
266
|
-
}
|
267
|
-
})
|
268
|
-
|
269
|
-
// this.overviewDataSeries.forEach(ds => ds.clear())
|
270
|
-
|
271
|
-
// newData.forEach((data, index) => {
|
272
|
-
// if (this.visibleSeries.includes(datasets[index].dataKey!)) {
|
273
|
-
// const filteredData = data.filter(d => typeof d.yValue === 'number')
|
274
|
-
// if (filteredData.length > 0) {
|
275
|
-
// this.overviewDataSeries[index].appendRange(
|
276
|
-
// filteredData.map(d => d.xValue),
|
277
|
-
// filteredData.map(d => d.yValue)
|
278
|
-
// )
|
279
|
-
// }
|
280
|
-
// }
|
281
|
-
// })
|
282
|
-
} catch (error) {
|
283
|
-
console.error('Error updating overview data series:', error)
|
284
|
-
}
|
285
|
-
}
|
286
|
-
|
287
|
-
get dataSet(): { xValue: number; yValue: number }[][] {
|
288
|
-
const { config, data } = this
|
289
|
-
const { datasets = [], labelDataKey: attrX } = config?.data || {}
|
290
|
-
|
291
|
-
if (!(data instanceof Array) || !attrX) {
|
292
|
-
return []
|
293
|
-
}
|
294
|
-
|
295
|
-
return datasets.map(dataset => {
|
296
|
-
return data
|
297
|
-
.map(item => {
|
298
|
-
if (!item || typeof item !== 'object') {
|
299
|
-
return
|
300
|
-
}
|
301
|
-
|
302
|
-
const xValue = new Date(item[attrX])
|
303
|
-
if (isNaN(xValue.getTime())) {
|
304
|
-
console.error('Invalid date:', item[attrX])
|
305
|
-
return
|
306
|
-
}
|
307
|
-
|
308
|
-
return {
|
309
|
-
xValue: xValue.getTime() / 1000,
|
310
|
-
yValue: item[dataset.dataKey!]
|
311
|
-
}
|
312
|
-
})
|
313
|
-
.filter(Boolean) as { xValue: number; yValue: number }[]
|
314
|
-
})
|
315
|
-
}
|
316
|
-
|
317
|
-
render() {
|
318
|
-
const { datasets = [] } = this.config?.data || {}
|
319
|
-
|
320
|
-
return html`
|
321
|
-
<div id=${this.containerId + '-overview'} class="overview" ?hidden=${!this.showOverview}></div>
|
322
|
-
<div id="chart-group">
|
323
|
-
${this.visibleSeries.map(dataKey =>
|
324
|
-
keyed(
|
325
|
-
dataKey,
|
326
|
-
html`
|
327
|
-
<div
|
328
|
-
id=${this.containerId + '-' + dataKey}
|
329
|
-
class="grouped-chart"
|
330
|
-
?hidden=${!this.visibleSeries.includes(dataKey!)}
|
331
|
-
></div>
|
332
|
-
`
|
333
|
-
)
|
334
|
-
)}
|
335
|
-
</div>
|
336
|
-
`
|
337
|
-
}
|
338
|
-
|
339
|
-
async buildChartGroup() {
|
340
|
-
this.cleanupGroup()
|
341
|
-
|
342
|
-
const { config } = this
|
343
|
-
const { datasets = [] } = config?.data || {}
|
344
|
-
|
345
|
-
await Promise.all(
|
346
|
-
datasets
|
347
|
-
.filter(dataset => this.visibleSeries.includes(dataset.dataKey!))
|
348
|
-
.map(async dataset => {
|
349
|
-
await this.addChart(dataset.dataKey!)
|
350
|
-
})
|
351
|
-
)
|
352
|
-
}
|
353
|
-
|
354
|
-
async updateSeries(after: string[], before: string[]) {
|
355
|
-
const addSeries = after?.filter(series => !before?.includes(series)) || []
|
356
|
-
const removeSeries = before?.filter(series => !after?.includes(series)) || []
|
357
|
-
|
358
|
-
for (const series of removeSeries) {
|
359
|
-
await this.removeChart(series)
|
360
|
-
}
|
361
|
-
|
362
|
-
for (const series of addSeries) {
|
363
|
-
await this.addChart(series)
|
364
|
-
}
|
365
|
-
}
|
366
|
-
|
367
|
-
async addChart(dataKey: string) {
|
368
|
-
const chartData = await this.createChart(dataKey)
|
369
|
-
|
370
|
-
if (chartData) {
|
371
|
-
const { chart, dataSeries, dataKey } = chartData
|
372
|
-
this.verticalGroup.addSurfaceToGroup(chart.sciChartSurface)
|
373
|
-
|
374
|
-
this.groupCharts = this.groupSorter([
|
375
|
-
...this.groupCharts,
|
376
|
-
{ dataKey, sciChartSurface: chart.sciChartSurface, dataSeries }
|
377
|
-
])
|
378
|
-
|
379
|
-
await this.addSeriesToOverviewChart(dataKey)
|
380
|
-
}
|
381
|
-
}
|
382
|
-
|
383
|
-
async removeChart(dataKey: string) {
|
384
|
-
const index = this.groupCharts.findIndex(chart => chart.dataKey == dataKey)
|
385
|
-
if (index === -1) return
|
386
|
-
|
387
|
-
const [groupedChart] = this.groupCharts.splice(index, 1)
|
388
|
-
this.destroyChart(groupedChart)
|
389
|
-
|
390
|
-
this.groupCharts = this.groupSorter(this.groupCharts)
|
391
|
-
|
392
|
-
await this.removeSeriesFromOverviewChart(dataKey)
|
393
|
-
}
|
394
|
-
|
395
|
-
groupSorter(group: any[]) {
|
396
|
-
return group.sort(
|
397
|
-
(a, b) =>
|
398
|
-
this.visibleSeries.findIndex((s: any) => s.dataKey == a.dataKey) -
|
399
|
-
this.visibleSeries.findIndex((s: any) => s.dataKey == b.dataKey)
|
400
|
-
)
|
401
|
-
}
|
402
|
-
|
403
|
-
async appendData(appendum: { [attr: string]: any }[]) {}
|
404
|
-
|
405
|
-
private async createChart(dataKey: string) {
|
406
|
-
const { data = {}, options = {} } = this.config || {}
|
407
|
-
const { datasets = [] } = data as OperatoChart.ChartData
|
408
|
-
const primaryDataset = datasets.find(dataset => dataset.dataKey == dataKey)
|
409
|
-
|
410
|
-
if (!primaryDataset) {
|
411
|
-
return null
|
412
|
-
}
|
413
|
-
|
414
|
-
const relatedDatasets = datasets.filter(dataset => dataset.dataKey?.startsWith(dataKey))
|
415
|
-
|
416
|
-
const yAxis = {
|
417
|
-
...options.scales?.yAxes?.[0],
|
418
|
-
axisTitle: primaryDataset?.label
|
419
|
-
}
|
420
|
-
|
421
|
-
const config = {
|
422
|
-
...this.config,
|
423
|
-
data: {
|
424
|
-
datasets: relatedDatasets
|
425
|
-
},
|
426
|
-
options: {
|
427
|
-
...options,
|
428
|
-
scales: {
|
429
|
-
...options.scales,
|
430
|
-
yAxes: [yAxis]
|
431
|
-
}
|
432
|
-
}
|
433
|
-
}
|
434
|
-
|
435
|
-
const container = this.renderRoot.querySelector(`#${this.containerId + '-' + dataKey}`)
|
436
|
-
const { chart, dataSeries } = (await buildSciChart(
|
437
|
-
config,
|
438
|
-
container,
|
439
|
-
{ fontSize: 14, fontFamily: 'Roboto', fontColor: undefined },
|
440
|
-
{
|
441
|
-
precision: primaryDataset.valueFormat ? calculatePrecision(primaryDataset.valueFormat) : undefined,
|
442
|
-
grouped: this.containerId
|
443
|
-
}
|
444
|
-
))!
|
445
|
-
|
446
|
-
this.synchronizer.addAxis(chart.sciChartSurface.xAxes.get(0))
|
447
|
-
|
448
|
-
// 각 시리즈에 대해 올바른 데이터를 추가
|
449
|
-
const newData = this.dataSet
|
450
|
-
dataSeries.forEach((ds, seriesIndex) => {
|
451
|
-
const dataset = relatedDatasets[seriesIndex]
|
452
|
-
const filteredData = newData[seriesIndex]?.filter(d => typeof d.yValue === 'number') || []
|
453
|
-
if (filteredData.length > 0) {
|
454
|
-
ds.appendRange(
|
455
|
-
filteredData.map(d => d.xValue),
|
456
|
-
filteredData.map(d => d.yValue)
|
457
|
-
)
|
458
|
-
}
|
459
|
-
})
|
460
|
-
|
461
|
-
return { chart, dataSeries, dataKey }
|
462
|
-
}
|
463
|
-
|
464
|
-
private destroyChart(groupedChart: { dataKey: string; sciChartSurface: any; dataSeries: any[] }) {
|
465
|
-
this.verticalGroup.removeSurface(groupedChart.sciChartSurface)
|
466
|
-
this.synchronizer.removeAxis(groupedChart.sciChartSurface.xAxes.get(0))
|
467
|
-
groupedChart.sciChartSurface.delete()
|
468
|
-
}
|
469
|
-
|
470
|
-
private async addSeriesToOverviewChart(dataKey: string) {
|
471
|
-
if (!this.overviewChart || !this.overviewDataSeries) {
|
472
|
-
console.error('Overview chart is not initialized.')
|
473
|
-
return
|
474
|
-
}
|
475
|
-
|
476
|
-
// Check if the series already exists in the overview chart
|
477
|
-
const existingSeries = this.overviewChart.sciChartSurface.renderableSeries.asArray().find((series: any) => {
|
478
|
-
return series.dataSeries.dataSeriesName === dataKey
|
479
|
-
})
|
480
|
-
|
481
|
-
if (existingSeries) {
|
482
|
-
console.warn(`Series for dataKey ${dataKey} already exists in the overview chart.`)
|
483
|
-
return // Exit the function without adding the series again
|
484
|
-
}
|
485
|
-
|
486
|
-
const dataset = this.config?.data.datasets.find(dataset => dataset.dataKey === dataKey)
|
487
|
-
if (!dataset) {
|
488
|
-
console.error('Dataset not found for dataKey:', dataKey)
|
489
|
-
return
|
490
|
-
}
|
491
|
-
|
492
|
-
const newSeries = await this.createSeriesForOverview(dataset)
|
493
|
-
|
494
|
-
if (newSeries) {
|
495
|
-
this.overviewChart.sciChartSurface.renderableSeries.add(newSeries.series)
|
496
|
-
this.overviewDataSeries.push(newSeries.dataSeries)
|
497
|
-
}
|
498
|
-
}
|
499
|
-
|
500
|
-
private async removeSeriesFromOverviewChart(dataKey: string) {
|
501
|
-
if (!this.overviewChart || !this.overviewDataSeries) {
|
502
|
-
console.error('Overview chart is not initialized.')
|
503
|
-
return
|
504
|
-
}
|
505
|
-
|
506
|
-
const { sciChartSurface } = this.overviewChart
|
507
|
-
|
508
|
-
// 오버뷰 차트의 renderableSeries에서 해당 시리즈 제거
|
509
|
-
const seriesIndex = sciChartSurface.renderableSeries.asArray().findIndex((series: any) => {
|
510
|
-
return series.dataSeries.dataSeriesName === dataKey
|
511
|
-
})
|
512
|
-
|
513
|
-
if (seriesIndex !== -1) {
|
514
|
-
const series = sciChartSurface.renderableSeries.get(seriesIndex)
|
515
|
-
const yAxisId = series.yAxisId
|
516
|
-
|
517
|
-
// 시리즈 제거
|
518
|
-
sciChartSurface.renderableSeries.removeAt(seriesIndex)
|
519
|
-
this.overviewDataSeries.splice(seriesIndex, 1) // 데이터 시리즈도 제거
|
520
|
-
|
521
|
-
// 고유 Y축 제거
|
522
|
-
if (yAxisId) {
|
523
|
-
const yAxisIndex = sciChartSurface.yAxes.asArray().findIndex((axis: any) => axis.id === yAxisId)
|
524
|
-
if (yAxisIndex !== -1) {
|
525
|
-
sciChartSurface.yAxes.removeAt(yAxisIndex)
|
526
|
-
}
|
527
|
-
}
|
528
|
-
} else {
|
529
|
-
console.error('Series not found in overview chart for dataKey:', dataKey)
|
530
|
-
}
|
531
|
-
}
|
532
|
-
|
533
|
-
private async createSeriesForOverview(dataset: any) {
|
534
|
-
if (!this.overviewChart) return null
|
535
|
-
|
536
|
-
const { sciChartSurface, wasmContext } = this.overviewChart
|
537
|
-
const dataSeries = new XyDataSeries(wasmContext, {
|
538
|
-
dataSeriesName: dataset.dataKey,
|
539
|
-
containsNaN: false
|
540
|
-
})
|
541
|
-
|
542
|
-
// 새로운 Y축을 추가하여 노멀라이즈 효과를 제공
|
543
|
-
const yAxisId = `yAxis_${dataset.dataKey}`
|
544
|
-
const yAxis = new NumericAxis(wasmContext, {
|
545
|
-
id: yAxisId,
|
546
|
-
autoRange: EAutoRange.Always,
|
547
|
-
drawLabels: false,
|
548
|
-
drawMajorTickLines: false,
|
549
|
-
drawMinorTickLines: false,
|
550
|
-
drawMajorGridLines: false,
|
551
|
-
drawMinorGridLines: false
|
552
|
-
})
|
553
|
-
|
554
|
-
sciChartSurface.yAxes.add(yAxis)
|
555
|
-
|
556
|
-
const series = new FastLineRenderableSeries(wasmContext, {
|
557
|
-
dataSeries,
|
558
|
-
strokeThickness: 1,
|
559
|
-
stroke: convertColor(dataset.color, DEFAULT_COLOR),
|
560
|
-
yAxisId
|
561
|
-
})
|
562
|
-
|
563
|
-
// 초기 데이터 추가
|
564
|
-
const newData = this.dataSet.find((data, index) => this.config?.data.datasets[index].dataKey === dataset.dataKey)
|
565
|
-
if (newData && newData.length > 0) {
|
566
|
-
const filteredData = newData.filter(d => typeof d.yValue === 'number')
|
567
|
-
if (filteredData.length > 0) {
|
568
|
-
dataSeries.appendRange(
|
569
|
-
filteredData.map(d => d.xValue),
|
570
|
-
filteredData.map(d => d.yValue)
|
571
|
-
)
|
572
|
-
} else {
|
573
|
-
console.warn('No valid yValues found for dataset:', dataset.dataKey)
|
574
|
-
}
|
575
|
-
}
|
576
|
-
|
577
|
-
return { series, dataSeries }
|
578
|
-
}
|
579
|
-
}
|