@operato/scene-scichart 7.0.5 → 7.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +19 -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 +154 -12
  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.d.ts +2 -19
  24. package/dist/templates/index.js +2 -1
  25. package/dist/templates/index.js.map +1 -1
  26. package/dist/templates/scichart-multiple-timeseries.d.ts +53 -0
  27. package/dist/templates/scichart-multiple-timeseries.js +81 -0
  28. package/dist/templates/scichart-multiple-timeseries.js.map +1 -0
  29. package/dist/templates/scichart-timeseries.d.ts +2 -19
  30. package/dist/templates/scichart-timeseries.js +2 -19
  31. package/dist/templates/scichart-timeseries.js.map +1 -1
  32. package/helps/scene/component/scichart-multiple-timeseries.md +23 -0
  33. package/helps/scene/component/scichart-timeseries.md +18 -0
  34. package/icons/scichart-multiple-timeseries.png +0 -0
  35. package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +9 -9
  36. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +24 -9
  37. package/logs/{application-2024-07-08-22.log → application-2024-07-28-03.log} +9 -9
  38. package/logs/{application-2024-07-08-23.log → application-2024-07-28-17.log} +140 -43
  39. package/logs/{application-2024-07-09-15.log → application-2024-07-28-18.log} +18 -18
  40. package/logs/connections-2024-07-23-14.log +50 -0
  41. package/logs/connections-2024-07-25-23.log +50 -0
  42. package/logs/connections-2024-07-26-18.log +50 -0
  43. package/logs/connections-2024-07-28-03.log +50 -0
  44. package/logs/connections-2024-07-28-17.log +200 -0
  45. package/logs/connections-2024-07-28-18.log +100 -0
  46. package/package.json +2 -2
  47. package/schema.graphql +211 -0
  48. package/src/charts/axis-synchronizer.ts +37 -0
  49. package/src/charts/ox-scichart-multiple.ts +334 -0
  50. package/src/charts/ox-scichart.ts +1 -1
  51. package/src/charts/scichart-builder.ts +197 -11
  52. package/src/index.ts +1 -0
  53. package/src/scichart-multiple-timeseries.ts +74 -0
  54. package/src/scichart-timeseries.ts +3 -54
  55. package/src/templates/index.ts +2 -1
  56. package/src/templates/scichart-multiple-timeseries.ts +87 -0
  57. package/src/templates/scichart-timeseries.ts +2 -19
  58. package/things-scene.config.js +0 -2
  59. package/translations/en.json +3 -1
  60. package/translations/ja.json +3 -1
  61. package/translations/ko.json +3 -1
  62. package/translations/ms.json +3 -1
  63. package/translations/zh.json +3 -1
  64. package/tsconfig.tsbuildinfo +1 -1
  65. package/cache/translations/system/en.json +0 -1
  66. package/cache/translations/system/ko.json +0 -1
  67. package/logs/connections-2024-07-08-22.log +0 -50
  68. package/logs/connections-2024-07-08-23.log +0 -100
  69. package/logs/connections-2024-07-09-15.log +0 -100
