@orbcharts/core 3.0.0-alpha.48 → 3.0.0-alpha.49

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 (83) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-core.es.js +3 -2
  3. package/dist/orbcharts-core.umd.js +1 -1
  4. package/dist/src/types/Chart.d.ts +10 -12
  5. package/package.json +41 -41
  6. package/src/AbstractChart.ts +48 -48
  7. package/src/GridChart.ts +20 -20
  8. package/src/MultiGridChart.ts +20 -20
  9. package/src/MultiValueChart.ts +20 -20
  10. package/src/RelationshipChart.ts +20 -20
  11. package/src/SeriesChart.ts +20 -20
  12. package/src/TreeChart.ts +20 -20
  13. package/src/base/createBaseChart.ts +369 -368
  14. package/src/base/createBasePlugin.ts +95 -95
  15. package/src/defaults.ts +220 -220
  16. package/src/defineGridPlugin.ts +3 -3
  17. package/src/defineMultiGridPlugin.ts +3 -3
  18. package/src/defineMultiValuePlugin.ts +3 -3
  19. package/src/defineNoneDataPlugin.ts +4 -4
  20. package/src/defineRelationshipPlugin.ts +3 -3
  21. package/src/defineSeriesPlugin.ts +3 -3
  22. package/src/defineTreePlugin.ts +3 -3
  23. package/src/grid/computeGridData.ts +134 -134
  24. package/src/grid/createGridContextObserver.ts +155 -155
  25. package/src/grid/gridObservables.ts +600 -600
  26. package/src/index.ts +21 -21
  27. package/src/multiGrid/computeMultiGridData.ts +130 -130
  28. package/src/multiGrid/createMultiGridContextObserver.ts +40 -40
  29. package/src/multiGrid/multiGridObservables.ts +364 -364
  30. package/src/multiValue/computeMultiValueData.ts +143 -143
  31. package/src/multiValue/createMultiValueContextObserver.ts +12 -12
  32. package/src/relationship/computeRelationshipData.ts +118 -118
  33. package/src/relationship/createRelationshipContextObserver.ts +12 -12
  34. package/src/series/computeSeriesData.ts +90 -90
  35. package/src/series/createSeriesContextObserver.ts +93 -93
  36. package/src/series/seriesObservables.ts +175 -175
  37. package/src/tree/computeTreeData.ts +131 -131
  38. package/src/tree/createTreeContextObserver.ts +61 -61
  39. package/src/tree/treeObservables.ts +94 -94
  40. package/src/types/Chart.ts +50 -48
  41. package/src/types/ChartParams.ts +51 -51
  42. package/src/types/ComputedData.ts +83 -83
  43. package/src/types/ComputedDataGrid.ts +13 -13
  44. package/src/types/ComputedDataMultiGrid.ts +2 -2
  45. package/src/types/ComputedDataMultiValue.ts +9 -9
  46. package/src/types/ComputedDataRelationship.ts +19 -19
  47. package/src/types/ComputedDataSeries.ts +7 -7
  48. package/src/types/ComputedDataTree.ts +19 -19
  49. package/src/types/ContextObserver.ts +38 -38
  50. package/src/types/ContextObserverGrid.ts +42 -42
  51. package/src/types/ContextObserverMultiGrid.ts +15 -15
  52. package/src/types/ContextObserverMultiValue.ts +4 -4
  53. package/src/types/ContextObserverRelationship.ts +4 -4
  54. package/src/types/ContextObserverSeries.ts +29 -29
  55. package/src/types/ContextObserverTree.ts +11 -11
  56. package/src/types/ContextSubject.ts +18 -18
  57. package/src/types/Data.ts +45 -45
  58. package/src/types/DataFormatter.ts +74 -74
  59. package/src/types/DataFormatterGrid.ts +67 -67
  60. package/src/types/DataFormatterMultiGrid.ts +44 -44
  61. package/src/types/DataFormatterMultiValue.ts +23 -23
  62. package/src/types/DataFormatterRelationship.ts +25 -25
  63. package/src/types/DataFormatterSeries.ts +20 -20
  64. package/src/types/DataFormatterTree.ts +12 -12
  65. package/src/types/DataGrid.ts +11 -11
  66. package/src/types/DataMultiGrid.ts +6 -6
  67. package/src/types/DataMultiValue.ts +12 -12
  68. package/src/types/DataRelationship.ts +27 -27
  69. package/src/types/DataSeries.ts +11 -11
  70. package/src/types/DataTree.ts +20 -20
  71. package/src/types/Event.ts +153 -153
  72. package/src/types/Layout.ts +11 -11
  73. package/src/types/Padding.ts +5 -5
  74. package/src/types/Plugin.ts +60 -60
  75. package/src/types/TransformData.ts +7 -7
  76. package/src/types/index.ts +37 -37
  77. package/src/utils/commonUtils.ts +50 -50
  78. package/src/utils/d3Utils.ts +89 -89
  79. package/src/utils/index.ts +4 -4
  80. package/src/utils/observables.ts +201 -201
  81. package/src/utils/orbchartsUtils.ts +349 -349
  82. package/tsconfig.json +13 -13
  83. package/vite.config.js +44 -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
+