@orbcharts/core 3.0.0-alpha.43 → 3.0.0-alpha.45

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 (85) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-core.es.js +97 -97
  3. package/dist/orbcharts-core.umd.js +2 -2
  4. package/dist/src/series/seriesObservables.d.ts +3 -3
  5. package/dist/src/types/ContextObserverSeries.d.ts +1 -1
  6. package/dist/src/types/DataFormatterSeries.d.ts +3 -3
  7. package/package.json +41 -41
  8. package/src/AbstractChart.ts +48 -48
  9. package/src/GridChart.ts +20 -20
  10. package/src/MultiGridChart.ts +20 -20
  11. package/src/MultiValueChart.ts +20 -20
  12. package/src/RelationshipChart.ts +20 -20
  13. package/src/SeriesChart.ts +20 -20
  14. package/src/TreeChart.ts +20 -20
  15. package/src/base/createBaseChart.ts +368 -367
  16. package/src/base/createBasePlugin.ts +89 -89
  17. package/src/defaults.ts +220 -220
  18. package/src/defineGridPlugin.ts +3 -3
  19. package/src/defineMultiGridPlugin.ts +3 -3
  20. package/src/defineMultiValuePlugin.ts +3 -3
  21. package/src/defineNoneDataPlugin.ts +4 -4
  22. package/src/defineRelationshipPlugin.ts +3 -3
  23. package/src/defineSeriesPlugin.ts +3 -3
  24. package/src/defineTreePlugin.ts +3 -3
  25. package/src/grid/computeGridData.ts +134 -134
  26. package/src/grid/createGridContextObserver.ts +147 -147
  27. package/src/grid/gridObservables.ts +573 -573
  28. package/src/index.ts +21 -21
  29. package/src/multiGrid/computeMultiGridData.ts +130 -130
  30. package/src/multiGrid/createMultiGridContextObserver.ts +40 -40
  31. package/src/multiGrid/multiGridObservables.ts +350 -350
  32. package/src/multiValue/computeMultiValueData.ts +143 -143
  33. package/src/multiValue/createMultiValueContextObserver.ts +12 -12
  34. package/src/relationship/computeRelationshipData.ts +118 -118
  35. package/src/relationship/createRelationshipContextObserver.ts +12 -12
  36. package/src/series/computeSeriesData.ts +90 -90
  37. package/src/series/createSeriesContextObserver.ts +93 -93
  38. package/src/series/seriesObservables.ts +175 -175
  39. package/src/tree/computeTreeData.ts +131 -131
  40. package/src/tree/createTreeContextObserver.ts +61 -61
  41. package/src/tree/treeObservables.ts +94 -94
  42. package/src/types/Chart.ts +48 -48
  43. package/src/types/ChartParams.ts +51 -51
  44. package/src/types/ComputedData.ts +83 -83
  45. package/src/types/ComputedDataGrid.ts +13 -13
  46. package/src/types/ComputedDataMultiGrid.ts +2 -2
  47. package/src/types/ComputedDataMultiValue.ts +9 -9
  48. package/src/types/ComputedDataRelationship.ts +19 -19
  49. package/src/types/ComputedDataSeries.ts +7 -7
  50. package/src/types/ComputedDataTree.ts +19 -19
  51. package/src/types/ContextObserver.ts +38 -38
  52. package/src/types/ContextObserverGrid.ts +41 -41
  53. package/src/types/ContextObserverMultiGrid.ts +15 -15
  54. package/src/types/ContextObserverMultiValue.ts +4 -4
  55. package/src/types/ContextObserverRelationship.ts +4 -4
  56. package/src/types/ContextObserverSeries.ts +29 -29
  57. package/src/types/ContextObserverTree.ts +11 -11
  58. package/src/types/ContextSubject.ts +18 -18
  59. package/src/types/Data.ts +45 -45
  60. package/src/types/DataFormatter.ts +74 -74
  61. package/src/types/DataFormatterGrid.ts +67 -67
  62. package/src/types/DataFormatterMultiGrid.ts +44 -44
  63. package/src/types/DataFormatterMultiValue.ts +23 -23
  64. package/src/types/DataFormatterRelationship.ts +25 -25
  65. package/src/types/DataFormatterSeries.ts +20 -20
  66. package/src/types/DataFormatterTree.ts +12 -12
  67. package/src/types/DataGrid.ts +11 -11
  68. package/src/types/DataMultiGrid.ts +6 -6
  69. package/src/types/DataMultiValue.ts +12 -12
  70. package/src/types/DataRelationship.ts +27 -27
  71. package/src/types/DataSeries.ts +11 -11
  72. package/src/types/DataTree.ts +20 -20
  73. package/src/types/Event.ts +153 -153
  74. package/src/types/Layout.ts +11 -11
  75. package/src/types/Padding.ts +5 -5
  76. package/src/types/Plugin.ts +60 -60
  77. package/src/types/TransformData.ts +7 -7
  78. package/src/types/index.ts +37 -37
  79. package/src/utils/commonUtils.ts +50 -50
  80. package/src/utils/d3Utils.ts +89 -89
  81. package/src/utils/index.ts +4 -4
  82. package/src/utils/observables.ts +201 -201
  83. package/src/utils/orbchartsUtils.ts +349 -349
  84. package/tsconfig.json +13 -13
  85. package/vite.config.js +44 -44