@@ -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,10 @@ import {
16
15
  DateTimeNumericAxis,
17
16
  EAutoRange,
18
17
  EAxisAlignment,
18
+ EExecuteOn,
19
+ ECoordinateMode,
20
+ EHorizontalAnchorPoint,
21
+ EVerticalAnchorPoint,
19
22
  NumberRange,
20
23
  MouseWheelZoomModifier,
21
24
  RubberBandXyZoomModifier,
@@ -33,8 +36,16 @@ import {
33
36
  ELegendPlacement,
34
37
  EXyDirection,
35
38
  XAxisDragModifier,
36
- YAxisDragModifier
39
+ YAxisDragModifier,
40
+ TextAnnotation,
41
+ LineAnnotation,
42
+ BoxAnnotation,
43
+ HorizontalLineAnnotation,
44
+ VerticalLineAnnotation,
45
+ OverviewRangeSelectionModifier,
46
+ ENumericFormat
37
47
  } from 'scichart'
48
+ import { AxisSynchroniser } from './axis-synchronizer'
38
49
 
39
50
  SciChartSurface.UseCommunityLicense()
40
51
 
@@ -49,6 +60,11 @@ const POINT_MARKER_SIZE = 10
49
60
  const STROKE_THICKNESS = 2
50
61
  const ANIMATION_DURATION = 1000
51
62
 
63
+ function getLocalTimeOffset() {
64
+ const now = new Date()
65
+ return now.getTimezoneOffset() * -60
66
+ }
67
+
52
68
  function getBaseColorFromTheme(theme?: 'light' | 'dark' | 'auto') {
53
69
  return new TinyColor(theme == 'dark' ? '#fff' : '#000')
54
70
  }
@@ -98,7 +114,8 @@ function createAxis(
98
114
  isXAxis: boolean,
99
115
  fontColor: string,
100
116
  fontFamily?: string,
101
- fontSize?: number
117
+ fontSize?: number,
118
+ options?: any
102
119
  ) {
103
120
  const { axisTitle, ticks } = axis
104
121
  const {
@@ -128,11 +145,24 @@ function createAxis(
128
145
  fontFamily,
129
146
  fontSize,
130
147
  color: textStrokeColor
131
- }
148
+ },
149
+ ...options
132
150
  }
133
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
+
134
161
  return isXAxis
135
- ? new DateTimeNumericAxis(wasmContext, { ...axisOptions, labelProvider: new SmartDateLabelProvider() })
162
+ ? new DateTimeNumericAxis(wasmContext, {
163
+ ...axisOptions,
164
+ labelProvider
165
+ })
136
166
  : new NumericAxis(wasmContext, { ...axisOptions, id: index !== 0 ? `yAxis${index}` : undefined })
137
167
  }
138
168
 
