@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.
- package/CHANGELOG.md +19 -0
- package/db.sqlite +0 -0
- package/dist/charts/axis-synchronizer.d.ts +10 -0
- package/dist/charts/axis-synchronizer.js +32 -0
- package/dist/charts/axis-synchronizer.js.map +1 -0
- package/dist/charts/ox-scichart-multiple.d.ts +40 -0
- package/dist/charts/ox-scichart-multiple.js +272 -0
- package/dist/charts/ox-scichart-multiple.js.map +1 -0
- package/dist/charts/ox-scichart.d.ts +1 -1
- package/dist/charts/ox-scichart.js.map +1 -1
- package/dist/charts/scichart-builder.d.ts +10 -1
- package/dist/charts/scichart-builder.js +154 -12
- package/dist/charts/scichart-builder.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/scichart-multiple-timeseries.d.ts +14 -0
- package/dist/scichart-multiple-timeseries.js +60 -0
- package/dist/scichart-multiple-timeseries.js.map +1 -0
- package/dist/scichart-timeseries.d.ts +2 -11
- package/dist/scichart-timeseries.js +2 -42
- package/dist/scichart-timeseries.js.map +1 -1
- package/dist/templates/index.d.ts +2 -19
- package/dist/templates/index.js +2 -1
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/scichart-multiple-timeseries.d.ts +53 -0
- package/dist/templates/scichart-multiple-timeseries.js +81 -0
- package/dist/templates/scichart-multiple-timeseries.js.map +1 -0
- package/dist/templates/scichart-timeseries.d.ts +2 -19
- package/dist/templates/scichart-timeseries.js +2 -19
- package/dist/templates/scichart-timeseries.js.map +1 -1
- package/helps/scene/component/scichart-multiple-timeseries.md +23 -0
- package/helps/scene/component/scichart-timeseries.md +18 -0
- package/icons/scichart-multiple-timeseries.png +0 -0
- package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +9 -9
- package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +24 -9
- package/logs/{application-2024-07-08-22.log → application-2024-07-28-03.log} +9 -9
- package/logs/{application-2024-07-08-23.log → application-2024-07-28-17.log} +140 -43
- package/logs/{application-2024-07-09-15.log → application-2024-07-28-18.log} +18 -18
- package/logs/connections-2024-07-23-14.log +50 -0
- package/logs/connections-2024-07-25-23.log +50 -0
- package/logs/connections-2024-07-26-18.log +50 -0
- package/logs/connections-2024-07-28-03.log +50 -0
- package/logs/connections-2024-07-28-17.log +200 -0
- package/logs/connections-2024-07-28-18.log +100 -0
- package/package.json +2 -2
- package/schema.graphql +211 -0
- package/src/charts/axis-synchronizer.ts +37 -0
- package/src/charts/ox-scichart-multiple.ts +334 -0
- package/src/charts/ox-scichart.ts +1 -1
- package/src/charts/scichart-builder.ts +197 -11
- package/src/index.ts +1 -0
- package/src/scichart-multiple-timeseries.ts +74 -0
- package/src/scichart-timeseries.ts +3 -54
- package/src/templates/index.ts +2 -1
- package/src/templates/scichart-multiple-timeseries.ts +87 -0
- package/src/templates/scichart-timeseries.ts +2 -19
- package/things-scene.config.js +0 -2
- package/translations/en.json +3 -1
- package/translations/ja.json +3 -1
- package/translations/ko.json +3 -1
- package/translations/ms.json +3 -1
- package/translations/zh.json +3 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/cache/translations/system/en.json +0 -1
- package/cache/translations/system/ko.json +0 -1
- package/logs/connections-2024-07-08-22.log +0 -50
- package/logs/connections-2024-07-08-23.log +0 -100
- 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
|
-
|
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, {
|
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
|
-
|
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