@orbcharts/core 3.0.0-alpha.52 → 3.0.0-alpha.53

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-core.es.js +709 -703
  3. package/dist/orbcharts-core.umd.js +2 -2
  4. package/dist/src/types/ContextObserverMultiGrid.d.ts +2 -1
  5. package/dist/vite.config.d.ts +1 -1
  6. package/package.json +41 -41
  7. package/src/AbstractChart.ts +48 -48
  8. package/src/GridChart.ts +20 -20
  9. package/src/MultiGridChart.ts +20 -20
  10. package/src/MultiValueChart.ts +20 -20
  11. package/src/RelationshipChart.ts +20 -20
  12. package/src/SeriesChart.ts +20 -20
  13. package/src/TreeChart.ts +20 -20
  14. package/src/base/createBaseChart.ts +369 -369
  15. package/src/base/createBasePlugin.ts +95 -95
  16. package/src/defaults.ts +226 -226
  17. package/src/defineGridPlugin.ts +3 -3
  18. package/src/defineMultiGridPlugin.ts +3 -3
  19. package/src/defineMultiValuePlugin.ts +3 -3
  20. package/src/defineNoneDataPlugin.ts +4 -4
  21. package/src/defineRelationshipPlugin.ts +3 -3
  22. package/src/defineSeriesPlugin.ts +3 -3
  23. package/src/defineTreePlugin.ts +3 -3
  24. package/src/grid/computeGridData.ts +134 -134
  25. package/src/grid/createGridContextObserver.ts +155 -155
  26. package/src/grid/gridObservables.ts +607 -607
  27. package/src/index.ts +21 -21
  28. package/src/multiGrid/computeMultiGridData.ts +130 -130
  29. package/src/multiGrid/createMultiGridContextObserver.ts +41 -40
  30. package/src/multiGrid/multiGridObservables.ts +365 -364
  31. package/src/multiValue/computeMultiValueData.ts +143 -143
  32. package/src/multiValue/createMultiValueContextObserver.ts +12 -12
  33. package/src/relationship/computeRelationshipData.ts +118 -118
  34. package/src/relationship/createRelationshipContextObserver.ts +12 -12
  35. package/src/series/computeSeriesData.ts +90 -90
  36. package/src/series/createSeriesContextObserver.ts +93 -93
  37. package/src/series/seriesObservables.ts +175 -175
  38. package/src/tree/computeTreeData.ts +132 -132
  39. package/src/tree/createTreeContextObserver.ts +61 -61
  40. package/src/tree/treeObservables.ts +94 -94
  41. package/src/types/Chart.ts +50 -50
  42. package/src/types/ChartParams.ts +51 -51
  43. package/src/types/ComputedData.ts +83 -83
  44. package/src/types/ComputedDataGrid.ts +13 -13
  45. package/src/types/ComputedDataMultiGrid.ts +2 -2
  46. package/src/types/ComputedDataMultiValue.ts +9 -9
  47. package/src/types/ComputedDataRelationship.ts +19 -19
  48. package/src/types/ComputedDataSeries.ts +7 -7
  49. package/src/types/ComputedDataTree.ts +19 -19
  50. package/src/types/ContextObserver.ts +38 -38
  51. package/src/types/ContextObserverGrid.ts +42 -42
  52. package/src/types/ContextObserverMultiGrid.ts +16 -15
  53. package/src/types/ContextObserverMultiValue.ts +4 -4
  54. package/src/types/ContextObserverRelationship.ts +4 -4
  55. package/src/types/ContextObserverSeries.ts +29 -29
  56. package/src/types/ContextObserverTree.ts +11 -11
  57. package/src/types/ContextSubject.ts +18 -18
  58. package/src/types/Data.ts +45 -45
  59. package/src/types/DataFormatter.ts +74 -74
  60. package/src/types/DataFormatterGrid.ts +67 -67
  61. package/src/types/DataFormatterMultiGrid.ts +44 -44
  62. package/src/types/DataFormatterMultiValue.ts +23 -23
  63. package/src/types/DataFormatterRelationship.ts +25 -25
  64. package/src/types/DataFormatterSeries.ts +20 -20
  65. package/src/types/DataFormatterTree.ts +12 -12
  66. package/src/types/DataGrid.ts +11 -11
  67. package/src/types/DataMultiGrid.ts +6 -6
  68. package/src/types/DataMultiValue.ts +12 -12
  69. package/src/types/DataRelationship.ts +27 -27
  70. package/src/types/DataSeries.ts +11 -11
  71. package/src/types/DataTree.ts +20 -20
  72. package/src/types/Event.ts +153 -153
  73. package/src/types/Layout.ts +11 -11
  74. package/src/types/Padding.ts +5 -5
  75. package/src/types/Plugin.ts +60 -60
  76. package/src/types/TransformData.ts +7 -7
  77. package/src/types/index.ts +37 -37
  78. package/src/utils/commonUtils.ts +50 -50
  79. package/src/utils/d3Utils.ts +89 -89
  80. package/src/utils/index.ts +4 -4
  81. package/src/utils/observables.ts +201 -201
  82. package/src/utils/orbchartsUtils.ts +349 -349
  83. package/tsconfig.json +13 -13
  84. package/vite.config.js +22 -44