@@ -204,7 +234,8 @@ function createSeries(
204
234
  export async function buildSciChart(
205
235
  config: OperatoChart.ChartConfig | undefined | null,
206
236
  container: any,
207
- { fontSize, fontFamily, fontColor }: { fontSize?: number; fontFamily?: string; fontColor?: string }
237
+ { fontSize, fontFamily, fontColor }: { fontSize?: number; fontFamily?: string; fontColor?: string },
238
+ grouped?: string
208
239
  ): Promise<{ chart: any; dataSeries: any[] } | undefined> {
209
240
  if (!config) return
210
241
 
@@ -219,7 +250,9 @@ export async function buildSciChart(
219
250
  xGridLine,
220
251
  yGridLine,
221
252
  y2ndGridLine,
222
- stacked
253
+ stacked,
254
+ multiAxis,
255
+ annotations
223
256
  } = options || {}
224
257
 
225
258
  var baseColor = getBaseColorFromTheme(theme)
@@ -244,14 +277,14 @@ export async function buildSciChart(
244
277
  })
245
278
 
246
279
  // Y 축 설정
247
- yAxes.forEach((axis, index) => {
280
+ ;(multiAxis ? yAxes : [yAxes[0]]).forEach((axis, index) => {
248
281
  const yAxis = createAxis(wasmContext, axis, index, false, fontColor, fontFamily, fontSize)
249
282
  sciChartSurface.yAxes.add(yAxis)
250
283
  })
251
284
 
252
285
  // 시리즈 설정
253
286
  const dataSeriesArray = datasets.map((dataset, index) => {
254
- const yAxisId = dataset.yAxisID == 'right' ? 'yAxis1' : undefined
287
+ const yAxisId = dataset.yAxisID == 'right' && multiAxis ? 'yAxis1' : undefined
255
288
  const { series, dataSeries } = createSeries(wasmContext, dataset, index, !!stacked, !!animation, yAxisId)
256
289
 
257
290
  sciChartSurface.renderableSeries.add(series)
@@ -259,7 +292,8 @@ export async function buildSciChart(
259
292
  if (tooltip) {
260
293
  const rolloverModifier = new RolloverModifier({
261
294
  showTooltip: true,
262
- showAxisLabel: true
295
+ showAxisLabel: true,
296
+ modifierGroup: grouped
263
297
  })
264
298
 
265
299
  sciChartSurface.chartModifiers.add(rolloverModifier)
@@ -290,9 +324,84 @@ export async function buildSciChart(
290
324
  }
291
325
  }
292
326
 
327
+ if (annotations) {
328
+ annotations.forEach(annotation => {
329
+ let sciAnnotation: any
330
+ let horizontalAnchorPoint: EHorizontalAnchorPoint =
331
+ annotation.horizontalAnchorPoint == 'Right'
332
+ ? EHorizontalAnchorPoint.Right
333
+ : annotation.horizontalAnchorPoint == 'Left'
334
+ ? EHorizontalAnchorPoint.Left
335
+ : EHorizontalAnchorPoint.Center
336
+ let verticalAnchorPoint: EVerticalAnchorPoint =
337
+ annotation.verticalAnchorPoint == 'Top'
338
+ ? EVerticalAnchorPoint.Top
339
+ : annotation.verticalAnchorPoint == 'Bottom'
340
+ ? EVerticalAnchorPoint.Bottom
341
+ : EVerticalAnchorPoint.Center
342
+
343
+ switch (annotation.type) {
344
+ case 'text':
345
+ sciAnnotation = new TextAnnotation({
346
+ x1: annotation.x1,
347
+ y1: annotation.y1,
348
+ text: annotation.text,
349
+ horizontalAnchorPoint,
350
+ verticalAnchorPoint,
351
+ fontSize: annotation.fontSize,
352
+ fontFamily: annotation.fontFamily,
353
+ textColor: convertColor(annotation.stroke, fontColor)
354
+ })
355
+ break
356
+ case 'line':
357
+ sciAnnotation = new LineAnnotation({
358
+ x1: annotation.x1,
359
+ y1: annotation.y1,
360
+ x2: annotation.x2,
361
+ y2: annotation.y2,
362
+ stroke: convertColor(annotation.stroke, '#FF0000'),
363
+ strokeThickness: annotation.strokeThickness,
364
+ xCoordinateMode: ECoordinateMode.Relative,
365
+ yCoordinateMode: ECoordinateMode.DataValue
366
+ })
367
+ break
368
+ case 'box':
369
+ sciAnnotation = new BoxAnnotation({
370
+ x1: annotation.x1,
371
+ y1: annotation.y1,
372
+ x2: annotation.x2,
373
+ y2: annotation.y2,
374
+ fill: convertColor(annotation.fill, '#FF0000'),
375
+ stroke: convertColor(annotation.stroke, '#FF0000'),
376
+ strokeThickness: annotation.strokeThickness
377
+ })
378
+ break
379
+ case 'horizontalLine':
380
+ sciAnnotation = new HorizontalLineAnnotation({
381
+ y1: annotation.y1,
382
+ stroke: convertColor(annotation.stroke, '#FF0000'),
383
+ strokeThickness: annotation.strokeThickness
384
+ })
385
+ break
386
+ case 'verticalLine':
387
+ sciAnnotation = new VerticalLineAnnotation({
388
+ x1: annotation.x1,
389
+ stroke: convertColor(annotation.stroke, '#FF0000'),
390
+ strokeThickness: annotation.strokeThickness
391
+ })
392
+ break
393
+ default:
394
+ break
395
+ }
396
+ if (sciAnnotation) {
397
+ sciChartSurface.annotations.add(sciAnnotation)
398
+ }
399
+ })
400
+ }
401
+
293
402
  // 줌인/줌아웃 모디파이어 추가
294
403
  sciChartSurface.chartModifiers.add(
295
- // new RubberBandXyZoomModifier(),
404
+ new RubberBandXyZoomModifier({ executeOn: EExecuteOn.MouseRightButton, modifierGroup: grouped }),
296
405
  // new ZoomPanModifier({ xyDirection: EXyDirection.XDirection }),
297
406
  new ZoomPanModifier(),
298
407
  new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection }),
@@ -321,3 +430,80 @@ export async function buildSciChart(
321
430
 
322
431
  return { chart, dataSeries: dataSeriesArray }
323
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'