@@ -1,574 +1,574 @@
1
- import {
2
- combineLatest,
3
- distinctUntilChanged,
4
- filter,
5
- map,
6
- merge,
7
- takeUntil,
8
- shareReplay,
9
- switchMap,
10
- Subject,
11
- Observable } from 'rxjs'
12
- import type {
13
- AxisPosition,
14
- ChartType,
15
- ChartParams,
16
- ComputedDataTypeMap,
17
- ComputedDatumTypeMap,
18
- ContextObserverFn,
19
- DataTypeMap,
20
- DataGridDatum,
21
- ComputedDatumGrid,
22
- DataFormatterTypeMap,
23
- DataFormatterGrid,
24
- DataFormatterValueAxis,
25
- DataFormatterGroupAxis,
26
- ComputedLayoutDatumGrid,
27
- ComputedLayoutDataGrid,
28
- GridContainerPosition,
29
- HighlightTarget,
30
- Layout,
31
- TransformData } from '../types'
32
- import { getMinAndMaxGrid } from '../utils/orbchartsUtils'
33
- import { createAxisLinearScale, createAxisPointScale, createAxisQuantizeScale } from '../utils/d3Utils'
34
- import { highlightObservable } from '../utils/observables'
35
- import { calcGridContainerLayout } from '../utils/orbchartsUtils'
36
- import { DATA_FORMATTER_GRID_GRID_DEFAULT } from '../defaults'
37
- import { getMinAndMaxValue, transposeData, createGridSeriesLabels, createGridGroupLabels, seriesColorPredicate } from '../utils/orbchartsUtils'
38
-
39
- export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
40
- computedData$: Observable<ComputedDataTypeMap<'grid'>>
41
- fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
42
- layout$: Observable<Layout>
43
- }): Observable<ComputedLayoutDatumGrid[][]> => {
44
-
45
- // 未篩選group範圍前的group scale
46
- function createOriginGroupScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
47
- const groupAxisWidth = (dataFormatter.grid.groupAxis.position === 'top' || dataFormatter.grid.groupAxis.position === 'bottom')
48
- ? layout.width
49
- : layout.height
50
- const groupEndIndex = computedData[0] ? computedData[0].length - 1 : 0
51
- const groupScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
52
- maxValue: groupEndIndex,
53
- minValue: 0,
54
- axisWidth: groupAxisWidth,
55
- scaleDomain: [0, groupEndIndex], // 不使用dataFormatter設定
56
- scaleRange: [0, 1] // 不使用dataFormatter設定
57
- })
58
- return groupScale
59
- }
60
-
61
- // 未篩選group範圍及visible前的value scale
62
- function createOriginValueScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
63
- const valueAxisWidth = (dataFormatter.grid.valueAxis.position === 'left' || dataFormatter.grid.valueAxis.position === 'right')
64
- ? layout.height
65
- : layout.width
66
-
67
- const listData = computedData.flat()
68
- const [minValue, maxValue] = getMinAndMaxValue(listData)
69
-
70
- const valueScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
71
- maxValue,
72
- minValue,
73
- axisWidth: valueAxisWidth,
74
- scaleDomain: [minValue, maxValue], // 不使用dataFormatter設定
75
- scaleRange: [0, 1] // 不使用dataFormatter設定
76
- })
77
-
78
- return valueScale
79
- }
80
-
81
- return combineLatest({
82
- computedData: computedData$,
83
- fullDataFormatter: fullDataFormatter$,
84
- layout: layout$
85
- }).pipe(
86
- switchMap(async d => d),
87
- map(data => {
88
- const groupScale = createOriginGroupScale(data.computedData, data.fullDataFormatter, data.layout)
89
- const valueScale = createOriginValueScale(data.computedData, data.fullDataFormatter, data.layout)
90
- const zeroY = valueScale(0)
91
-
92
- return data.computedData.map((seriesData, seriesIndex) => {
93
- return seriesData.map((groupDatum, groupIndex) => {
94
- const axisX = groupScale(groupIndex)
95
- const axisY = valueScale(groupDatum.value ?? 0)
96
- return {
97
- ...groupDatum,
98
- axisX,
99
- axisY,
100
- axisYFromZero: axisY - zeroY
101
- }
102
- })
103
- })
104
- })
105
- )
106
- }
107
-
108
- export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
109
- fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
110
- layout$: Observable<Layout>
111
- }): Observable<TransformData> => {
112
- const destroy$ = new Subject()
113
-
114
- function calcAxesTransform ({ xAxis, yAxis, width, height }: {
115
- xAxis: DataFormatterGroupAxis | DataFormatterValueAxis,
116
- yAxis: DataFormatterValueAxis,
117
- width: number,
118
- height: number
119
- }): TransformData {
120
- if (!xAxis || !yAxis) {
121
- return {
122
- translate: [0, 0],
123
- scale: [1, 1],
124
- rotate: 0,
125
- rotateX: 0,
126
- rotateY: 0,
127
- value: ''
128
- }
129
- }
130
- // const width = size.width - fullChartParams.layout.left - fullChartParams.layout.right
131
- // const height = size.height - fullChartParams.layout.top - fullChartParams.layout.bottom
132
- let translateX = 0
133
- let translateY = 0
134
- let rotate = 0
135
- let rotateX = 0
136
- let rotateY = 0
137
- if (xAxis.position === 'bottom') {
138
- if (yAxis.position === 'left') {
139
- rotateX = 180
140
- translateY = height
141
- } else if (yAxis.position === 'right') {
142
- rotateX = 180
143
- rotateY = 180
144
- translateX = width
145
- translateY = height
146
- } else {
147
- // 預設
148
- rotateX = 180
149
- translateY = height
150
- }
151
- } else if (xAxis.position === 'top') {
152
- if (yAxis.position === 'left') {
153
- } else if (yAxis.position === 'right') {
154
- rotateY = 180
155
- translateX = width
156
- } else {
157
- // 預設
158
- rotateX = 180
159
- translateY = height
160
- }
161
- } else if (xAxis.position === 'left') {
162
- if (yAxis.position === 'bottom') {
163
- rotate = -90
164
- translateY = height
165
- } else if (yAxis.position === 'top') {
166
- rotate = -90
167
- rotateY = 180
168
- } else {
169
- // 預設
170
- rotateX = 180
171
- translateY = height
172
- }
173
- } else if (xAxis.position === 'right') {
174
- if (yAxis.position === 'bottom') {
175
- rotate = -90
176
- rotateX = 180
177
- translateY = height
178
- translateX = width
179
- } else if (yAxis.position === 'top') {
180
- rotate = -90
181
- rotateX = 180
182
- rotateY = 180
183
- translateX = width
184
- } else {
185
- // 預設
186
- rotateX = 180
187
- translateY = height
188
- }
189
- }
190
- // selection.style('transform', `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`)
191
-
192
- return {
193
- translate: [translateX, translateY],
194
- scale: [1, 1],
195
- rotate,
196
- rotateX,
197
- rotateY,
198
- value: `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
199
- }
200
- }
201
-
202
- return new Observable(subscriber => {
203
- combineLatest({
204
- fullDataFormatter: fullDataFormatter$,
205
- layout: layout$
206
- }).pipe(
207
- takeUntil(destroy$),
208
- switchMap(async (d) => d),
209
- ).subscribe(data => {
210
- const axesTransformData = calcAxesTransform({
211
- xAxis: data.fullDataFormatter.grid.groupAxis,
212
- yAxis: data.fullDataFormatter.grid.valueAxis,
213
- width: data.layout.width,
214
- height: data.layout.height
215
- })
216
-
217
- subscriber.next(axesTransformData)
218
- })
219
-
220
- return function unscbscribe () {
221
- destroy$.next(undefined)
222
- }
223
- })
224
- }
225
-
226
-
227
- export const gridAxesReverseTransformObservable = ({ gridAxesTransform$ }: {
228
- gridAxesTransform$: Observable<TransformData>
229
- }): Observable<TransformData> => {
230
- return gridAxesTransform$.pipe(
231
- map(d => {
232
- // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
233
- const translate: [number, number] = [0, 0] // 無需逆轉
234
- const scale: [number, number] = [1 / d.scale[0], 1 / d.scale[1]]
235
- const rotate = d.rotate * -1
236
- const rotateX = d.rotateX * -1
237
- const rotateY = d.rotateY * -1
238
- return {
239
- translate,
240
- scale,
241
- rotate,
242
- rotateX,
243
- rotateY,
244
- value: `translate(${translate[0]}px, ${translate[1]}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
245
- }
246
- }),
247
- )
248
- }
249
-
250
- export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
251
- computedData$: Observable<ComputedDataTypeMap<'grid'>>
252
- fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
253
- layout$: Observable<Layout>
254
- }): Observable<TransformData> => {
255
- const destroy$ = new Subject()
256
-
257
- function calcGridDataAreaTransform ({ data, groupAxis, valueAxis, width, height }: {
258
- data: ComputedDataTypeMap<'grid'>
259
- groupAxis: DataFormatterGroupAxis
260
- valueAxis: DataFormatterValueAxis
261
- width: number
262
- height: number
263
- }): TransformData {
264
- let translateX = 0
265
- let translateY = 0
266
- let scaleX = 0
267
- let scaleY = 0
268
-
269
- // -- groupScale --
270
- const groupAxisWidth = (groupAxis.position === 'top' || groupAxis.position === 'bottom')
271
- ? width
272
- : height
273
- const groupMin = 0
274
- const groupMax = data[0] ? data[0].length - 1 : 0
275
- const groupScaleDomainMin = groupAxis.scaleDomain[0] === 'auto'
276
- ? groupMin - groupAxis.scalePadding
277
- : groupAxis.scaleDomain[0] as number - groupAxis.scalePadding
278
- const groupScaleDomainMax = groupAxis.scaleDomain[1] === 'auto'
279
- ? groupMax + groupAxis.scalePadding
280
- : groupAxis.scaleDomain[1] as number + groupAxis.scalePadding
281
-
282
- const groupScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
283
- maxValue: groupMax,
284
- minValue: groupMin,
285
- axisWidth: groupAxisWidth,
286
- // scaleDomain: groupAxis.scaleDomain,
287
- scaleDomain: [groupScaleDomainMin, groupScaleDomainMax],
288
- scaleRange: [0, 1]
289
- })
290
-
291
- // -- translateX, scaleX --
292
- const rangeMinX = groupScale(groupMin)
293
- const rangeMaxX = groupScale(groupMax)
294
- if (groupMin == groupMax) {
295
- // 當group只有一個
296
- translateX = 0
297
- scaleX = 1
298
- } else {
299
- translateX = rangeMinX
300
- const gWidth = rangeMaxX - rangeMinX
301
- scaleX = gWidth / groupAxisWidth
302
- }
303
-
304
- // -- valueScale --
305
- const filteredData = data.map((d, i) => {
306
- return d.filter((_d, _i) => {
307
- return _i >= groupScaleDomainMin && _i <= groupScaleDomainMax && _d.visible == true
308
- })
309
- })
310
-
311
- const filteredMinAndMax = getMinAndMaxGrid(filteredData)
312
-
313
- const valueAxisWidth = (valueAxis.position === 'left' || valueAxis.position === 'right')
314
- ? height
315
- : width
316
-
317
- const valueScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
318
- maxValue: filteredMinAndMax[1],
319
- minValue: filteredMinAndMax[0],
320
- axisWidth: valueAxisWidth,
321
- scaleDomain: valueAxis.scaleDomain,
322
- scaleRange: valueAxis.scaleRange
323
- })
324
-
325
- // -- translateY, scaleY --
326
- const minAndMax = getMinAndMaxGrid(data)
327
- const rangeMinY = valueScale(minAndMax[0])
328
- const rangeMaxY = valueScale(minAndMax[1])
329
- translateY = rangeMinY
330
- const gHeight = rangeMaxY - rangeMinY
331
- scaleY = gHeight / valueAxisWidth
332
-
333
- return {
334
- translate: [translateX, translateY],
335
- scale: [scaleX, scaleY],
336
- rotate: 0,
337
- rotateX: 0,
338
- rotateY: 0,
339
- value: `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`
340
- }
341
- }
342
-
343
- return new Observable(subscriber => {
344
- combineLatest({
345
- computedData: computedData$,
346
- fullDataFormatter: fullDataFormatter$,
347
- layout: layout$
348
- }).pipe(
349
- takeUntil(destroy$),
350
- switchMap(async (d) => d),
351
- ).subscribe(data => {
352
- const dataAreaTransformData = calcGridDataAreaTransform ({
353
- data: data.computedData,
354
- groupAxis: data.fullDataFormatter.grid.groupAxis,
355
- valueAxis: data.fullDataFormatter.grid.valueAxis,
356
- width: data.layout.width,
357
- height: data.layout.height
358
- })
359
-
360
- subscriber.next(dataAreaTransformData)
361
- })
362
-
363
- return function unscbscribe () {
364
- destroy$.next(undefined)
365
- }
366
- })
367
- }
368
-
369
- export const gridGraphicReverseScaleObservable = ({ gridContainerPosition$, gridAxesTransform$, gridGraphicTransform$ }: {
370
- gridContainerPosition$: Observable<GridContainerPosition[]>
371
- gridAxesTransform$: Observable<TransformData>
372
- gridGraphicTransform$: Observable<TransformData>
373
- }): Observable<[number, number][]> => {
374
- return combineLatest({
375
- gridContainerPosition: gridContainerPosition$,
376
- gridAxesTransform: gridAxesTransform$,
377
- gridGraphicTransform: gridGraphicTransform$,
378
- }).pipe(
379
- switchMap(async (d) => d),
380
- map(data => {
381
- if (data.gridAxesTransform.rotate == 0 || data.gridAxesTransform.rotate == 180) {
382
- return data.gridContainerPosition.map((series, seriesIndex) => {
383
- return [
384
- 1 / data.gridGraphicTransform.scale[0] / data.gridContainerPosition[seriesIndex].scale[0],
385
- 1 / data.gridGraphicTransform.scale[1] / data.gridContainerPosition[seriesIndex].scale[1],
386
- ]
387
- })
388
- } else {
389
- return data.gridContainerPosition.map((series, seriesIndex) => {
390
- // 由於有垂直的旋轉,所以外層 (container) x和y的scale要互換
391
- return [
392
- 1 / data.gridGraphicTransform.scale[0] / data.gridContainerPosition[seriesIndex].scale[1],
393
- 1 / data.gridGraphicTransform.scale[1] / data.gridContainerPosition[seriesIndex].scale[0],
394
- ]
395
- })
396
- }
397
- }),
398
- )
399
- }
400
-
401
- export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
402
- fullDataFormatter$: Observable<DataFormatterGrid>
403
- layout$: Observable<Layout>
404
- }): Observable<{
405
- width: number;
406
- height: number;
407
- }> => {
408
- const destroy$ = new Subject()
409
-
410
- function calcAxesSize ({ xAxisPosition, yAxisPosition, width, height }: {
411
- xAxisPosition: AxisPosition
412
- yAxisPosition: AxisPosition
413
- width: number
414
- height: number
415
- }) {
416
- if ((xAxisPosition === 'bottom' || xAxisPosition === 'top') && (yAxisPosition === 'left' || yAxisPosition === 'right')) {
417
- return { width, height }
418
- } else if ((xAxisPosition === 'left' || xAxisPosition === 'right') && (yAxisPosition === 'bottom' || yAxisPosition === 'top')) {
419
- return {
420
- width: height,
421
- height: width
422
- }
423
- }
424
- }
425
-
426
- return new Observable(subscriber => {
427
- combineLatest({
428
- fullDataFormatter: fullDataFormatter$,
429
- layout: layout$
430
- }).pipe(
431
- takeUntil(destroy$),
432
- switchMap(async (d) => d),
433
- ).subscribe(data => {
434
-
435
- const axisSize = calcAxesSize({
436
- xAxisPosition: data.fullDataFormatter.grid.groupAxis.position,
437
- yAxisPosition: data.fullDataFormatter.grid.valueAxis.position,
438
- width: data.layout.width,
439
- height: data.layout.height,
440
- })
441
-
442
- subscriber.next(axisSize)
443
-
444
- return function unsubscribe () {
445
- destroy$.next(undefined)
446
- }
447
- })
448
- })
449
- }
450
-
451
- // export const gridHighlightObservable = ({ computedData$, fullChartParams$, event$ }: {
452
- // computedData$: Observable<ComputedDataTypeMap<'grid'>>
453
- // fullChartParams$: Observable<ChartParams>
454
- // event$: Subject<any>
455
- // }): Observable<string[]> => {
456
- // const datumList$ = computedData$.pipe(
457
- // map(d => d.flat())
458
- // )
459
- // return highlightObservable ({ datumList$, fullChartParams$, event$ })
460
- // }
461
-
462
- export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
463
- return computedData$.pipe(
464
- map(data => {
465
- return data
466
- .filter(series => series.length)
467
- .map(series => {
468
- return series[0].seriesLabel
469
- })
470
- }),
471
- distinctUntilChanged((a, b) => {
472
- return JSON.stringify(a).length === JSON.stringify(b).length
473
- }),
474
- )
475
- }
476
-
477
- export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
478
- return computedData$.pipe(
479
- map(data => {
480
- const visibleComputedData = data
481
- .map(d => {
482
- return d.filter(_d => {
483
- return _d.visible == true
484
- })
485
- })
486
- .filter(d => d.length)
487
- return visibleComputedData
488
- })
489
- )
490
- }
491
-
492
- export const gridVisibleComputedLayoutDataObservable = ({ computedLayoutData$ }: { computedLayoutData$: Observable<ComputedLayoutDataGrid> }) => {
493
- return computedLayoutData$.pipe(
494
- map(data => {
495
- const visibleComputedData = data
496
- .map(d => {
497
- return d.filter(_d => {
498
- return _d.visible == true
499
- })
500
- })
501
- .filter(d => d.length)
502
- return visibleComputedData
503
- })
504
- )
505
- }
506
-
507
- // export const isSeriesSeprateObservable = ({ computedData$, fullDataFormatter$ }: {
508
- // computedData$: Observable<ComputedDataTypeMap<'grid'>>
509
- // fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
510
- // }) => {
511
- // return combineLatest({
512
- // computedData: computedData$,
513
- // fullDataFormatter: fullDataFormatter$
514
- // }).pipe(
515
- // map(data => {
516
- // return data.fullDataFormatter.grid.seriesSlotIndexes && data.fullDataFormatter.grid.seriesSlotIndexes.length === data.computedData.length
517
- // ? true
518
- // : false
519
- // }),
520
- // distinctUntilChanged()
521
- // )
522
- // }
523
-
524
- // 所有container位置(對應series)
525
- export const gridContainerPositionObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
526
- computedData$: Observable<ComputedDataTypeMap<'grid'>>
527
- fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
528
- layout$: Observable<Layout>
529
- }): Observable<GridContainerPosition[]> => {
530
-
531
- const gridContainerPosition$ = combineLatest({
532
- computedData: computedData$,
533
- fullDataFormatter: fullDataFormatter$,
534
- layout: layout$,
535
- }).pipe(
536
- switchMap(async (d) => d),
537
- map(data => {
538
-
539
- if (data.fullDataFormatter.grid.separateSeries) {
540
- // -- 依slotIndexes計算 --
541
- return calcGridContainerLayout(data.layout, data.fullDataFormatter.container, data.computedData.length)
542
- // return data.computedData.map((seriesData, seriesIndex) => {
543
- // const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
544
- // const rowIndex = Math.floor(seriesIndex / data.fullDataFormatter.container.columnAmount)
545
- // const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
546
- // return {
547
- // slotIndex: seriesIndex,
548
- // rowIndex,
549
- // columnIndex,
550
- // translate,
551
- // scale,
552
- // }
553
- // })
554
- } else {
555
- // -- 無拆分 --
556
- return calcGridContainerLayout(data.layout, data.fullDataFormatter.container, 1)
557
- // const columnIndex = 0
558
- // const rowIndex = 0
559
- // return data.computedData.map((seriesData, seriesIndex) => {
560
- // const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
561
- // return {
562
- // slotIndex: 0,
563
- // rowIndex,
564
- // columnIndex,
565
- // translate,
566
- // scale,
567
- // }
568
- // })
569
- }
570
- })
571
- )
572
-
573
- return gridContainerPosition$
1
+ import {
2
+ combineLatest,
3
+ distinctUntilChanged,
4
+ filter,
5
+ map,
6
+ merge,
7
+ takeUntil,
8
+ shareReplay,
9
+ switchMap,
10
+ Subject,
11
+ Observable } from 'rxjs'
12
+ import type {
13
+ AxisPosition,
14
+ ChartType,
15
+ ChartParams,
16
+ ComputedDataTypeMap,
17
+ ComputedDatumTypeMap,
18
+ ContextObserverFn,
19
+ DataTypeMap,
20
+ DataGridDatum,
21
+ ComputedDatumGrid,
22
+ DataFormatterTypeMap,
23
+ DataFormatterGrid,
24
+ DataFormatterValueAxis,
25
+ DataFormatterGroupAxis,
26
+ ComputedLayoutDatumGrid,
27
+ ComputedLayoutDataGrid,
28
+ GridContainerPosition,
29
+ HighlightTarget,
30
+ Layout,
31
+ TransformData } from '../types'
32
+ import { getMinAndMaxGrid } from '../utils/orbchartsUtils'
33
+ import { createAxisLinearScale, createAxisPointScale, createAxisQuantizeScale } from '../utils/d3Utils'
34
+ import { highlightObservable } from '../utils/observables'
35
+ import { calcGridContainerLayout } from '../utils/orbchartsUtils'
36
+ import { DATA_FORMATTER_GRID_GRID_DEFAULT } from '../defaults'
37
+ import { getMinAndMaxValue, transposeData, createGridSeriesLabels, createGridGroupLabels, seriesColorPredicate } from '../utils/orbchartsUtils'
38
+
39
+ export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
40
+ computedData$: Observable<ComputedDataTypeMap<'grid'>>
41
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
42
+ layout$: Observable<Layout>
43
+ }): Observable<ComputedLayoutDatumGrid[][]> => {
44
+
45
+ // 未篩選group範圍前的group scale
46
+ function createOriginGroupScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
47
+ const groupAxisWidth = (dataFormatter.grid.groupAxis.position === 'top' || dataFormatter.grid.groupAxis.position === 'bottom')
48
+ ? layout.width
49
+ : layout.height
50
+ const groupEndIndex = computedData[0] ? computedData[0].length - 1 : 0
51
+ const groupScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
52
+ maxValue: groupEndIndex,
53
+ minValue: 0,
54
+ axisWidth: groupAxisWidth,
55
+ scaleDomain: [0, groupEndIndex], // 不使用dataFormatter設定
56
+ scaleRange: [0, 1] // 不使用dataFormatter設定
57
+ })
58
+ return groupScale
59
+ }
60
+
61
+ // 未篩選group範圍及visible前的value scale
62
+ function createOriginValueScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
63
+ const valueAxisWidth = (dataFormatter.grid.valueAxis.position === 'left' || dataFormatter.grid.valueAxis.position === 'right')
64
+ ? layout.height
65
+ : layout.width
66
+
67
+ const listData = computedData.flat()
68
+ const [minValue, maxValue] = getMinAndMaxValue(listData)
69
+
70
+ const valueScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
71
+ maxValue,
72
+ minValue,
73
+ axisWidth: valueAxisWidth,
74
+ scaleDomain: [minValue, maxValue], // 不使用dataFormatter設定
75
+ scaleRange: [0, 1] // 不使用dataFormatter設定
76
+ })
77
+
78
+ return valueScale
79
+ }
80
+
81
+ return combineLatest({
82
+ computedData: computedData$,
83
+ fullDataFormatter: fullDataFormatter$,
84
+ layout: layout$
85
+ }).pipe(
86
+ switchMap(async d => d),
87
+ map(data => {
88
+ const groupScale = createOriginGroupScale(data.computedData, data.fullDataFormatter, data.layout)
89
+ const valueScale = createOriginValueScale(data.computedData, data.fullDataFormatter, data.layout)
90
+ const zeroY = valueScale(0)
91
+
92
+ return data.computedData.map((seriesData, seriesIndex) => {
93
+ return seriesData.map((groupDatum, groupIndex) => {
94
+ const axisX = groupScale(groupIndex)
95
+ const axisY = valueScale(groupDatum.value ?? 0)
96
+ return {
97
+ ...groupDatum,
98
+ axisX,
99
+ axisY,
100
+ axisYFromZero: axisY - zeroY
101
+ }
102
+ })
103
+ })
104
+ })
105
+ )
106
+ }
107
+
108
+ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
109
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
110
+ layout$: Observable<Layout>
111
+ }): Observable<TransformData> => {
112
+ const destroy$ = new Subject()
113
+
114
+ function calcAxesTransform ({ xAxis, yAxis, width, height }: {
115
+ xAxis: DataFormatterGroupAxis | DataFormatterValueAxis,
116
+ yAxis: DataFormatterValueAxis,
117
+ width: number,
118
+ height: number
119
+ }): TransformData {
120
+ if (!xAxis || !yAxis) {
121
+ return {
122
+ translate: [0, 0],
123
+ scale: [1, 1],
124
+ rotate: 0,
125
+ rotateX: 0,
126
+ rotateY: 0,
127
+ value: ''
128
+ }
129
+ }
130
+ // const width = size.width - fullChartParams.layout.left - fullChartParams.layout.right
131
+ // const height = size.height - fullChartParams.layout.top - fullChartParams.layout.bottom
132
+ let translateX = 0
133
+ let translateY = 0
134
+ let rotate = 0
135
+ let rotateX = 0
136
+ let rotateY = 0
137
+ if (xAxis.position === 'bottom') {
138
+ if (yAxis.position === 'left') {
139
+ rotateX = 180
140
+ translateY = height
141
+ } else if (yAxis.position === 'right') {
142
+ rotateX = 180
143
+ rotateY = 180
144
+ translateX = width
145
+ translateY = height
146
+ } else {
147
+ // 預設
148
+ rotateX = 180
149
+ translateY = height
150
+ }
151
+ } else if (xAxis.position === 'top') {
152
+ if (yAxis.position === 'left') {
153
+ } else if (yAxis.position === 'right') {
154
+ rotateY = 180
155
+ translateX = width
156
+ } else {
157
+ // 預設
158
+ rotateX = 180
159
+ translateY = height
160
+ }
161
+ } else if (xAxis.position === 'left') {
162
+ if (yAxis.position === 'bottom') {
163
+ rotate = -90
164
+ translateY = height
165
+ } else if (yAxis.position === 'top') {
166
+ rotate = -90
167
+ rotateY = 180
168
+ } else {
169
+ // 預設
170
+ rotateX = 180
171
+ translateY = height
172
+ }
173
+ } else if (xAxis.position === 'right') {
174
+ if (yAxis.position === 'bottom') {
175
+ rotate = -90
176
+ rotateX = 180
177
+ translateY = height
178
+ translateX = width
179
+ } else if (yAxis.position === 'top') {
180
+ rotate = -90
181
+ rotateX = 180
182
+ rotateY = 180
183
+ translateX = width
184
+ } else {
185
+ // 預設
186
+ rotateX = 180
187
+ translateY = height
188
+ }
189
+ }
190
+ // selection.style('transform', `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`)
191
+
192
+ return {
193
+ translate: [translateX, translateY],
194
+ scale: [1, 1],
195
+ rotate,
196
+ rotateX,
197
+ rotateY,
198
+ value: `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
199
+ }
200
+ }
201
+
202
+ return new Observable(subscriber => {
203
+ combineLatest({
204
+ fullDataFormatter: fullDataFormatter$,
205
+ layout: layout$
206
+ }).pipe(
207
+ takeUntil(destroy$),
208
+ switchMap(async (d) => d),
209
+ ).subscribe(data => {
210
+ const axesTransformData = calcAxesTransform({
211
+ xAxis: data.fullDataFormatter.grid.groupAxis,
212
+ yAxis: data.fullDataFormatter.grid.valueAxis,
213
+ width: data.layout.width,
214
+ height: data.layout.height
215
+ })
216
+
217
+ subscriber.next(axesTransformData)
218
+ })
219
+
220
+ return function unscbscribe () {
221
+ destroy$.next(undefined)
222
+ }
223
+ })
224
+ }
225
+
226
+
227
+ export const gridAxesReverseTransformObservable = ({ gridAxesTransform$ }: {
228
+ gridAxesTransform$: Observable<TransformData>
229
+ }): Observable<TransformData> => {
230
+ return gridAxesTransform$.pipe(
231
+ map(d => {
232
+ // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
233
+ const translate: [number, number] = [0, 0] // 無需逆轉
234
+ const scale: [number, number] = [1 / d.scale[0], 1 / d.scale[1]]
235
+ const rotate = d.rotate * -1
236
+ const rotateX = d.rotateX * -1
237
+ const rotateY = d.rotateY * -1
238
+ return {
239
+ translate,
240
+ scale,
241
+ rotate,
242
+ rotateX,
243
+ rotateY,
244
+ value: `translate(${translate[0]}px, ${translate[1]}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
245
+ }
246
+ }),
247
+ )
248
+ }
249
+
250
+ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
251
+ computedData$: Observable<ComputedDataTypeMap<'grid'>>
252
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
253
+ layout$: Observable<Layout>
254
+ }): Observable<TransformData> => {
255
+ const destroy$ = new Subject()
256
+
257
+ function calcGridDataAreaTransform ({ data, groupAxis, valueAxis, width, height }: {
258
+ data: ComputedDataTypeMap<'grid'>
259
+ groupAxis: DataFormatterGroupAxis
260
+ valueAxis: DataFormatterValueAxis
261
+ width: number
262
+ height: number
263
+ }): TransformData {
264
+ let translateX = 0
265
+ let translateY = 0
266
+ let scaleX = 0
267
+ let scaleY = 0
268
+
269
+ // -- groupScale --
270
+ const groupAxisWidth = (groupAxis.position === 'top' || groupAxis.position === 'bottom')
271
+ ? width
272
+ : height
273
+ const groupMin = 0
274
+ const groupMax = data[0] ? data[0].length - 1 : 0
275
+ const groupScaleDomainMin = groupAxis.scaleDomain[0] === 'auto'
276
+ ? groupMin - groupAxis.scalePadding
277
+ : groupAxis.scaleDomain[0] as number - groupAxis.scalePadding
278
+ const groupScaleDomainMax = groupAxis.scaleDomain[1] === 'auto'
279
+ ? groupMax + groupAxis.scalePadding
280
+ : groupAxis.scaleDomain[1] as number + groupAxis.scalePadding
281
+
282
+ const groupScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
283
+ maxValue: groupMax,
284
+ minValue: groupMin,
285
+ axisWidth: groupAxisWidth,
286
+ // scaleDomain: groupAxis.scaleDomain,
287
+ scaleDomain: [groupScaleDomainMin, groupScaleDomainMax],
288
+ scaleRange: [0, 1]
289
+ })
290
+
291
+ // -- translateX, scaleX --
292
+ const rangeMinX = groupScale(groupMin)
293
+ const rangeMaxX = groupScale(groupMax)
294
+ if (groupMin == groupMax) {
295
+ // 當group只有一個
296
+ translateX = 0
297
+ scaleX = 1
298
+ } else {
299
+ translateX = rangeMinX
300
+ const gWidth = rangeMaxX - rangeMinX
301
+ scaleX = gWidth / groupAxisWidth
302
+ }
303
+
304
+ // -- valueScale --
305
+ const filteredData = data.map((d, i) => {
306
+ return d.filter((_d, _i) => {
307
+ return _i >= groupScaleDomainMin && _i <= groupScaleDomainMax && _d.visible == true
308
+ })
309
+ })
310
+
311
+ const filteredMinAndMax = getMinAndMaxGrid(filteredData)
312
+
313
+ const valueAxisWidth = (valueAxis.position === 'left' || valueAxis.position === 'right')
314
+ ? height
315
+ : width
316
+
317
+ const valueScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
318
+ maxValue: filteredMinAndMax[1],
319
+ minValue: filteredMinAndMax[0],
320
+ axisWidth: valueAxisWidth,
321
+ scaleDomain: valueAxis.scaleDomain,
322
+ scaleRange: valueAxis.scaleRange
323
+ })
324
+
325
+ // -- translateY, scaleY --
326
+ const minAndMax = getMinAndMaxGrid(data)
327
+ const rangeMinY = valueScale(minAndMax[0])
328
+ const rangeMaxY = valueScale(minAndMax[1])
329
+ translateY = rangeMinY
330
+ const gHeight = rangeMaxY - rangeMinY
331
+ scaleY = gHeight / valueAxisWidth
332
+
333
+ return {
334
+ translate: [translateX, translateY],
335
+ scale: [scaleX, scaleY],
336
+ rotate: 0,
337
+ rotateX: 0,
338
+ rotateY: 0,
339
+ value: `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`
340
+ }
341
+ }
342
+
343
+ return new Observable(subscriber => {
344
+ combineLatest({
345
+ computedData: computedData$,
346
+ fullDataFormatter: fullDataFormatter$,
347
+ layout: layout$
348
+ }).pipe(
349
+ takeUntil(destroy$),
350
+ switchMap(async (d) => d),
351
+ ).subscribe(data => {
352
+ const dataAreaTransformData = calcGridDataAreaTransform ({
353
+ data: data.computedData,
354
+ groupAxis: data.fullDataFormatter.grid.groupAxis,
355
+ valueAxis: data.fullDataFormatter.grid.valueAxis,
356
+ width: data.layout.width,
357
+ height: data.layout.height
358
+ })
359
+
360
+ subscriber.next(dataAreaTransformData)
361
+ })
362
+
363
+ return function unscbscribe () {
364
+ destroy$.next(undefined)
365
+ }
366
+ })
367
+ }
368
+
369
+ export const gridGraphicReverseScaleObservable = ({ gridContainerPosition$, gridAxesTransform$, gridGraphicTransform$ }: {
370
+ gridContainerPosition$: Observable<GridContainerPosition[]>
371
+ gridAxesTransform$: Observable<TransformData>
372
+ gridGraphicTransform$: Observable<TransformData>
373
+ }): Observable<[number, number][]> => {
374
+ return combineLatest({
375
+ gridContainerPosition: gridContainerPosition$,
376
+ gridAxesTransform: gridAxesTransform$,
377
+ gridGraphicTransform: gridGraphicTransform$,
378
+ }).pipe(
379
+ switchMap(async (d) => d),
380
+ map(data => {
381
+ if (data.gridAxesTransform.rotate == 0 || data.gridAxesTransform.rotate == 180) {
382
+ return data.gridContainerPosition.map((series, seriesIndex) => {
383
+ return [
384
+ 1 / data.gridGraphicTransform.scale[0] / data.gridContainerPosition[seriesIndex].scale[0],
385
+ 1 / data.gridGraphicTransform.scale[1] / data.gridContainerPosition[seriesIndex].scale[1],
386
+ ]
387
+ })
388
+ } else {
389
+ return data.gridContainerPosition.map((series, seriesIndex) => {
390
+ // 由於有垂直的旋轉,所以外層 (container) x和y的scale要互換
391
+ return [
392
+ 1 / data.gridGraphicTransform.scale[0] / data.gridContainerPosition[seriesIndex].scale[1],
393
+ 1 / data.gridGraphicTransform.scale[1] / data.gridContainerPosition[seriesIndex].scale[0],
394
+ ]
395
+ })
396
+ }
397
+ }),
398
+ )
399
+ }
400
+
401
+ export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
402
+ fullDataFormatter$: Observable<DataFormatterGrid>
403
+ layout$: Observable<Layout>
404
+ }): Observable<{
405
+ width: number;
406
+ height: number;
407
+ }> => {
408
+ const destroy$ = new Subject()
409
+
410
+ function calcAxesSize ({ xAxisPosition, yAxisPosition, width, height }: {
411
+ xAxisPosition: AxisPosition
412
+ yAxisPosition: AxisPosition
413
+ width: number
414
+ height: number
415
+ }) {
416
+ if ((xAxisPosition === 'bottom' || xAxisPosition === 'top') && (yAxisPosition === 'left' || yAxisPosition === 'right')) {
417
+ return { width, height }
418
+ } else if ((xAxisPosition === 'left' || xAxisPosition === 'right') && (yAxisPosition === 'bottom' || yAxisPosition === 'top')) {
419
+ return {
420
+ width: height,
421
+ height: width
422
+ }
423
+ }
424
+ }
425
+
426
+ return new Observable(subscriber => {
427
+ combineLatest({
428
+ fullDataFormatter: fullDataFormatter$,
429
+ layout: layout$
430
+ }).pipe(
431
+ takeUntil(destroy$),
432
+ switchMap(async (d) => d),
433
+ ).subscribe(data => {
434
+
435
+ const axisSize = calcAxesSize({
436
+ xAxisPosition: data.fullDataFormatter.grid.groupAxis.position,
437
+ yAxisPosition: data.fullDataFormatter.grid.valueAxis.position,
438
+ width: data.layout.width,
439
+ height: data.layout.height,
440
+ })
441
+
442
+ subscriber.next(axisSize)
443
+
444
+ return function unsubscribe () {
445
+ destroy$.next(undefined)
446
+ }
447
+ })
448
+ })
449
+ }
450
+
451
+ // export const gridHighlightObservable = ({ computedData$, fullChartParams$, event$ }: {
452
+ // computedData$: Observable<ComputedDataTypeMap<'grid'>>
453
+ // fullChartParams$: Observable<ChartParams>
454
+ // event$: Subject<any>
455
+ // }): Observable<string[]> => {
456
+ // const datumList$ = computedData$.pipe(
457
+ // map(d => d.flat())
458
+ // )
459
+ // return highlightObservable ({ datumList$, fullChartParams$, event$ })
460
+ // }
461
+
462
+ export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
463
+ return computedData$.pipe(
464
+ map(data => {
465
+ return data
466
+ .filter(series => series.length)
467
+ .map(series => {
468
+ return series[0].seriesLabel
469
+ })
470
+ }),
471
+ distinctUntilChanged((a, b) => {
472
+ return JSON.stringify(a).length === JSON.stringify(b).length
473
+ }),
474
+ )
475
+ }
476
+
477
+ export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
478
+ return computedData$.pipe(
479
+ map(data => {
480
+ const visibleComputedData = data
481
+ .map(d => {
482
+ return d.filter(_d => {
483
+ return _d.visible == true
484
+ })
485
+ })
486
+ .filter(d => d.length)
487
+ return visibleComputedData
488
+ })
489
+ )
490
+ }
491
+
492
+ export const gridVisibleComputedLayoutDataObservable = ({ computedLayoutData$ }: { computedLayoutData$: Observable<ComputedLayoutDataGrid> }) => {
493
+ return computedLayoutData$.pipe(
494
+ map(data => {
495
+ const visibleComputedData = data
496
+ .map(d => {
497
+ return d.filter(_d => {
498
+ return _d.visible == true
499
+ })
500
+ })
501
+ .filter(d => d.length)
502
+ return visibleComputedData
503
+ })
504
+ )
505
+ }
506
+
507
+ // export const isSeriesSeprateObservable = ({ computedData$, fullDataFormatter$ }: {
508
+ // computedData$: Observable<ComputedDataTypeMap<'grid'>>
509
+ // fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
510
+ // }) => {
511
+ // return combineLatest({
512
+ // computedData: computedData$,
513
+ // fullDataFormatter: fullDataFormatter$
514
+ // }).pipe(
515
+ // map(data => {
516
+ // return data.fullDataFormatter.grid.seriesSlotIndexes && data.fullDataFormatter.grid.seriesSlotIndexes.length === data.computedData.length
517
+ // ? true
518
+ // : false
519
+ // }),
520
+ // distinctUntilChanged()
521
+ // )
522
+ // }
523
+
524
+ // 所有container位置(對應series)
525
+ export const gridContainerPositionObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
526
+ computedData$: Observable<ComputedDataTypeMap<'grid'>>
527
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
528
+ layout$: Observable<Layout>
529
+ }): Observable<GridContainerPosition[]> => {
530
+
531
+ const gridContainerPosition$ = combineLatest({
532
+ computedData: computedData$,
533
+ fullDataFormatter: fullDataFormatter$,
534
+ layout: layout$,
535
+ }).pipe(
536
+ switchMap(async (d) => d),
537
+ map(data => {
538
+
539
+ if (data.fullDataFormatter.grid.separateSeries) {
540
+ // -- 依slotIndexes計算 --
541
+ return calcGridContainerLayout(data.layout, data.fullDataFormatter.container, data.computedData.length)
542
+ // return data.computedData.map((seriesData, seriesIndex) => {
543
+ // const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
544
+ // const rowIndex = Math.floor(seriesIndex / data.fullDataFormatter.container.columnAmount)
545
+ // const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
546
+ // return {
547
+ // slotIndex: seriesIndex,
548
+ // rowIndex,
549
+ // columnIndex,
550
+ // translate,
551
+ // scale,
552
+ // }
553
+ // })
554
+ } else {
555
+ // -- 無拆分 --
556
+ return calcGridContainerLayout(data.layout, data.fullDataFormatter.container, 1)
557
+ // const columnIndex = 0
558
+ // const rowIndex = 0
559
+ // return data.computedData.map((seriesData, seriesIndex) => {
560
+ // const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
561
+ // return {
562
+ // slotIndex: 0,
563
+ // rowIndex,
564
+ // columnIndex,
565
+ // translate,
566
+ // scale,
567
+ // }
568
+ // })
569
+ }
570
+ })
571
+ )
572
+
573
+ return gridContainerPosition$
574
574
  }