@@ -1,349 +1,349 @@
1
- import * as d3 from 'd3'
2
- import type { ChartType } from '../types/Chart'
3
- import type { ChartParams } from '../types/ChartParams'
4
- import type { DatumBase, DatumValue } from '../types/Data'
5
- import type { DataSeries, DataSeriesDatum, DataSeriesValue } from '../types/DataSeries'
6
- import type { DataGrid, DataGridDatum, DataGridValue } from '../types/DataGrid'
7
- import type { DataMultiGrid } from '../types/DataMultiGrid'
8
- import type { DataMultiValue, DataMultiValueDatum, DataMultiValueValue } from '../types/DataMultiValue'
9
- import type { DataFormatterContainer } from '../types/DataFormatter'
10
- import type { SeriesDirection, DataFormatterGrid, DataFormatterGridGrid } from '../types/DataFormatterGrid'
11
- import type { DataFormatterMultiGrid } from '../types/DataFormatterMultiGrid'
12
- import type { ComputedDatumSeriesValue } from '../types/ComputedData'
13
- import type { ComputedDatumSeries } from '../types/ComputedDataSeries'
14
- import type { ComputedDatumGrid, ComputedDataGrid } from '../types/ComputedDataGrid'
15
- import type { ComputedDataMultiGrid } from '../types/ComputedDataMultiGrid'
16
- import type { SeriesContainerPosition } from '../types/ContextObserverSeries'
17
- import type { GridContainerPosition } from '../types/ContextObserverGrid'
18
- import type { Layout } from '../types/Layout'
19
- // import type { ComputedDatumMultiGrid } from '../types/ComputedDataMultiGrid'
20
- import { isPlainObject } from './commonUtils'
21
-
22
- export function formatValueToLabel (value: any, valueFormatter: string | ((text: d3.NumberValue) => string)) {
23
- if (valueFormatter! instanceof Function == true) {
24
- return (valueFormatter as ((text: d3.NumberValue) => string))(value)
25
- }
26
- return d3.format(valueFormatter as string)!(value)
27
- }
28
-
29
- export function createDefaultDatumId (chartTypeOrPrefix: string, levelOneIndex: number, levelTwoIndex: number, levelThreeIndex?: number) {
30
- let text = `${chartTypeOrPrefix}_${levelOneIndex}_${levelTwoIndex}`
31
- if (levelThreeIndex != null) {
32
- text += `_${levelThreeIndex}`
33
- }
34
- return text
35
- }
36
-
37
- export function createDefaultSeriesLabel (chartTypeOrPrefix: string, seriesIndex: number) {
38
- return `${chartTypeOrPrefix}_series${seriesIndex}`
39
- }
40
-
41
- export function createDefaultGroupLabel (chartTypeOrPrefix: string, groupIndex: number) {
42
- return `${chartTypeOrPrefix}_group${groupIndex}`
43
- }
44
-
45
- export function createGridSeriesLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'grid' }: {
46
- transposedDataGrid: DataGridDatum[][],
47
- dataFormatterGrid: DataFormatterGridGrid
48
- chartType?: ChartType
49
- }) {
50
- const labels = dataFormatterGrid.seriesDirection === 'row'
51
- ? dataFormatterGrid.rowLabels
52
- : dataFormatterGrid.columnLabels
53
- return transposedDataGrid.map((_, rowIndex) => {
54
- return labels[rowIndex] != null
55
- ? labels[rowIndex]
56
- : createDefaultSeriesLabel(chartType, rowIndex)
57
- })
58
- }
59
-
60
- export function createMultiGridSeriesLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'multiGrid', gridIndex = 0 }: {
61
- transposedDataGrid: DataGridDatum[][],
62
- dataFormatterGrid: DataFormatterGridGrid
63
- chartType?: ChartType
64
- gridIndex?: number
65
- }) {
66
- const labels = dataFormatterGrid.seriesDirection === 'row'
67
- ? dataFormatterGrid.rowLabels
68
- : dataFormatterGrid.columnLabels
69
- return transposedDataGrid.map((_, rowIndex) => {
70
- return labels[rowIndex] != null
71
- ? labels[rowIndex]
72
- : createDefaultSeriesLabel(`${chartType}_grid${gridIndex}`, rowIndex)
73
- })
74
- }
75
-
76
- export function createGridGroupLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'grid' }: {
77
- transposedDataGrid: DataGridDatum[][],
78
- dataFormatterGrid: DataFormatterGridGrid
79
- chartType?: ChartType
80
- }) {
81
- if (transposedDataGrid[0] == null) {
82
- return []
83
- }
84
- const labels = dataFormatterGrid.seriesDirection === 'row'
85
- ? dataFormatterGrid.columnLabels
86
- : dataFormatterGrid.rowLabels
87
- return transposedDataGrid[0].map((_, columnLabels) => {
88
- return labels[columnLabels] != null
89
- ? labels[columnLabels]
90
- : createDefaultGroupLabel(chartType, columnLabels)
91
- })
92
- }
93
-
94
- export function createMultiGridGroupLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'multiGrid', gridIndex = 0 }: {
95
- transposedDataGrid: DataGridDatum[][],
96
- dataFormatterGrid: DataFormatterGridGrid
97
- chartType?: ChartType
98
- gridIndex?: number
99
- }) {
100
- if (transposedDataGrid[0] == null) {
101
- return []
102
- }
103
- const labels = dataFormatterGrid.seriesDirection === 'row'
104
- ? dataFormatterGrid.columnLabels
105
- : dataFormatterGrid.rowLabels
106
- return transposedDataGrid[0].map((_, columnLabels) => {
107
- return labels[columnLabels] != null
108
- ? labels[columnLabels]
109
- : createDefaultGroupLabel(`${chartType}_grid${gridIndex}`, columnLabels)
110
- })
111
- }
112
-
113
- // 取得最小及最大值 - 數字陣列
114
- export function getMinAndMax (data: number[]): [number, number] {
115
- const defaultMinAndMax: [number, number] = [0, 0] // default
116
- if (!data.length) {
117
- return defaultMinAndMax
118
- }
119
- const minAndMax: [number, number] = data.reduce((prev, current) => {
120
- // [min, max]
121
- return [
122
- current < prev[0] ? current : prev[0],
123
- current > prev[1] ? current : prev[1]
124
- ]
125
- }, [data[0], data[0]])
126
- return minAndMax
127
- }
128
-
129
- // 取得最小及最大值 - datum格式陣列資料
130
- export function getMinAndMaxValue (data: DatumValue[]): [number, number] {
131
- const arr = data
132
- .filter(d => d != null && d.value != null)
133
- .map(d => d.value )
134
- return getMinAndMax(arr)
135
- }
136
-
137
- // 取得最小及最大值 - Series Data
138
- export function getMinAndMaxSeries (data: DataSeries): [number, number] {
139
- const flatData: (DataSeriesValue | DataSeriesDatum)[] = data[0] && Array.isArray((data as (DataSeriesValue | DataSeriesDatum)[][])[0])
140
- ? data.flat()
141
- : data as (DataSeriesValue | DataSeriesDatum)[]
142
- const arr = flatData
143
- .filter(d => (d == null || (isPlainObject(d) && (d as DataSeriesDatum).value == null)) === false) // 過濾掉null &
144
- .map(d => typeof d === 'number' ? d : d.value )
145
- return getMinAndMax(arr)
146
- }
147
-
148
- // 取得最小及最大值 - Grid Data
149
- export function getMinAndMaxGrid (data: DataGrid): [number, number] {
150
- const flatData: (DataGridValue | DataGridDatum)[] = data.flat()
151
- const arr = flatData
152
- .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
153
- .map(d => typeof d === 'number' ? d : d.value )
154
- return getMinAndMax(arr)
155
- }
156
-
157
- // 取得最小及最大值 - MultiGrid Data
158
- export function getMinAndMaxMultiGrid (data: DataMultiGrid): [number, number] {
159
- const flatData: (DataGridValue | DataGridDatum)[] = data.flat().flat()
160
- const arr = flatData
161
- .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
162
- .map(d => typeof d === 'number' ? d : d.value )
163
- return getMinAndMax(arr)
164
- }
165
-
166
- // 取得最小及最大值 - MultiValue Data
167
- export function getMinAndMaxMultiValue (data: DataMultiValue, valueIndex: number = 2): [number, number] {
168
- const flatData: (DataMultiValueDatum | DataMultiValueValue)[] = data.flat().filter((d, i) => i == valueIndex)
169
- const arr = flatData
170
- .filter(d => (d == null || (isPlainObject(d) && (d as DataMultiValueDatum).value == null)) === false) // 過濾掉null
171
- .map(d => typeof d === 'number' ? d : d.value )
172
- return getMinAndMax(arr)
173
- }
174
-
175
- // @Q@ 待處理
176
- // // 取得最小及最大值 - Relationship Data
177
- // export function getMinAndMaxRelationship (data: DataRelationship, target: 'nodes' | 'edges' = 'nodes'): [number, number] {
178
-
179
- // }
180
-
181
- // @Q@ 待處理
182
- // // 取得最小及最大值 - Tree Data
183
- // export function getMinAndMaxTree (data: DataTree): [number, number] {
184
-
185
- // }
186
-
187
- // 轉置成seriesDirection為main的陣列格式
188
- export function transposeData<T> (seriesDirection: SeriesDirection, data: T[][]): T[][] {
189
- if (seriesDirection === 'row') {
190
- return Object.assign([], data)
191
- }
192
- // 取得原始陣列的維度
193
- const rows = data.length;
194
- const cols = data.reduce((prev, current) => {
195
- return Math.max(prev, current.length)
196
- }, 0)
197
-
198
- // 初始化轉換後的陣列
199
- const transposedArray = new Array(cols).fill(null).map(() => new Array(rows).fill(null))
200
-
201
- // 遍歷原始陣列,進行轉換
202
- for (let i = 0; i < rows; i++) {
203
- for (let j = 0; j < cols; j++) {
204
- transposedArray[j][i] = data[i][j]
205
- }
206
- }
207
-
208
- return transposedArray
209
- }
210
-
211
-
212
- export function seriesColorPredicate (seriesIndex: number, chartParams: ChartParams) {
213
- return seriesIndex < chartParams.colors[chartParams.colorScheme].series.length
214
- ? chartParams.colors[chartParams.colorScheme].series[seriesIndex]
215
- : chartParams.colors[chartParams.colorScheme].series[
216
- seriesIndex % chartParams.colors[chartParams.colorScheme].series.length
217
- ]
218
- }
219
-
220
- // export function calcSeriesContainerPosition (layout: Layout, container: DataFormatterContainer, rowIndex: number, columnIndex: number) {
221
- // const { gap, rowAmount, columnAmount } = container
222
- // const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
223
- // const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
224
- // const x = columnIndex * width + (columnIndex * gap)
225
- // const y = rowIndex * height + (rowIndex * gap)
226
- // // const translate: [number, number] = [x, y]
227
-
228
- // return {
229
- // // translate,
230
- // startX: x,
231
- // startY: y,
232
- // centerX: x + width / 2,
233
- // centerY: y + height / 2,
234
- // width,
235
- // height
236
- // }
237
- // }
238
-
239
- // 計算預設欄列數量
240
- // 規則1.rowAmount*columnAmount要大於或等於amount,並且數字要盡可能小
241
- // 規則2.columnAmount要大於或等於rowAmount,並且數字要盡可能小
242
- function calcGridDimensions (amount: number): { rowAmount: number; columnAmount: number } {
243
- let rowAmount = Math.floor(Math.sqrt(amount))
244
- let columnAmount = Math.ceil(amount / rowAmount)
245
- while (rowAmount * columnAmount < amount) {
246
- columnAmount++
247
- }
248
- return { rowAmount, columnAmount }
249
- }
250
-
251
- export function calcSeriesContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): SeriesContainerPosition[] {
252
- const { gap } = container
253
- const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
254
- // 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
255
- ? container
256
- // 否則計算一個合適的預設值
257
- : calcGridDimensions(amount)
258
-
259
- return new Array(amount).fill(null).map((_, index) => {
260
- const columnIndex = index % columnAmount
261
- const rowIndex = Math.floor(index / columnAmount)
262
-
263
- const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
264
- const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
265
- const x = columnIndex * width + (columnIndex * gap)
266
- const y = rowIndex * height + (rowIndex * gap)
267
- // const translate: [number, number] = [x, y]
268
-
269
- return {
270
- slotIndex: index,
271
- rowIndex,
272
- columnIndex,
273
- // translate,
274
- startX: x,
275
- startY: y,
276
- centerX: x + width / 2,
277
- centerY: y + height / 2,
278
- width,
279
- height
280
- }
281
- })
282
- }
283
-
284
- // export function calcGridContainerPosition (layout: Layout, container: DataFormatterContainer, rowIndex: number, columnIndex: number) {
285
- // const { gap, rowAmount, columnAmount } = container
286
- // const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
287
- // const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
288
- // const x = columnIndex * width + (columnIndex * gap)
289
- // const y = rowIndex * height + (rowIndex * gap)
290
- // const translate: [number, number] = [x, y]
291
- // const scale: [number, number] = [width / layout.width, height / layout.height]
292
-
293
- // return {
294
- // translate,
295
- // scale
296
- // }
297
- // }
298
-
299
- export function calcGridContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): GridContainerPosition[] {
300
- const { gap } = container
301
- const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
302
- // 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
303
- ? container
304
- // 否則計算一個合適的預設值
305
- : calcGridDimensions(amount)
306
-
307
- return new Array(amount).fill(null).map((_, index) => {
308
- const columnIndex = index % columnAmount
309
- const rowIndex = Math.floor(index / columnAmount)
310
-
311
- const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
312
- const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
313
- const x = columnIndex * width + (columnIndex * gap)
314
- const y = rowIndex * height + (rowIndex * gap)
315
- const translate: [number, number] = [x, y]
316
- const scale: [number, number] = [width / layout.width, height / layout.height]
317
-
318
- return {
319
- slotIndex: index,
320
- rowIndex,
321
- columnIndex,
322
- translate,
323
- scale
324
- }
325
- })
326
- }
327
-
328
- // // multiGrid datum color
329
- // export function multiGridColorPredicate ({ seriesIndex, groupIndex, data, chartParams }: {
330
- // seriesIndex: number
331
- // groupIndex: number
332
- // data: ComputedDataMultiGrid
333
- // chartParams: ChartParams
334
- // }) {
335
- // // 累加前面的grid的seriesIndex
336
- // const accSeriesIndex = data.reduce((prev, current) => {
337
- // if (current[0] && current[0][0] && groupIndex > current[0][0].gridIndex) {
338
- // return prev + current[0].length
339
- // } else if (current[0] && current[0][0] && groupIndex == current[0][0].gridIndex) {
340
- // return prev + seriesIndex
341
- // } else {
342
- // return prev
343
- // }
344
- // }, 0)
345
-
346
- // return seriesColorPredicate(accSeriesIndex, chartParams)
347
- // }
348
-
349
-
1
+ import * as d3 from 'd3'
2
+ import type { ChartType } from '../types/Chart'
3
+ import type { ChartParams } from '../types/ChartParams'
4
+ import type { DatumBase, DatumValue } from '../types/Data'
5
+ import type { DataSeries, DataSeriesDatum, DataSeriesValue } from '../types/DataSeries'
6
+ import type { DataGrid, DataGridDatum, DataGridValue } from '../types/DataGrid'
7
+ import type { DataMultiGrid } from '../types/DataMultiGrid'
8
+ import type { DataMultiValue, DataMultiValueDatum, DataMultiValueValue } from '../types/DataMultiValue'
9
+ import type { DataFormatterContainer } from '../types/DataFormatter'
10
+ import type { SeriesDirection, DataFormatterGrid, DataFormatterGridGrid } from '../types/DataFormatterGrid'
11
+ import type { DataFormatterMultiGrid } from '../types/DataFormatterMultiGrid'
12
+ import type { ComputedDatumSeriesValue } from '../types/ComputedData'
13
+ import type { ComputedDatumSeries } from '../types/ComputedDataSeries'
14
+ import type { ComputedDatumGrid, ComputedDataGrid } from '../types/ComputedDataGrid'
15
+ import type { ComputedDataMultiGrid } from '../types/ComputedDataMultiGrid'
16
+ import type { SeriesContainerPosition } from '../types/ContextObserverSeries'
17
+ import type { GridContainerPosition } from '../types/ContextObserverGrid'
18
+ import type { Layout } from '../types/Layout'
19
+ // import type { ComputedDatumMultiGrid } from '../types/ComputedDataMultiGrid'
20
+ import { isPlainObject } from './commonUtils'
21
+
22
+ export function formatValueToLabel (value: any, valueFormatter: string | ((text: d3.NumberValue) => string)) {
23
+ if (valueFormatter! instanceof Function == true) {
24
+ return (valueFormatter as ((text: d3.NumberValue) => string))(value)
25
+ }
26
+ return d3.format(valueFormatter as string)!(value)
27
+ }
28
+
29
+ export function createDefaultDatumId (chartTypeOrPrefix: string, levelOneIndex: number, levelTwoIndex: number, levelThreeIndex?: number) {
30
+ let text = `${chartTypeOrPrefix}_${levelOneIndex}_${levelTwoIndex}`
31
+ if (levelThreeIndex != null) {
32
+ text += `_${levelThreeIndex}`
33
+ }
34
+ return text
35
+ }
36
+
37
+ export function createDefaultSeriesLabel (chartTypeOrPrefix: string, seriesIndex: number) {
38
+ return `${chartTypeOrPrefix}_series${seriesIndex}`
39
+ }
40
+
41
+ export function createDefaultGroupLabel (chartTypeOrPrefix: string, groupIndex: number) {
42
+ return `${chartTypeOrPrefix}_group${groupIndex}`
43
+ }
44
+
45
+ export function createGridSeriesLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'grid' }: {
46
+ transposedDataGrid: DataGridDatum[][],
47
+ dataFormatterGrid: DataFormatterGridGrid
48
+ chartType?: ChartType
49
+ }) {
50
+ const labels = dataFormatterGrid.seriesDirection === 'row'
51
+ ? dataFormatterGrid.rowLabels
52
+ : dataFormatterGrid.columnLabels
53
+ return transposedDataGrid.map((_, rowIndex) => {
54
+ return labels[rowIndex] != null
55
+ ? labels[rowIndex]
56
+ : createDefaultSeriesLabel(chartType, rowIndex)
57
+ })
58
+ }
59
+
60
+ export function createMultiGridSeriesLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'multiGrid', gridIndex = 0 }: {
61
+ transposedDataGrid: DataGridDatum[][],
62
+ dataFormatterGrid: DataFormatterGridGrid
63
+ chartType?: ChartType
64
+ gridIndex?: number
65
+ }) {
66
+ const labels = dataFormatterGrid.seriesDirection === 'row'
67
+ ? dataFormatterGrid.rowLabels
68
+ : dataFormatterGrid.columnLabels
69
+ return transposedDataGrid.map((_, rowIndex) => {
70
+ return labels[rowIndex] != null
71
+ ? labels[rowIndex]
72
+ : createDefaultSeriesLabel(`${chartType}_grid${gridIndex}`, rowIndex)
73
+ })
74
+ }
75
+
76
+ export function createGridGroupLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'grid' }: {
77
+ transposedDataGrid: DataGridDatum[][],
78
+ dataFormatterGrid: DataFormatterGridGrid
79
+ chartType?: ChartType
80
+ }) {
81
+ if (transposedDataGrid[0] == null) {
82
+ return []
83
+ }
84
+ const labels = dataFormatterGrid.seriesDirection === 'row'
85
+ ? dataFormatterGrid.columnLabels
86
+ : dataFormatterGrid.rowLabels
87
+ return transposedDataGrid[0].map((_, columnLabels) => {
88
+ return labels[columnLabels] != null
89
+ ? labels[columnLabels]
90
+ : createDefaultGroupLabel(chartType, columnLabels)
91
+ })
92
+ }
93
+
94
+ export function createMultiGridGroupLabels ({ transposedDataGrid, dataFormatterGrid, chartType = 'multiGrid', gridIndex = 0 }: {
95
+ transposedDataGrid: DataGridDatum[][],
96
+ dataFormatterGrid: DataFormatterGridGrid
97
+ chartType?: ChartType
98
+ gridIndex?: number
99
+ }) {
100
+ if (transposedDataGrid[0] == null) {
101
+ return []
102
+ }
103
+ const labels = dataFormatterGrid.seriesDirection === 'row'
104
+ ? dataFormatterGrid.columnLabels
105
+ : dataFormatterGrid.rowLabels
106
+ return transposedDataGrid[0].map((_, columnLabels) => {
107
+ return labels[columnLabels] != null
108
+ ? labels[columnLabels]
109
+ : createDefaultGroupLabel(`${chartType}_grid${gridIndex}`, columnLabels)
110
+ })
111
+ }
112
+
113
+ // 取得最小及最大值 - 數字陣列
114
+ export function getMinAndMax (data: number[]): [number, number] {
115
+ const defaultMinAndMax: [number, number] = [0, 0] // default
116
+ if (!data.length) {
117
+ return defaultMinAndMax
118
+ }
119
+ const minAndMax: [number, number] = data.reduce((prev, current) => {
120
+ // [min, max]
121
+ return [
122
+ current < prev[0] ? current : prev[0],
123
+ current > prev[1] ? current : prev[1]
124
+ ]
125
+ }, [data[0], data[0]])
126
+ return minAndMax
127
+ }
128
+
129
+ // 取得最小及最大值 - datum格式陣列資料
130
+ export function getMinAndMaxValue (data: DatumValue[]): [number, number] {
131
+ const arr = data
132
+ .filter(d => d != null && d.value != null)
133
+ .map(d => d.value )
134
+ return getMinAndMax(arr)
135
+ }
136
+
137
+ // 取得最小及最大值 - Series Data
138
+ export function getMinAndMaxSeries (data: DataSeries): [number, number] {
139
+ const flatData: (DataSeriesValue | DataSeriesDatum)[] = data[0] && Array.isArray((data as (DataSeriesValue | DataSeriesDatum)[][])[0])
140
+ ? data.flat()
141
+ : data as (DataSeriesValue | DataSeriesDatum)[]
142
+ const arr = flatData
143
+ .filter(d => (d == null || (isPlainObject(d) && (d as DataSeriesDatum).value == null)) === false) // 過濾掉null &
144
+ .map(d => typeof d === 'number' ? d : d.value )
145
+ return getMinAndMax(arr)
146
+ }
147
+
148
+ // 取得最小及最大值 - Grid Data
149
+ export function getMinAndMaxGrid (data: DataGrid): [number, number] {
150
+ const flatData: (DataGridValue | DataGridDatum)[] = data.flat()
151
+ const arr = flatData
152
+ .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
153
+ .map(d => typeof d === 'number' ? d : d.value )
154
+ return getMinAndMax(arr)
155
+ }
156
+
157
+ // 取得最小及最大值 - MultiGrid Data
158
+ export function getMinAndMaxMultiGrid (data: DataMultiGrid): [number, number] {
159
+ const flatData: (DataGridValue | DataGridDatum)[] = data.flat().flat()
160
+ const arr = flatData
161
+ .filter(d => (d == null || (isPlainObject(d) && (d as DataGridDatum).value == null)) === false) // 過濾掉null
162
+ .map(d => typeof d === 'number' ? d : d.value )
163
+ return getMinAndMax(arr)
164
+ }
165
+
166
+ // 取得最小及最大值 - MultiValue Data
167
+ export function getMinAndMaxMultiValue (data: DataMultiValue, valueIndex: number = 2): [number, number] {
168
+ const flatData: (DataMultiValueDatum | DataMultiValueValue)[] = data.flat().filter((d, i) => i == valueIndex)
169
+ const arr = flatData
170
+ .filter(d => (d == null || (isPlainObject(d) && (d as DataMultiValueDatum).value == null)) === false) // 過濾掉null
171
+ .map(d => typeof d === 'number' ? d : d.value )
172
+ return getMinAndMax(arr)
173
+ }
174
+
175
+ // @Q@ 待處理
176
+ // // 取得最小及最大值 - Relationship Data
177
+ // export function getMinAndMaxRelationship (data: DataRelationship, target: 'nodes' | 'edges' = 'nodes'): [number, number] {
178
+
179
+ // }
180
+
181
+ // @Q@ 待處理
182
+ // // 取得最小及最大值 - Tree Data
183
+ // export function getMinAndMaxTree (data: DataTree): [number, number] {
184
+
185
+ // }
186
+
187
+ // 轉置成seriesDirection為main的陣列格式
188
+ export function transposeData<T> (seriesDirection: SeriesDirection, data: T[][]): T[][] {
189
+ if (seriesDirection === 'row') {
190
+ return Object.assign([], data)
191
+ }
192
+ // 取得原始陣列的維度
193
+ const rows = data.length;
194
+ const cols = data.reduce((prev, current) => {
195
+ return Math.max(prev, current.length)
196
+ }, 0)
197
+
198
+ // 初始化轉換後的陣列
199
+ const transposedArray = new Array(cols).fill(null).map(() => new Array(rows).fill(null))
200
+
201
+ // 遍歷原始陣列,進行轉換
202
+ for (let i = 0; i < rows; i++) {
203
+ for (let j = 0; j < cols; j++) {
204
+ transposedArray[j][i] = data[i][j]
205
+ }
206
+ }
207
+
208
+ return transposedArray
209
+ }
210
+
211
+
212
+ export function seriesColorPredicate (seriesIndex: number, chartParams: ChartParams) {
213
+ return seriesIndex < chartParams.colors[chartParams.colorScheme].series.length
214
+ ? chartParams.colors[chartParams.colorScheme].series[seriesIndex]
215
+ : chartParams.colors[chartParams.colorScheme].series[
216
+ seriesIndex % chartParams.colors[chartParams.colorScheme].series.length
217
+ ]
218
+ }
219
+
220
+ // export function calcSeriesContainerPosition (layout: Layout, container: DataFormatterContainer, rowIndex: number, columnIndex: number) {
221
+ // const { gap, rowAmount, columnAmount } = container
222
+ // const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
223
+ // const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
224
+ // const x = columnIndex * width + (columnIndex * gap)
225
+ // const y = rowIndex * height + (rowIndex * gap)
226
+ // // const translate: [number, number] = [x, y]
227
+
228
+ // return {
229
+ // // translate,
230
+ // startX: x,
231
+ // startY: y,
232
+ // centerX: x + width / 2,
233
+ // centerY: y + height / 2,
234
+ // width,
235
+ // height
236
+ // }
237
+ // }
238
+
239
+ // 計算預設欄列數量
240
+ // 規則1.rowAmount*columnAmount要大於或等於amount,並且數字要盡可能小
241
+ // 規則2.columnAmount要大於或等於rowAmount,並且數字要盡可能小
242
+ function calcGridDimensions (amount: number): { rowAmount: number; columnAmount: number } {
243
+ let rowAmount = Math.floor(Math.sqrt(amount))
244
+ let columnAmount = Math.ceil(amount / rowAmount)
245
+ while (rowAmount * columnAmount < amount) {
246
+ columnAmount++
247
+ }
248
+ return { rowAmount, columnAmount }
249
+ }
250
+
251
+ export function calcSeriesContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): SeriesContainerPosition[] {
252
+ const { gap } = container
253
+ const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
254
+ // 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
255
+ ? container
256
+ // 否則計算一個合適的預設值
257
+ : calcGridDimensions(amount)
258
+
259
+ return new Array(amount).fill(null).map((_, index) => {
260
+ const columnIndex = index % columnAmount
261
+ const rowIndex = Math.floor(index / columnAmount)
262
+
263
+ const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
264
+ const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
265
+ const x = columnIndex * width + (columnIndex * gap)
266
+ const y = rowIndex * height + (rowIndex * gap)
267
+ // const translate: [number, number] = [x, y]
268
+
269
+ return {
270
+ slotIndex: index,
271
+ rowIndex,
272
+ columnIndex,
273
+ // translate,
274
+ startX: x,
275
+ startY: y,
276
+ centerX: x + width / 2,
277
+ centerY: y + height / 2,
278
+ width,
279
+ height
280
+ }
281
+ })
282
+ }
283
+
284
+ // export function calcGridContainerPosition (layout: Layout, container: DataFormatterContainer, rowIndex: number, columnIndex: number) {
285
+ // const { gap, rowAmount, columnAmount } = container
286
+ // const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
287
+ // const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
288
+ // const x = columnIndex * width + (columnIndex * gap)
289
+ // const y = rowIndex * height + (rowIndex * gap)
290
+ // const translate: [number, number] = [x, y]
291
+ // const scale: [number, number] = [width / layout.width, height / layout.height]
292
+
293
+ // return {
294
+ // translate,
295
+ // scale
296
+ // }
297
+ // }
298
+
299
+ export function calcGridContainerLayout (layout: Layout, container: DataFormatterContainer, amount: number): GridContainerPosition[] {
300
+ const { gap } = container
301
+ const { rowAmount, columnAmount } = (container.rowAmount * container.columnAmount) >= amount
302
+ // 如果container設定的rowAmount和columnAmount的乘積大於或等於amount,則使用目前設定
303
+ ? container
304
+ // 否則計算一個合適的預設值
305
+ : calcGridDimensions(amount)
306
+
307
+ return new Array(amount).fill(null).map((_, index) => {
308
+ const columnIndex = index % columnAmount
309
+ const rowIndex = Math.floor(index / columnAmount)
310
+
311
+ const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
312
+ const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
313
+ const x = columnIndex * width + (columnIndex * gap)
314
+ const y = rowIndex * height + (rowIndex * gap)
315
+ const translate: [number, number] = [x, y]
316
+ const scale: [number, number] = [width / layout.width, height / layout.height]
317
+
318
+ return {
319
+ slotIndex: index,
320
+ rowIndex,
321
+ columnIndex,
322
+ translate,
323
+ scale
324
+ }
325
+ })
326
+ }
327
+
328
+ // // multiGrid datum color
329
+ // export function multiGridColorPredicate ({ seriesIndex, groupIndex, data, chartParams }: {
330
+ // seriesIndex: number
331
+ // groupIndex: number
332
+ // data: ComputedDataMultiGrid
333
+ // chartParams: ChartParams
334
+ // }) {
335
+ // // 累加前面的grid的seriesIndex
336
+ // const accSeriesIndex = data.reduce((prev, current) => {
337
+ // if (current[0] && current[0][0] && groupIndex > current[0][0].gridIndex) {
338
+ // return prev + current[0].length
339
+ // } else if (current[0] && current[0][0] && groupIndex == current[0][0].gridIndex) {
340
+ // return prev + seriesIndex
341
+ // } else {
342
+ // return prev
343
+ // }
344
+ // }, 0)
345
+
346
+ // return seriesColorPredicate(accSeriesIndex, chartParams)
347
+ // }
348
+
349
+