@operato/scene-chartjs 7.3.13 → 7.3.19

Sign up to get free protection for your applications and to get access to all the features.
package/src/ox-chart.ts DELETED
@@ -1,168 +0,0 @@
1
- import 'chartjs-plugin-datalabels'
2
- import 'chartjs-plugin-style'
3
-
4
- import { LitElement, PropertyValues, html } from 'lit'
5
- import { customElement, property, query } from 'lit/decorators.js'
6
-
7
- import { Chart } from 'chart.js'
8
- import { format as formatText } from '@operato/utils/format.js'
9
- import DataBinderPlugin from './plugins/chartjs-plugin-data-binder'
10
- import { convertConfigure } from './config-converter'
11
-
12
- Chart.plugins.register(DataBinderPlugin)
13
-
14
- @customElement('ox-chart')
15
- export class OxChart extends LitElement {
16
- @property({ type: Number }) width!: number
17
- @property({ type: Number }) height!: number
18
- @property({ type: Object }) options!: SceneChart.ChartConfig
19
- @property({ type: Object }) data!: SceneChart.ChartData
20
-
21
- private _chart?: SceneChart | null
22
-
23
- @query('canvas') _canvas!: HTMLCanvasElement
24
-
25
- firstUpdated() {
26
- this.initChart()
27
- }
28
-
29
- render() {
30
- return html` <canvas></canvas> `
31
- }
32
-
33
- dispose() {
34
- this._chart?.destroy()
35
- this._chart = null
36
- }
37
-
38
- updated(changes: PropertyValues<this>) {
39
- if (changes.has('width') || changes.has('height')) {
40
- this.updateChartSize()
41
- }
42
-
43
- if (changes.has('options')) {
44
- this.updateChartConfig()
45
- }
46
-
47
- if (changes.has('data')) {
48
- this._chart!.data.rawData = this.data
49
- this._chart!.update()
50
- }
51
- }
52
-
53
- initChart() {
54
- const { data, options, type } = this.options
55
- this.options.options.tooltip = this.options.options.tooltip ?? true
56
- options!.maintainAspectRatio = false
57
-
58
- this.attachPluginOptions(options)
59
- convertConfigure(this.options as SceneChart.ChartConfig)
60
-
61
- this._chart = new Chart(this._canvas, {
62
- type,
63
- data,
64
- options
65
- }) as SceneChart
66
-
67
- this.updateChartSize()
68
- }
69
-
70
- updateChartSize() {
71
- const width = Math.floor(this.width)
72
- const height = Math.floor(this.height)
73
-
74
- this._canvas.style.width = `${width}px`
75
- this._canvas.style.height = `${height}px`
76
-
77
- const _ = () => {
78
- if (this._canvas.offsetWidth == 0 || this._canvas.offsetHeight == 0) {
79
- requestAnimationFrame(_)
80
- } else {
81
- /*
82
- 주의 : chart.resize() 내에서 pixel ratio를 감안해서, canvas 의 width, height를 설정하기때문에,
83
- 별도 처리가 필요하지 않다.
84
- */
85
- this._chart!.resize()
86
- }
87
- }
88
-
89
- requestAnimationFrame(_)
90
- }
91
-
92
- updateChartConfig() {
93
- if (!this._chart) return
94
-
95
- const { data, options, type } = this.options
96
- options!.maintainAspectRatio = false
97
-
98
- this.attachPluginOptions(options)
99
- convertConfigure(this.options as SceneChart.ChartConfig)
100
-
101
- this._chart.type = type
102
- this._chart.data = data
103
- this._chart.options = options
104
- this._chart.data.rawData = this.data
105
- this._chart.update()
106
- }
107
-
108
- attachPluginOptions(options: SceneChart.ChartOptions) {
109
- if (!options.plugins) {
110
- options.plugins = {}
111
- }
112
-
113
- this.attachDatalabelPluginOptions(options.plugins)
114
- }
115
-
116
- attachDatalabelPluginOptions(pluginOptions: SceneChart.ChartPluginsOptions) {
117
- pluginOptions.datalabels = {
118
- ...pluginOptions.datalabels,
119
- display: function (context) {
120
- //@ts-ignore
121
- return !!context.dataset.displayValue
122
- },
123
- anchor: function (context) {
124
- //@ts-ignore
125
- return context.dataset.dataLabelAnchor || 'center'
126
- },
127
- offset: function (context) {
128
- //@ts-ignore
129
- return context.dataset.dataLabelOffset || 0
130
- },
131
- //@ts-ignore
132
- align: function (context) {
133
- //@ts-ignore
134
- return context.dataset.dataLabelAnchor || 'center'
135
- },
136
- //@ts-ignore
137
- rotation: function (context) {
138
- //@ts-ignore
139
- return context.dataset.dataLabelRotation || 0
140
- },
141
- color: function (context) {
142
- //@ts-ignore
143
- return context.dataset?.defaultFontColor || '#000'
144
- },
145
- font: function (context) {
146
- return {
147
- //@ts-ignore
148
- size: context.dataset?.defaultFontSize,
149
- //@ts-ignore
150
- family: context.chart.options?.defaultFontFamily
151
- }
152
- },
153
- clamp: true,
154
- formatter: function (value, context) {
155
- //@ts-ignore
156
- var format = context.dataset.valueFormat || ''
157
- //@ts-ignore
158
- var prefix = context.dataset.valuePrefix || ''
159
- //@ts-ignore
160
- var suffix = context.dataset.valueSuffix || ''
161
- if (value == undefined) return value
162
-
163
- var stringValue = format ? formatText(format, Number(value)) : Number(value).toLocaleString()
164
- return prefix + stringValue + suffix
165
- }
166
- }
167
- }
168
- }
@@ -1,41 +0,0 @@
1
- import 'ses'
2
-
3
- function seriesHighlight(chartInstance: SceneChart, seriesData: SceneChart.DataSeries) {
4
- chartInstance.data.datasets?.forEach(dataset => {
5
- let highlight = dataset.highlight
6
- if (!highlight) {
7
- return
8
- }
9
-
10
- let highlightColor = highlight.color
11
- let highlightCondition = highlight.condition
12
- const c = new Compartment()
13
-
14
- seriesData.forEach((sdata, sIndex) => {
15
- sdata.forEach((data: SceneChart.Data, i: number) => {
16
- if (!c.evaluate(highlightCondition)) {
17
- return
18
- }
19
-
20
- let meta = chartInstance.getDatasetMeta(sIndex)
21
- meta.data[i]._model.backgroundColor = highlightColor
22
- //@ts-ignore
23
- meta.data[i]._model.hoverBackgroundColor = highlightColor
24
-
25
- // dataset.backgroundColor = highlightColor
26
- })
27
- })
28
- })
29
- }
30
-
31
- export default {
32
- id: 'chart-series-highlight',
33
- beforeDraw: function (chartInstance: SceneChart) {
34
- if (!chartInstance.data.rawData) {
35
- return
36
- }
37
-
38
- let seriesData = chartInstance.data.rawData.seriesData
39
- seriesHighlight(chartInstance, seriesData)
40
- }
41
- }
@@ -1,134 +0,0 @@
1
- function convertObject(
2
- dataArray: string | SceneChart.DataSeries | Object,
3
- chartInstance: SceneChart
4
- ): null | Object | SceneChart.DataSeries {
5
- if (!dataArray) {
6
- return null
7
- }
8
-
9
- if (typeof dataArray == 'string') {
10
- try {
11
- dataArray = JSON.parse(dataArray)
12
- } catch (e) {
13
- console.warn('invalid chart data format', e)
14
- return null
15
- }
16
- }
17
-
18
- if (!(dataArray instanceof Array)) {
19
- // is not Array
20
- if (dataArray instanceof Object) {
21
- return dataArray
22
- }
23
- return null
24
- }
25
-
26
- if (dataArray.length === 0) {
27
- return null
28
- }
29
-
30
- // modeling중 변수 기본값에 대한 처리
31
- if (dataArray[0].hasOwnProperty('__field1')) {
32
- dataArray = toObjectArrayValue(dataArray) as SceneChart.DataSeries
33
- }
34
-
35
- let label = chartInstance.data.labelDataKey
36
- let seriesKeys = []
37
-
38
- for (let i in chartInstance.data.datasets) {
39
- seriesKeys.push(chartInstance.data.datasets[Number(i)].dataKey)
40
- }
41
-
42
- let seriesData: SceneChart.DataSeries = []
43
- let labelData: SceneChart.DataSeries = []
44
-
45
- let convertedObject = {
46
- seriesData,
47
- labelData
48
- }
49
-
50
- for (let i = 0; i < (dataArray as Array<any>).length; i++) {
51
- let currData: SceneChart.Data = (dataArray as SceneChart.DataSeries)[Number(i)]
52
- labelData.push(currData[label!])
53
-
54
- for (let i in seriesKeys) {
55
- if (!seriesKeys[i]) continue
56
-
57
- if (!seriesData[i]) seriesData[i] = []
58
-
59
- // 값이 NaN 경우엔 차트를 그리지 않음
60
- if (isNaN(currData[seriesKeys[i]])) {
61
- currData[seriesKeys[i]] = NaN
62
- }
63
-
64
- seriesData[i].push(currData[seriesKeys[i]])
65
- }
66
- }
67
-
68
- return convertedObject
69
- }
70
-
71
- function toObjectArrayValue(array: SceneChart.DataSeries): SceneChart.DataSeries | null {
72
- if (!array || array.length === 0) {
73
- return null
74
- }
75
-
76
- let indexKeyMap: SceneChart.Data = {}
77
- let value = []
78
-
79
- for (let key in array[0]) {
80
- indexKeyMap[key] = array[0][key]
81
- }
82
-
83
- for (var i = 1; i < array.length; i++) {
84
- let object: SceneChart.Data = {}
85
- let thisObject = array[i]
86
-
87
- for (let key in indexKeyMap) {
88
- let k = indexKeyMap[key]
89
- let v = thisObject[key]
90
- object[k] = v
91
- }
92
-
93
- value.push(object)
94
- }
95
-
96
- return value
97
- }
98
-
99
- function updateSeriesDatas(chartInstance: SceneChart) {
100
- if (!chartInstance.data.rawData) {
101
- return
102
- }
103
-
104
- let seriesData = chartInstance.data.rawData.seriesData
105
-
106
- if (!seriesData || seriesData.length === 0) seriesData = [null]
107
-
108
- for (let key in chartInstance.data.datasets) {
109
- chartInstance.data.datasets[Number(key)].data = seriesData[key] || []
110
- }
111
- }
112
-
113
- function updateLabelDatas(chartInstance: SceneChart) {
114
- let labelData = chartInstance.data.rawData.labelData
115
- chartInstance.config.data!.labels = labelData || []
116
- }
117
-
118
- export default {
119
- id: 'data-binder',
120
- beforeUpdate: function (chartInstance: SceneChart) {
121
- if (!chartInstance.data) return
122
-
123
- if (!chartInstance.data.rawData) chartInstance.data.rawData = []
124
-
125
- chartInstance.data.rawData = convertObject(chartInstance.data.rawData, chartInstance) || {
126
- seriesData: [],
127
- labelData: []
128
- }
129
-
130
- let seriesData = chartInstance.data.rawData.seriesData
131
- updateLabelDatas(chartInstance)
132
- updateSeriesDatas(chartInstance)
133
- }
134
- }
@@ -1,102 +0,0 @@
1
- declare class SceneChart extends Chart {
2
- type: Chart.ChartType | string
3
- data: SceneChart.ChartData
4
- }
5
-
6
- declare namespace SceneChart {
7
- type Theme = 'light' | 'dark'
8
- type Data = { [key: string]: any }
9
- type DataSeries = Array<Data>
10
-
11
- interface TickOptions extends Chart.TickOptions {
12
- autoMax?: boolean
13
- autoMin?: boolean
14
- }
15
-
16
- interface ChartScales {
17
- type?: Chart.ScaleType | string
18
- display?: boolean
19
- position?: Chart.PositionType | string
20
- gridLines?: GridLineOptions
21
- scaleLabel?: Chart.ScaleTitleOptions
22
- ticks?: TickOptions
23
- xAxes?: ChartXAxe[]
24
- yAxes?: ChartYAxe[]
25
- }
26
-
27
- interface ChartDataSets extends Chart.ChartDataSets {
28
- color: string
29
- dataKey: string
30
- valueFormat: string
31
- valuePrefix: string
32
- valueSuffix: string
33
- displayValue: string
34
- dataLabelAnchor: string
35
- dataLabelOffset?: number
36
- dataLabelRotation?: number
37
- defaultFontColor: string
38
- defaultFontSize: number
39
- highlight: {
40
- color: string
41
- condition: string
42
- }
43
- }
44
-
45
- interface ChartData {
46
- labels?: Array<string | string[]>
47
- datasets?: ChartDataSets[]
48
- rawData?: any
49
- labelDataKey?: string
50
- }
51
-
52
- interface ChartXAxe extends Chart.ChartXAxe {
53
- categorySpacing?: number
54
- barSpacing?: number
55
- ticks?: TickOptions
56
- axisTitle?: string
57
- }
58
- interface ChartYAxe extends ChartXAxe {}
59
-
60
- interface GridLineOptions extends Chart.GridLineOptions {}
61
- interface ChartLegendOptions extends Chart.ChartLegendOptions {}
62
- interface ChartTooltipOptions extends Chart.ChartTooltipOptions {}
63
- interface ChartTooltipItem extends Chart.ChartTooltipItem {}
64
- interface RadialLinearScale extends Chart.RadialLinearScale {}
65
- interface ChartPluginsOptions extends Chart.ChartPluginsOptions {}
66
-
67
- interface Context {
68
- dataset: ChartDataSets
69
- }
70
-
71
- interface DataLabelsPluginOptions {
72
- display: (context: Context) => true | false | 'auto'
73
- anchor: (context: Context) => 'center' | 'start' | 'end' | string
74
- color: (context: Context) => string
75
- font: (context: Context) => { size: number }
76
- clamp: boolean
77
- formatter: (value: any, context: Context) => string
78
- }
79
-
80
- interface ChartOptions extends Chart.ChartOptions {
81
- scales: ChartScales
82
- scale: RadialLinearScale
83
- legend: ChartLegendOptions
84
- tooltip: boolean /* show or hide tooltip */
85
- tooltips: ChartTooltipOptions
86
- multiAxis: boolean
87
- defaultFontSize: number | string
88
- defaultFontFamily: string
89
- defaultFontColor: string
90
- theme: Theme
91
- stacked?: boolean
92
- xGridLine: boolean
93
- fillStyle: string
94
- maintainAspectRatio?: boolean
95
- }
96
-
97
- interface ChartConfig {
98
- type: string
99
- data: ChartData
100
- options: ChartOptions
101
- }
102
- }
@@ -1,121 +0,0 @@
1
- const icon = new URL('../../icons/bar-chart.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'bar-chart',
5
- description: 'ChartJS - barchart',
6
- icon: icon,
7
- group: 'chartAndGauge',
8
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
9
- model: {
10
- type: 'chartjs',
11
- top: 200,
12
- left: 300,
13
- width: 200,
14
- height: 200,
15
- chart: {
16
- type: 'bar',
17
- data: {
18
- labels: [],
19
- datasets: [
20
- {
21
- label: 'series 1',
22
- type: 'bar',
23
- data: [],
24
- backgroundColor: 'rgb(66, 110, 164)',
25
- borderColor: 'rgb(66, 110, 164)',
26
- borderWidth: 0,
27
- dataKey: 'value',
28
- yAxisID: 'left'
29
- }
30
- ],
31
- labelDataKey: 'color'
32
- },
33
- options: {
34
- theme: 'dark',
35
- xGridLine: false,
36
- yGridLine: true,
37
- legend: {
38
- display: true,
39
- position: 'top'
40
- },
41
- scales: {
42
- xAxes: [
43
- {
44
- gridLines: {
45
- display: false
46
- },
47
- scaleLabel: {
48
- labelString: '',
49
- display: false
50
- },
51
- ticks: {
52
- display: true
53
- }
54
- }
55
- ],
56
- yAxes: [
57
- {
58
- id: 'left',
59
- position: 'left',
60
- gridLines: {
61
- display: true
62
- },
63
- scaleLabel: {
64
- labelString: '',
65
- display: false
66
- },
67
- ticks: {
68
- autoMin: true,
69
- autoMax: true,
70
- display: true
71
- }
72
- },
73
- {
74
- id: 'right',
75
- position: 'right',
76
- display: false,
77
- gridLines: {
78
- display: false
79
- },
80
- scaleLabel: {
81
- labelString: '',
82
- display: false
83
- },
84
- ticks: {
85
- autoMin: true,
86
- autoMax: true,
87
- display: true
88
- }
89
- }
90
- ]
91
- }
92
- }
93
- },
94
- data: [
95
- {
96
- color: 'Red',
97
- value: 12
98
- },
99
- {
100
- color: 'Blue',
101
- value: 19
102
- },
103
- {
104
- color: 'Yellow',
105
- value: 3
106
- },
107
- {
108
- color: 'Green',
109
- value: 5
110
- },
111
- {
112
- color: 'Purple',
113
- value: 2
114
- },
115
- {
116
- color: 'Orange',
117
- value: 3
118
- }
119
- ]
120
- }
121
- }
@@ -1,55 +0,0 @@
1
- const icon = new URL('../../icons/doughnut-chart.png', import.meta.url).href
2
-
3
- export default {
4
- type: 'doughnut-chart',
5
- description: 'ChartJS - doughnut',
6
- icon: icon,
7
- group: 'chartAndGauge',
8
- /* line|shape|textAndMedia|chartAndGauge|table|container|dataSource|IoT|3D|warehouse|form|etc */
9
- model: {
10
- type: 'chartjs',
11
- top: 0,
12
- left: 0,
13
- width: 200,
14
- height: 200,
15
- chart: {
16
- type: 'doughnut',
17
- data: {
18
- labels: [],
19
- datasets: [
20
- {
21
- data: [],
22
- backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
23
- borderWidth: 0,
24
- dataKey: 'value'
25
- }
26
- ],
27
- labelDataKey: 'label'
28
- },
29
- options: {
30
- theme: 'dark',
31
- legend: {
32
- display: true,
33
- position: 'top'
34
- },
35
- animation: {
36
- animateScale: true
37
- }
38
- }
39
- },
40
- data: [
41
- {
42
- label: 'Red',
43
- value: 300
44
- },
45
- {
46
- label: 'Blue',
47
- value: 50
48
- },
49
- {
50
- label: 'Yellow',
51
- value: 100
52
- }
53
- ]
54
- }
55
- }