@operato/scene-scichart 2.0.0-beta.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 (79) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +13 -0
  3. package/assets/favicon.ico +0 -0
  4. package/assets/images/spinner.png +0 -0
  5. package/db.sqlite +0 -0
  6. package/dist/charts/sci-candle-stick-chart.d.ts +19 -0
  7. package/dist/charts/sci-candle-stick-chart.js +248 -0
  8. package/dist/charts/sci-candle-stick-chart.js.map +1 -0
  9. package/dist/charts/volume-pallette-provider.d.ts +12 -0
  10. package/dist/charts/volume-pallette-provider.js +21 -0
  11. package/dist/charts/volume-pallette-provider.js.map +1 -0
  12. package/dist/data/binance-rest-client.d.ts +14 -0
  13. package/dist/data/binance-rest-client.js +53 -0
  14. package/dist/data/binance-rest-client.js.map +1 -0
  15. package/dist/editors/index.d.ts +0 -0
  16. package/dist/editors/index.js +2 -0
  17. package/dist/editors/index.js.map +1 -0
  18. package/dist/groups/index.d.ts +0 -0
  19. package/dist/groups/index.js +2 -0
  20. package/dist/groups/index.js.map +1 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +3 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/scichart-candle-stick.d.ts +10 -0
  25. package/dist/scichart-candle-stick.js +50 -0
  26. package/dist/scichart-candle-stick.js.map +1 -0
  27. package/dist/scichart-timeseries.d.ts +23 -0
  28. package/dist/scichart-timeseries.js +118 -0
  29. package/dist/scichart-timeseries.js.map +1 -0
  30. package/dist/scichart.d.ts +20 -0
  31. package/dist/scichart.js +70 -0
  32. package/dist/scichart.js.map +1 -0
  33. package/dist/templates/index.d.ts +14 -0
  34. package/dist/templates/index.js +4 -0
  35. package/dist/templates/index.js.map +1 -0
  36. package/dist/templates/scichart-candle-stick.d.ts +14 -0
  37. package/dist/templates/scichart-candle-stick.js +16 -0
  38. package/dist/templates/scichart-candle-stick.js.map +1 -0
  39. package/dist/templates/scichart.d.ts +14 -0
  40. package/dist/templates/scichart.js +16 -0
  41. package/dist/templates/scichart.js.map +1 -0
  42. package/dist/themes/app-theme.d.ts +56 -0
  43. package/dist/themes/app-theme.js +35 -0
  44. package/dist/themes/app-theme.js.map +1 -0
  45. package/icons/no-image.png +0 -0
  46. package/icons/scichart-candle-stick.png +0 -0
  47. package/icons/scichart.png +0 -0
  48. package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +25 -0
  49. package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +30 -0
  50. package/logs/application-2024-03-15-04.log +28 -0
  51. package/logs/application-2024-03-17-03.log +12 -0
  52. package/logs/application-2024-03-17-04.log +6 -0
  53. package/logs/connections-2024-03-15-03.log +82 -0
  54. package/logs/connections-2024-03-15-04.log +164 -0
  55. package/logs/connections-2024-03-17-03.log +88 -0
  56. package/logs/connections-2024-03-17-04.log +44 -0
  57. package/package.json +62 -0
  58. package/schema.graphql +3969 -0
  59. package/src/charts/sci-candle-stick-chart.ts +305 -0
  60. package/src/charts/volume-pallette-provider.ts +41 -0
  61. package/src/data/binance-rest-client.ts +74 -0
  62. package/src/editors/index.ts +0 -0
  63. package/src/groups/index.ts +0 -0
  64. package/src/index.ts +2 -0
  65. package/src/scichart-candle-stick.ts +60 -0
  66. package/src/scichart-timeseries.ts +156 -0
  67. package/src/scichart.ts +88 -0
  68. package/src/templates/index.ts +4 -0
  69. package/src/templates/scichart-candle-stick.ts +16 -0
  70. package/src/templates/scichart.ts +16 -0
  71. package/src/themes/app-theme.ts +72 -0
  72. package/things-scene.config.js +9 -0
  73. package/translations/en.json +3 -0
  74. package/translations/ja.json +3 -0
  75. package/translations/ko.json +3 -0
  76. package/translations/ms.json +3 -0
  77. package/translations/zh.json +3 -0
  78. package/tsconfig.json +22 -0
  79. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,305 @@
1
+ import { LitElement, PropertyValues, PropertyValueMap, css, html } from 'lit'
2
+ import { customElement, property, query, state } from 'lit/decorators.js'
3
+
4
+ import {
5
+ SciChartSurface,
6
+ NumberRange,
7
+ NumericAxis,
8
+ OhlcDataSeries,
9
+ FastCandlestickRenderableSeries,
10
+ ZoomPanModifier,
11
+ ZoomExtentsModifier,
12
+ MouseWheelZoomModifier,
13
+ ENumericFormat,
14
+ DateTimeNumericAxis,
15
+ EAutoRange,
16
+ FastLineRenderableSeries,
17
+ XyMovingAverageFilter,
18
+ SciChartOverview,
19
+ CursorModifier,
20
+ CursorTooltipSvgAnnotation,
21
+ SeriesInfo,
22
+ EDataSeriesType,
23
+ ESeriesType,
24
+ IRenderableSeries,
25
+ FastMountainRenderableSeries,
26
+ GradientParams,
27
+ Point,
28
+ OhlcSeriesInfo,
29
+ FastColumnRenderableSeries,
30
+ XyDataSeries,
31
+ FastOhlcRenderableSeries
32
+ } from 'scichart'
33
+
34
+ import { appTheme } from '../themes/app-theme'
35
+ import { VolumePaletteProvider } from './volume-pallette-provider'
36
+ import { simpleBinanceRestClient } from '../data/binance-rest-client'
37
+
38
+ const Y_AXIS_VOLUME_ID = 'Y_AXIS_VOLUME_ID'
39
+
40
+ SciChartSurface.configure({
41
+ dataUrl: `/node_modules/scichart/_wasm/scichart2d.data`,
42
+ wasmUrl: `/node_modules/scichart/_wasm/scichart2d.wasm`
43
+ })
44
+
45
+ @customElement('sci-candle-stock-chart')
46
+ export class SciCandleStockChart extends LitElement {
47
+ static styles = [
48
+ css`
49
+ :host {
50
+ display: flex;
51
+ flex-direction: column;
52
+
53
+ width: 100%;
54
+ }
55
+
56
+ #chart {
57
+ flex: 8;
58
+ }
59
+
60
+ #overview {
61
+ flex: 2;
62
+ }
63
+ `
64
+ ]
65
+
66
+ render() {
67
+ return html`
68
+ <div id="chart"></div>
69
+ <div id="overview"></div>
70
+ `
71
+ }
72
+
73
+ @property({ type: String, attribute: 'series-type' }) seriesType: 'candle-stick' | 'ohlc' = 'candle-stick'
74
+
75
+ @state() candlestickChartSeries!: FastCandlestickRenderableSeries
76
+ @state() ohlcChartSeries!: FastOhlcRenderableSeries
77
+ @state() sciChartSurface?: SciChartSurface
78
+ @state() sciChartOverview?: SciChartOverview
79
+
80
+ @query('#chart') chart!: HTMLDivElement
81
+ @query('#overview') overview!: HTMLDivElement
82
+
83
+ disconnectedCallback(): void {
84
+ if (this.sciChartSurface) {
85
+ this.sciChartSurface.delete()
86
+ this.sciChartOverview!.delete()
87
+ this.sciChartSurface = undefined
88
+ this.sciChartOverview = undefined
89
+ return
90
+ }
91
+ }
92
+
93
+ protected async firstUpdated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): Promise<void> {
94
+ const { sciChartSurface, overview, candlestickSeries, ohlcSeries } = await this.build()
95
+
96
+ this.candlestickChartSeries = candlestickSeries
97
+ this.ohlcChartSeries = ohlcSeries
98
+ this.sciChartSurface = sciChartSurface
99
+ this.sciChartOverview = overview
100
+
101
+ this.candlestickChartSeries.isVisible = this.seriesType == 'candle-stick'
102
+ this.ohlcChartSeries.isVisible = this.seriesType == 'ohlc'
103
+ }
104
+
105
+ updated(changes: PropertyValues<this>) {
106
+ if (changes.has('seriesType') && this.candlestickChartSeries) {
107
+ this.candlestickChartSeries.isVisible = this.seriesType == 'candle-stick'
108
+ this.ohlcChartSeries.isVisible = this.seriesType == 'ohlc'
109
+ }
110
+ }
111
+
112
+ // Override the Renderableseries to display on the scichart overview
113
+ private getOverviewSeries(defaultSeries: IRenderableSeries) {
114
+ if (defaultSeries.type === ESeriesType.CandlestickSeries) {
115
+ // Swap the default candlestick series on the overview chart for a mountain series. Same data
116
+ return new FastMountainRenderableSeries(defaultSeries.parentSurface.webAssemblyContext2D, {
117
+ dataSeries: defaultSeries.dataSeries,
118
+ fillLinearGradient: new GradientParams(new Point(0, 0), new Point(0, 1), [
119
+ { color: appTheme.VividSkyBlue + '77', offset: 0 },
120
+ { color: 'Transparent', offset: 1 }
121
+ ]),
122
+ stroke: appTheme.VividSkyBlue
123
+ })
124
+ }
125
+ }
126
+
127
+ // Override the standard tooltip displayed by CursorModifier
128
+ private getTooltipLegendTemplate(seriesInfos: SeriesInfo[], svgAnnotation: CursorTooltipSvgAnnotation) {
129
+ let outputSvgString = ''
130
+
131
+ // Foreach series there will be a seriesInfo supplied by SciChart. This contains info about the series under the house
132
+ seriesInfos.forEach((seriesInfo, index) => {
133
+ const y = 20 + index * 20
134
+ const textColor = seriesInfo.stroke
135
+ let legendText = seriesInfo.formattedYValue
136
+ if (seriesInfo.dataSeriesType === EDataSeriesType.Ohlc) {
137
+ const o = seriesInfo as OhlcSeriesInfo
138
+ legendText = `Open=${o.formattedOpenValue} High=${o.formattedHighValue} Low=${o.formattedLowValue} Close=${o.formattedCloseValue}`
139
+ }
140
+ outputSvgString += `<text x="8" y="${y}" font-size="13" font-family="Verdana" fill="${textColor}">
141
+ ${seriesInfo.seriesName}: ${legendText}
142
+ </text>`
143
+ })
144
+
145
+ return `<svg width="100%" height="100%">
146
+ ${outputSvgString}
147
+ </svg>`
148
+ }
149
+
150
+ private async build() {
151
+ // Create a SciChartSurface
152
+ const { sciChartSurface, wasmContext } = await SciChartSurface.create(this.chart, {
153
+ theme: appTheme.SciChartJsTheme
154
+ })
155
+
156
+ // Add an XAxis of type DateTimeAxis
157
+ // Note for crypto data this is fine, but for stocks/forex you will need to use CategoryAxis which collapses gaps at weekends
158
+ // In future we have a hybrid IndexDateAxis which 'magically' solves problems of different # of points in stock market datasetd with gaps
159
+ const xAxis = new DateTimeNumericAxis(wasmContext, {
160
+ // autoRange.never as we're setting visibleRange explicitly below. If you dont do this, leave this flag default
161
+ autoRange: EAutoRange.Never
162
+ })
163
+ sciChartSurface.xAxes.add(xAxis)
164
+
165
+ // Create a NumericAxis on the YAxis with 2 Decimal Places
166
+ sciChartSurface.yAxes.add(
167
+ new NumericAxis(wasmContext, {
168
+ growBy: new NumberRange(0.1, 0.1),
169
+ labelFormat: ENumericFormat.Decimal,
170
+ labelPrecision: 2,
171
+ labelPrefix: '$',
172
+ autoRange: EAutoRange.Always
173
+ })
174
+ )
175
+
176
+ // Create a secondary YAxis to host volume data on its own scale
177
+ sciChartSurface.yAxes.add(
178
+ new NumericAxis(wasmContext, {
179
+ id: Y_AXIS_VOLUME_ID,
180
+ growBy: new NumberRange(0, 4),
181
+ isVisible: false,
182
+ autoRange: EAutoRange.Always
183
+ })
184
+ )
185
+
186
+ // Fetch data from now to 300 1hr candles ago
187
+ const endDate = new Date(Date.now())
188
+ const startDate = new Date()
189
+ startDate.setHours(endDate.getHours() - 300)
190
+ const priceBars = await simpleBinanceRestClient.getCandles('BTCUSDT', '1h', startDate, endDate)
191
+
192
+ // Maps PriceBar { date, open, high, low, close, volume } to structure-of-arrays expected by scichart
193
+ const xValues: number[] = []
194
+ const openValues: number[] = []
195
+ const highValues: number[] = []
196
+ const lowValues: number[] = []
197
+ const closeValues: number[] = []
198
+ const volumeValues: number[] = []
199
+ priceBars.forEach((priceBar: any) => {
200
+ xValues.push(priceBar.date)
201
+ openValues.push(priceBar.open)
202
+ highValues.push(priceBar.high)
203
+ lowValues.push(priceBar.low)
204
+ closeValues.push(priceBar.close)
205
+ volumeValues.push(priceBar.volume)
206
+ })
207
+
208
+ // Zoom to the latest 100 candles
209
+ const startViewportRange = new Date()
210
+ startViewportRange.setHours(startDate.getHours() - 100)
211
+ xAxis.visibleRange = new NumberRange(startViewportRange.getTime() / 1000, endDate.getTime() / 1000)
212
+
213
+ // Create and add the Candlestick series
214
+ // The Candlestick Series requires a special dataseries type called OhlcDataSeries with o,h,l,c and date values
215
+ const candleDataSeries = new OhlcDataSeries(wasmContext, {
216
+ xValues,
217
+ openValues,
218
+ highValues,
219
+ lowValues,
220
+ closeValues,
221
+ dataSeriesName: 'BTC/USDT'
222
+ })
223
+ const candlestickSeries = new FastCandlestickRenderableSeries(wasmContext, {
224
+ dataSeries: candleDataSeries,
225
+ stroke: appTheme.ForegroundColor, // used by cursorModifier below
226
+ strokeThickness: 1,
227
+ brushUp: appTheme.VividGreen + '77',
228
+ brushDown: appTheme.MutedRed + '77',
229
+ strokeUp: appTheme.VividGreen,
230
+ strokeDown: appTheme.MutedRed
231
+ })
232
+ sciChartSurface.renderableSeries.add(candlestickSeries)
233
+
234
+ // Add an Ohlcseries. this will be invisible to begin with
235
+ const ohlcSeries = new FastOhlcRenderableSeries(wasmContext, {
236
+ dataSeries: candleDataSeries,
237
+ stroke: appTheme.ForegroundColor, // used by cursorModifier below
238
+ strokeThickness: 1,
239
+ dataPointWidth: 0.9,
240
+ strokeUp: appTheme.VividGreen,
241
+ strokeDown: appTheme.MutedRed,
242
+ isVisible: false
243
+ })
244
+ sciChartSurface.renderableSeries.add(ohlcSeries)
245
+
246
+ // Add some moving averages using SciChart's filters/transforms API
247
+ // when candleDataSeries updates, XyMovingAverageFilter automatically recomputes
248
+ sciChartSurface.renderableSeries.add(
249
+ new FastLineRenderableSeries(wasmContext, {
250
+ dataSeries: new XyMovingAverageFilter(candleDataSeries, {
251
+ dataSeriesName: 'Moving Average (20)',
252
+ length: 20
253
+ }),
254
+ stroke: appTheme.VividSkyBlue
255
+ })
256
+ )
257
+
258
+ sciChartSurface.renderableSeries.add(
259
+ new FastLineRenderableSeries(wasmContext, {
260
+ dataSeries: new XyMovingAverageFilter(candleDataSeries, {
261
+ dataSeriesName: 'Moving Average (50)',
262
+ length: 50
263
+ }),
264
+ stroke: appTheme.VividPink
265
+ })
266
+ )
267
+
268
+ // Add volume data onto the chart
269
+ sciChartSurface.renderableSeries.add(
270
+ new FastColumnRenderableSeries(wasmContext, {
271
+ dataSeries: new XyDataSeries(wasmContext, { xValues, yValues: volumeValues, dataSeriesName: 'Volume' }),
272
+ strokeThickness: 0,
273
+ // This is how we get volume to scale - on a hidden YAxis
274
+ yAxisId: Y_AXIS_VOLUME_ID,
275
+ // This is how we colour volume bars red or green
276
+ paletteProvider: new VolumePaletteProvider(
277
+ candleDataSeries,
278
+ appTheme.VividGreen + '77',
279
+ appTheme.MutedRed + '77'
280
+ )
281
+ })
282
+ )
283
+
284
+ // Optional: Add some interactivity modifiers
285
+ sciChartSurface.chartModifiers.add(
286
+ new ZoomExtentsModifier(),
287
+ new ZoomPanModifier(),
288
+ new MouseWheelZoomModifier(),
289
+ new CursorModifier({
290
+ crosshairStroke: appTheme.VividOrange,
291
+ axisLabelFill: appTheme.VividOrange,
292
+ tooltipLegendTemplate: this.getTooltipLegendTemplate
293
+ })
294
+ )
295
+
296
+ // Add Overview chart. This will automatically bind to the parent surface
297
+ // displaying its series. Zooming the chart will zoom the overview and vice versa
298
+ const overview = await SciChartOverview.create(sciChartSurface, this.overview, {
299
+ theme: appTheme.SciChartJsTheme,
300
+ transformRenderableSeries: this.getOverviewSeries as any
301
+ })
302
+
303
+ return { sciChartSurface, overview, candlestickSeries, ohlcSeries }
304
+ }
305
+ }
@@ -0,0 +1,41 @@
1
+ import {
2
+ OhlcDataSeries,
3
+ IRenderableSeries,
4
+ EFillPaletteMode,
5
+ IFillPaletteProvider,
6
+ IPointMetadata,
7
+ parseColorToUIntArgb
8
+ } from 'scichart'
9
+
10
+ export class VolumePaletteProvider implements IFillPaletteProvider {
11
+ fillPaletteMode: EFillPaletteMode = EFillPaletteMode.SOLID
12
+ private ohlcDataSeries: OhlcDataSeries
13
+ private upColorArgb: number
14
+ private downColorArgb: number
15
+
16
+ constructor(masterData: OhlcDataSeries, upColor: string, downColor: string) {
17
+ this.upColorArgb = parseColorToUIntArgb(upColor)
18
+ this.downColorArgb = parseColorToUIntArgb(downColor)
19
+ this.ohlcDataSeries = masterData
20
+ }
21
+ onAttached(parentSeries: IRenderableSeries): void {}
22
+ onDetached(): void {}
23
+
24
+ // Return up or down color for the volume bars depending on Ohlc data
25
+ overrideFillArgb(xValue: number, yValue: number, index: number, opacity?: number, metadata?: IPointMetadata): number {
26
+ const isUpCandle =
27
+ this.ohlcDataSeries.getNativeOpenValues().get(index) >= this.ohlcDataSeries.getNativeCloseValues().get(index)
28
+ return isUpCandle ? this.upColorArgb : this.downColorArgb
29
+ }
30
+
31
+ // Override stroke as well, even though strokethickness is 0, because stroke is used if column thickness goes to 0.
32
+ overrideStrokeArgb(
33
+ xValue: number,
34
+ yValue: number,
35
+ index: number,
36
+ opacity?: number,
37
+ metadata?: IPointMetadata
38
+ ): number {
39
+ return this.overrideFillArgb(xValue, yValue, index, opacity, metadata)
40
+ }
41
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Defines a price bar with Open, High, Low, Close and Date encoded as number
3
+ */
4
+ export type TPriceBar = {
5
+ date: number
6
+ open: number
7
+ high: number
8
+ low: number
9
+ close: number
10
+ volume: number
11
+ }
12
+
13
+ /**
14
+ * Parses JSON candles into TPriceBar array
15
+ * @param candles
16
+ */
17
+ const parseCandles = (candles: any[]): TPriceBar[] => {
18
+ const priceBars: TPriceBar[] = []
19
+
20
+ candles.forEach((candle: any) => {
21
+ const [timestamp, open, high, low, close, volume] = candle
22
+ const openValue = parseFloat(open)
23
+ const highValue = parseFloat(high)
24
+ const lowValue = parseFloat(low)
25
+ const closeValue = parseFloat(close)
26
+ const volumeValue = parseFloat(volume)
27
+
28
+ priceBars.push({
29
+ date: timestamp / 1000,
30
+ open: openValue,
31
+ high: highValue,
32
+ low: lowValue,
33
+ close: closeValue,
34
+ volume: volumeValue
35
+ })
36
+ })
37
+
38
+ return priceBars
39
+ }
40
+
41
+ /**
42
+ * Fetches candles from Binance Rest API
43
+ */
44
+ const getCandles = async (
45
+ symbol: string,
46
+ interval: string,
47
+ startTime?: Date,
48
+ endTime?: Date,
49
+ limit: number = 500
50
+ ): Promise<TPriceBar[]> => {
51
+ let url = `https://api.binance.us/api/v3/klines?symbol=${symbol}&interval=${interval}`
52
+ if (startTime) {
53
+ url += `&startTime=${startTime.getTime()}`
54
+ }
55
+ if (endTime) {
56
+ url += `&endTime=${endTime.getTime()}`
57
+ }
58
+ if (limit) {
59
+ url += `&limit=${limit}`
60
+ }
61
+ try {
62
+ console.log(`SimpleBinanceClient: Fetching ${symbol} ${interval} from ${startTime} to ${endTime}`)
63
+ const response = await fetch(url)
64
+ const data = await response.json()
65
+ return parseCandles(data)
66
+ } catch (err) {
67
+ console.error(err)
68
+ return []
69
+ }
70
+ }
71
+
72
+ export const simpleBinanceRestClient = {
73
+ getCandles
74
+ }
File without changes
File without changes
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default as Scichart } from './scichart'
2
+ export { default as ScichartCandleStick } from './scichart-candle-stick'
@@ -0,0 +1,60 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ const NATURE = {
6
+ mutable: false,
7
+ resizable: true,
8
+ rotatable: true,
9
+ properties: [
10
+ {
11
+ type: 'select',
12
+ label: 'series',
13
+ name: 'series',
14
+ property: {
15
+ options: ['', 'candle-stick', 'ohlc']
16
+ }
17
+ }
18
+ ]
19
+ }
20
+
21
+ import './charts/sci-candle-stick-chart'
22
+ import { Component, HTMLOverlayContainer, Properties, ComponentNature, error } from '@hatiolab/things-scene'
23
+
24
+ import { SciCandleStockChart } from './charts/sci-candle-stick-chart'
25
+
26
+ export default class ScichartCandleStick extends HTMLOverlayContainer {
27
+ static get nature(): ComponentNature {
28
+ return NATURE
29
+ }
30
+
31
+ dispose() {
32
+ super.dispose()
33
+ }
34
+
35
+ /*
36
+ * 컴포넌트의 생성 또는 속성 변화 시에 호출되며,
37
+ * 그에 따른 html element의 반영이 필요한 부분을 구현한다.
38
+ *
39
+ * ThingsComponent state => HTML element properties
40
+ */
41
+ setElementProperties(chart: SciCandleStockChart) {
42
+ const { series = 'candle-stick' } = this.state
43
+
44
+ chart.seriesType = series
45
+ }
46
+
47
+ /*
48
+ * 컴포넌트가 ready 상태가 되거나, 컴포넌트의 속성이 변화될 시 setElementProperties 뒤에 호출된다.
49
+ * 변화에 따른 기본적인 html 속성이 super.reposition()에서 진행되고, 그 밖의 작업이 필요할 때, 오버라이드 한다.
50
+ */
51
+ reposition() {
52
+ super.reposition()
53
+ }
54
+
55
+ get tagName() {
56
+ return 'sci-candle-stock-chart'
57
+ }
58
+ }
59
+
60
+ Component.register('scichart-candle-stick', ScichartCandleStick)
@@ -0,0 +1,156 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ const NATURE = {
6
+ mutable: false,
7
+ resizable: true,
8
+ rotatable: true,
9
+ properties: [
10
+ {
11
+ type: 'number',
12
+ label: 'sample-count',
13
+ name: 'sampleCount'
14
+ },
15
+ {
16
+ type: 'number',
17
+ label: 'max-value',
18
+ name: 'maxValue'
19
+ },
20
+ {
21
+ type: 'string',
22
+ label: 'attr-x',
23
+ name: 'attrX'
24
+ },
25
+ {
26
+ type: 'string',
27
+ label: 'attr-y',
28
+ name: 'attrY'
29
+ }
30
+ ]
31
+ }
32
+
33
+ import { Component, HTMLOverlayContainer, Properties, ComponentNature, error } from '@hatiolab/things-scene'
34
+
35
+ import {
36
+ MouseWheelZoomModifier,
37
+ FastLineRenderableSeries,
38
+ XyDataSeries,
39
+ ZoomExtentsModifier,
40
+ ZoomPanModifier,
41
+ NumberRange,
42
+ EAxisAlignment,
43
+ EAutoRange
44
+ } from 'scichart'
45
+
46
+ import { SciChartSurface } from 'scichart/Charting/Visuals/SciChartSurface'
47
+ import { NumericAxis } from 'scichart/Charting/Visuals/Axis/NumericAxis'
48
+
49
+ SciChartSurface.configure({
50
+ dataUrl: `/node_modules/scichart/_wasm/scichart2d.data`,
51
+ wasmUrl: `/node_modules/scichart/_wasm/scichart2d.wasm`
52
+ })
53
+
54
+ export default class ScichartTimeSeries extends HTMLOverlayContainer {
55
+ static get nature() {
56
+ return NATURE
57
+ }
58
+
59
+ _anchor?: HTMLDivElement
60
+
61
+ async oncreate_element(div: HTMLDivElement) {
62
+ const { sciChartSurface, wasmContext } = await SciChartSurface.create(div)
63
+ var { sampleCount, maxValue } = this.state
64
+
65
+ // SciChartSurface.setRuntimeLicenseKey('YOUR_RUNTIME_KEY')
66
+
67
+ const xAxis = new NumericAxis(wasmContext, {
68
+ axisTitle: 'X Axis',
69
+ autoRange: EAutoRange.Never,
70
+ axisAlignment: EAxisAlignment.Bottom,
71
+ visibleRange: new NumberRange(0, sampleCount)
72
+ })
73
+ const yAxis = new NumericAxis(wasmContext, {
74
+ axisTitle: 'Y Axis',
75
+ autoRange: EAutoRange.Never,
76
+ visibleRange: new NumberRange(0, maxValue)
77
+ })
78
+
79
+ sciChartSurface.xAxes.add(xAxis)
80
+ sciChartSurface.yAxes.add(yAxis)
81
+
82
+ const dataSeries = new XyDataSeries(wasmContext, {
83
+ xValues: this.dataSet.map(d => d.xValue),
84
+ yValues: this.dataSet.map(d => d.yValue)
85
+ })
86
+
87
+ const lineSeries = new FastLineRenderableSeries(wasmContext, {
88
+ dataSeries: dataSeries,
89
+ xAxisId: sciChartSurface.xAxes.get(0).id,
90
+ yAxisId: sciChartSurface.yAxes.get(0).id,
91
+ stroke: '#FF6600',
92
+ strokeThickness: 2
93
+ })
94
+
95
+ sciChartSurface.renderableSeries.add(lineSeries)
96
+
97
+ // ZoomPanModifier, MouseWheelZoomModifier, ZoomExtentsModifier 추가
98
+ // ZoomPanModifier: Chart를 드래그하여 이동
99
+ // MouseWheelZoomModifier: 마우스 휠로 Chart Zoom
100
+ // ZoomExtentsModifier: Chart의 전체 범위로 Zoom
101
+ sciChartSurface.chartModifiers.add(
102
+ new ZoomPanModifier({ enableZoom: true }),
103
+ new MouseWheelZoomModifier(),
104
+ new ZoomExtentsModifier()
105
+ )
106
+ }
107
+
108
+ dispose() {
109
+ super.dispose()
110
+
111
+ delete this._anchor
112
+ }
113
+
114
+ /*
115
+ * 컴포넌트의 생성 또는 속성 변화 시에 호출되며,
116
+ * 그에 따른 html element의 반영이 필요한 부분을 구현한다.
117
+ *
118
+ * ThingsComponent state => HTML element properties
119
+ */
120
+ setElementProperties(div: HTMLDivElement) {}
121
+
122
+ /*
123
+ * 컴포넌트가 ready 상태가 되거나, 컴포넌트의 속성이 변화될 시 setElementProperties 뒤에 호출된다.
124
+ * 변화에 따른 기본적인 html 속성이 super.reposition()에서 진행되고, 그 밖의 작업이 필요할 때, 오버라이드 한다.
125
+ */
126
+ reposition() {
127
+ super.reposition()
128
+ }
129
+
130
+ get dataSet(): { xValue: number; yValue: number }[] {
131
+ var { attrX, attrY, data } = this.state
132
+
133
+ if (!(data instanceof Array)) {
134
+ return []
135
+ }
136
+
137
+ return data
138
+ .map(item => {
139
+ if (!item || typeof item !== 'object') {
140
+ return
141
+ }
142
+
143
+ return {
144
+ xValue: item[attrX],
145
+ yValue: item[attrY]
146
+ }
147
+ })
148
+ .filter(Boolean) as { xValue: number; yValue: number }[]
149
+ }
150
+
151
+ get tagName() {
152
+ return 'div'
153
+ }
154
+ }
155
+
156
+ Component.register('scichart-timeseries', ScichartTimeSeries)