@orbcharts/core 3.0.0-alpha.32 → 3.0.0-alpha.33
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.
- package/dist/orbcharts-core.es.js +1572 -1414
- package/dist/orbcharts-core.umd.js +2 -2
- package/dist/src/defaults.d.ts +4 -3
- package/dist/src/grid/gridObservables.d.ts +27 -3
- package/dist/src/multiGrid/multiGridObservables.d.ts +3 -15
- package/dist/src/types/ContextObserverGrid.d.ts +15 -2
- package/dist/src/types/ContextObserverMultiGrid.d.ts +3 -24
- package/dist/src/types/DataFormatterGrid.d.ts +24 -6
- package/dist/src/types/DataFormatterMultiGrid.d.ts +9 -9
- package/dist/src/utils/orbchartsUtils.d.ts +7 -2
- package/package.json +1 -1
- package/src/base/createBaseChart.ts +3 -3
- package/src/defaults.ts +31 -18
- package/src/grid/computeGridData.ts +87 -30
- package/src/grid/createGridContextObserver.ts +42 -9
- package/src/grid/gridObservables.ts +155 -28
- package/src/multiGrid/computeMultiGridData.ts +16 -12
- package/src/multiGrid/multiGridObservables.ts +188 -114
- package/src/types/ContextObserverGrid.ts +20 -2
- package/src/types/ContextObserverMultiGrid.ts +18 -19
- package/src/types/DataFormatterGrid.ts +28 -13
- package/src/types/DataFormatterMultiGrid.ts +14 -12
- package/src/utils/orbchartsUtils.ts +26 -10
|
@@ -19,15 +19,18 @@ import type {
|
|
|
19
19
|
DataTypeMap,
|
|
20
20
|
DataFormatterTypeMap,
|
|
21
21
|
DataFormatterGrid,
|
|
22
|
-
|
|
22
|
+
DataFormatterGridContainer,
|
|
23
23
|
DataFormatterValueAxis,
|
|
24
24
|
DataFormatterGroupAxis,
|
|
25
|
+
ContainerPosition,
|
|
25
26
|
HighlightTarget,
|
|
26
27
|
Layout,
|
|
27
28
|
TransformData } from '../types'
|
|
28
|
-
import { getMinAndMaxGrid
|
|
29
|
+
import { getMinAndMaxGrid } from '../utils/orbchartsUtils'
|
|
29
30
|
import { createAxisLinearScale, createAxisPointScale, createAxisQuantizeScale } from '../utils/d3Utils'
|
|
30
31
|
import { highlightObservable } from '../utils/observables'
|
|
32
|
+
import { calcGridContainerPosition } from '../utils/orbchartsUtils'
|
|
33
|
+
import { DATA_FORMATTER_GRID_GRID_DEFAULT } from '../defaults'
|
|
31
34
|
|
|
32
35
|
export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
|
33
36
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
|
@@ -44,7 +47,7 @@ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
|
|
44
47
|
if (!xAxis || !yAxis) {
|
|
45
48
|
return {
|
|
46
49
|
translate: [0, 0],
|
|
47
|
-
scale: [
|
|
50
|
+
scale: [1, 1],
|
|
48
51
|
rotate: 0,
|
|
49
52
|
rotateX: 0,
|
|
50
53
|
rotateY: 0,
|
|
@@ -102,6 +105,8 @@ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
|
|
102
105
|
translateX = width
|
|
103
106
|
} else if (yAxis.position === 'top') {
|
|
104
107
|
rotate = -90
|
|
108
|
+
rotateX = 180
|
|
109
|
+
rotateY = 180
|
|
105
110
|
translateX = width
|
|
106
111
|
} else {
|
|
107
112
|
// 預設
|
|
@@ -109,12 +114,11 @@ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
|
|
109
114
|
translateY = height
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
|
-
|
|
113
117
|
// selection.style('transform', `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`)
|
|
114
118
|
|
|
115
119
|
return {
|
|
116
120
|
translate: [translateX, translateY],
|
|
117
|
-
scale: [
|
|
121
|
+
scale: [1, 1],
|
|
118
122
|
rotate,
|
|
119
123
|
rotateX,
|
|
120
124
|
rotateY,
|
|
@@ -131,8 +135,8 @@ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
|
|
131
135
|
switchMap(async (d) => d),
|
|
132
136
|
).subscribe(data => {
|
|
133
137
|
const axesTransformData = calcAxesTransform({
|
|
134
|
-
xAxis: data.fullDataFormatter.groupAxis,
|
|
135
|
-
yAxis: data.fullDataFormatter.valueAxis,
|
|
138
|
+
xAxis: data.fullDataFormatter.grid.groupAxis,
|
|
139
|
+
yAxis: data.fullDataFormatter.grid.valueAxis,
|
|
136
140
|
width: data.layout.width,
|
|
137
141
|
height: data.layout.height
|
|
138
142
|
})
|
|
@@ -146,6 +150,30 @@ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
|
|
146
150
|
})
|
|
147
151
|
}
|
|
148
152
|
|
|
153
|
+
|
|
154
|
+
export const gridAxesReverseTransformObservable = ({ gridAxesTransform$ }: {
|
|
155
|
+
gridAxesTransform$: Observable<TransformData>
|
|
156
|
+
}): Observable<TransformData> => {
|
|
157
|
+
return gridAxesTransform$.pipe(
|
|
158
|
+
map(d => {
|
|
159
|
+
// const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
|
|
160
|
+
const translate: [number, number] = [0, 0] // 無需逆轉
|
|
161
|
+
const scale: [number, number] = [1 / d.scale[0], 1 / d.scale[1]]
|
|
162
|
+
const rotate = d.rotate * -1
|
|
163
|
+
const rotateX = d.rotateX * -1
|
|
164
|
+
const rotateY = d.rotateY * -1
|
|
165
|
+
return {
|
|
166
|
+
translate,
|
|
167
|
+
scale,
|
|
168
|
+
rotate,
|
|
169
|
+
rotateX,
|
|
170
|
+
rotateY,
|
|
171
|
+
value: `translate(${translate[0]}px, ${translate[1]}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
|
|
172
|
+
}
|
|
173
|
+
}),
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
|
|
149
177
|
export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
|
|
150
178
|
computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
|
151
179
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
|
@@ -244,8 +272,8 @@ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatte
|
|
|
244
272
|
).subscribe(data => {
|
|
245
273
|
const dataAreaTransformData = calcGridDataAreaTransform ({
|
|
246
274
|
data: data.computedData,
|
|
247
|
-
groupAxis: data.fullDataFormatter.groupAxis,
|
|
248
|
-
valueAxis: data.fullDataFormatter.valueAxis,
|
|
275
|
+
groupAxis: data.fullDataFormatter.grid.groupAxis,
|
|
276
|
+
valueAxis: data.fullDataFormatter.grid.valueAxis,
|
|
249
277
|
width: data.layout.width,
|
|
250
278
|
height: data.layout.height
|
|
251
279
|
})
|
|
@@ -259,24 +287,33 @@ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatte
|
|
|
259
287
|
})
|
|
260
288
|
}
|
|
261
289
|
|
|
262
|
-
export const
|
|
290
|
+
export const gridGraphicReverseScaleObservable = ({ gridContainer$, gridAxesTransform$, gridGraphicTransform$ }: {
|
|
291
|
+
gridContainer$: Observable<ContainerPosition[]>
|
|
263
292
|
gridAxesTransform$: Observable<TransformData>
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
293
|
+
gridGraphicTransform$: Observable<TransformData>
|
|
294
|
+
}): Observable<[number, number][]> => {
|
|
295
|
+
return combineLatest({
|
|
296
|
+
gridContainer: gridContainer$,
|
|
297
|
+
gridAxesTransform: gridAxesTransform$,
|
|
298
|
+
gridGraphicTransform: gridGraphicTransform$,
|
|
299
|
+
}).pipe(
|
|
300
|
+
switchMap(async (d) => d),
|
|
301
|
+
map(data => {
|
|
302
|
+
if (data.gridAxesTransform.rotate == 0 || data.gridAxesTransform.rotate == 180) {
|
|
303
|
+
return data.gridContainer.map((series, seriesIndex) => {
|
|
304
|
+
return [
|
|
305
|
+
1 / data.gridGraphicTransform.scale[0] / data.gridContainer[seriesIndex].scale[0],
|
|
306
|
+
1 / data.gridGraphicTransform.scale[1] / data.gridContainer[seriesIndex].scale[1],
|
|
307
|
+
]
|
|
308
|
+
})
|
|
309
|
+
} else {
|
|
310
|
+
return data.gridContainer.map((series, seriesIndex) => {
|
|
311
|
+
// 由於有垂直的旋轉,所以外層 (container) x和y的scale要互換
|
|
312
|
+
return [
|
|
313
|
+
1 / data.gridGraphicTransform.scale[0] / data.gridContainer[seriesIndex].scale[1],
|
|
314
|
+
1 / data.gridGraphicTransform.scale[1] / data.gridContainer[seriesIndex].scale[0],
|
|
315
|
+
]
|
|
316
|
+
})
|
|
280
317
|
}
|
|
281
318
|
}),
|
|
282
319
|
)
|
|
@@ -317,8 +354,8 @@ export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
|
|
|
317
354
|
).subscribe(data => {
|
|
318
355
|
|
|
319
356
|
const axisSize = calcAxesSize({
|
|
320
|
-
xAxisPosition: data.fullDataFormatter.groupAxis.position,
|
|
321
|
-
yAxisPosition: data.fullDataFormatter.valueAxis.position,
|
|
357
|
+
xAxisPosition: data.fullDataFormatter.grid.groupAxis.position,
|
|
358
|
+
yAxisPosition: data.fullDataFormatter.grid.valueAxis.position,
|
|
322
359
|
width: data.layout.width,
|
|
323
360
|
height: data.layout.height,
|
|
324
361
|
})
|
|
@@ -343,6 +380,21 @@ export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
|
|
|
343
380
|
// return highlightObservable ({ datumList$, fullChartParams$, event$ })
|
|
344
381
|
// }
|
|
345
382
|
|
|
383
|
+
export const existedSeriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
|
|
384
|
+
return computedData$.pipe(
|
|
385
|
+
map(data => {
|
|
386
|
+
return data
|
|
387
|
+
.filter(series => series.length)
|
|
388
|
+
.map(series => {
|
|
389
|
+
return series[0].seriesLabel
|
|
390
|
+
})
|
|
391
|
+
}),
|
|
392
|
+
distinctUntilChanged((a, b) => {
|
|
393
|
+
return JSON.stringify(a).length === JSON.stringify(b).length
|
|
394
|
+
}),
|
|
395
|
+
)
|
|
396
|
+
}
|
|
397
|
+
|
|
346
398
|
export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
|
|
347
399
|
return computedData$.pipe(
|
|
348
400
|
map(data => {
|
|
@@ -358,3 +410,78 @@ export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedD
|
|
|
358
410
|
)
|
|
359
411
|
}
|
|
360
412
|
|
|
413
|
+
export const isSeriesPositionSeprateObservable = ({ computedData$, fullDataFormatter$ }: {
|
|
414
|
+
computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
|
415
|
+
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
|
416
|
+
}) => {
|
|
417
|
+
return combineLatest({
|
|
418
|
+
computedData: computedData$,
|
|
419
|
+
fullDataFormatter: fullDataFormatter$
|
|
420
|
+
}).pipe(
|
|
421
|
+
map(data => {
|
|
422
|
+
return data.fullDataFormatter.grid.seriesSlotIndexes && data.fullDataFormatter.grid.seriesSlotIndexes.length === data.computedData.length
|
|
423
|
+
? true
|
|
424
|
+
: false
|
|
425
|
+
}),
|
|
426
|
+
distinctUntilChanged()
|
|
427
|
+
)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// 所有container位置(對應series)
|
|
431
|
+
export const gridContainerObservable = ({ computedData$, fullDataFormatter$, fullChartParams$, layout$ }: {
|
|
432
|
+
computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
|
433
|
+
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
|
434
|
+
fullChartParams$: Observable<ChartParams>
|
|
435
|
+
layout$: Observable<Layout>
|
|
436
|
+
}) => {
|
|
437
|
+
|
|
438
|
+
const gridContainer$ = combineLatest({
|
|
439
|
+
computedData: computedData$,
|
|
440
|
+
fullDataFormatter: fullDataFormatter$,
|
|
441
|
+
fullChartParams: fullChartParams$,
|
|
442
|
+
layout: layout$,
|
|
443
|
+
}).pipe(
|
|
444
|
+
switchMap(async (d) => d),
|
|
445
|
+
map(data => {
|
|
446
|
+
|
|
447
|
+
const grid = data.fullDataFormatter.grid
|
|
448
|
+
|
|
449
|
+
// 有設定series定位
|
|
450
|
+
const hasSeriesPosition = grid.seriesSlotIndexes && grid.seriesSlotIndexes.length === data.computedData.length
|
|
451
|
+
? true
|
|
452
|
+
: false
|
|
453
|
+
|
|
454
|
+
if (hasSeriesPosition) {
|
|
455
|
+
// -- 依seriesSlotIndexes計算 --
|
|
456
|
+
return data.computedData.map((seriesData, seriesIndex) => {
|
|
457
|
+
const columnIndex = grid.seriesSlotIndexes[seriesIndex] % data.fullDataFormatter.container.columnAmount
|
|
458
|
+
const rowIndex = Math.floor(grid.seriesSlotIndexes[seriesIndex] / data.fullDataFormatter.container.columnAmount)
|
|
459
|
+
const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
|
460
|
+
return {
|
|
461
|
+
slotIndex: grid.seriesSlotIndexes[seriesIndex],
|
|
462
|
+
rowIndex,
|
|
463
|
+
columnIndex,
|
|
464
|
+
translate,
|
|
465
|
+
scale,
|
|
466
|
+
}
|
|
467
|
+
})
|
|
468
|
+
} else {
|
|
469
|
+
// -- 依grid的slotIndex計算 --
|
|
470
|
+
const columnIndex = grid.slotIndex % data.fullDataFormatter.container.columnAmount
|
|
471
|
+
const rowIndex = Math.floor(grid.slotIndex / data.fullDataFormatter.container.columnAmount)
|
|
472
|
+
return data.computedData.map((seriesData, seriesIndex) => {
|
|
473
|
+
const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
|
474
|
+
return {
|
|
475
|
+
slotIndex: grid.slotIndex,
|
|
476
|
+
rowIndex,
|
|
477
|
+
columnIndex,
|
|
478
|
+
translate,
|
|
479
|
+
scale,
|
|
480
|
+
}
|
|
481
|
+
})
|
|
482
|
+
}
|
|
483
|
+
})
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
return gridContainer$
|
|
487
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { DataGrid } from '../types/DataGrid'
|
|
2
2
|
import type { ComputedDataFn } from '../types/ComputedData'
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
3
|
+
import type { DataFormatterGrid } from '../types/DataFormatterGrid'
|
|
4
|
+
import type { ComputedDataMultiGrid } from '../types/ComputedDataMultiGrid'
|
|
5
5
|
import { computeBaseGridData } from '../grid/computeGridData'
|
|
6
|
-
import {
|
|
6
|
+
import { DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT } from '../defaults'
|
|
7
7
|
import { seriesColorPredicate } from '../utils/orbchartsUtils'
|
|
8
8
|
|
|
9
9
|
export const computeMultiGridData: ComputedDataFn<'multiGrid'> = ({ data = [], dataFormatter, chartParams, layout }) => {
|
|
@@ -11,23 +11,27 @@ export const computeMultiGridData: ComputedDataFn<'multiGrid'> = ({ data = [], d
|
|
|
11
11
|
return []
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
let multiGridData:
|
|
14
|
+
let multiGridData: ComputedDataMultiGrid = []
|
|
15
15
|
|
|
16
16
|
try {
|
|
17
|
-
const
|
|
17
|
+
const defaultGrid = dataFormatter.gridList[0] || DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT
|
|
18
18
|
|
|
19
19
|
// 計算每個grid的資料
|
|
20
20
|
multiGridData = data.map((gridData, gridIndex) => {
|
|
21
|
-
const currentDataFormatterGrid = dataFormatter.
|
|
22
|
-
|
|
23
|
-
// ...currentDataFormatterGrid,
|
|
24
|
-
// type: `multiGrid` as any,
|
|
25
|
-
// visibleFilter: dataFormatter.visibleFilter as any,
|
|
26
|
-
// }
|
|
21
|
+
const currentDataFormatterGrid = dataFormatter.gridList[gridIndex] || defaultGrid
|
|
22
|
+
|
|
27
23
|
return computeBaseGridData(
|
|
28
24
|
{
|
|
29
25
|
data: gridData,
|
|
30
|
-
dataFormatter:
|
|
26
|
+
dataFormatter: {
|
|
27
|
+
type: 'grid',
|
|
28
|
+
grid: {
|
|
29
|
+
...currentDataFormatterGrid
|
|
30
|
+
},
|
|
31
|
+
container: {
|
|
32
|
+
...dataFormatter.container
|
|
33
|
+
}
|
|
34
|
+
},
|
|
31
35
|
chartParams,
|
|
32
36
|
layout
|
|
33
37
|
},
|
|
@@ -16,21 +16,16 @@ import type {
|
|
|
16
16
|
ChartType,
|
|
17
17
|
ChartParams,
|
|
18
18
|
ComputedDataTypeMap,
|
|
19
|
-
|
|
20
|
-
ContextObserverFn,
|
|
19
|
+
ComputedDataGrid,
|
|
21
20
|
DataTypeMap,
|
|
22
21
|
DataFormatterTypeMap,
|
|
23
22
|
DataFormatterGrid,
|
|
24
|
-
DataFormatterContext,
|
|
25
|
-
DataFormatterValueAxis,
|
|
26
|
-
DataFormatterGroupAxis,
|
|
27
23
|
DataFormatterMultiGridContainer,
|
|
28
24
|
EventMultiGrid,
|
|
29
25
|
HighlightTarget,
|
|
30
26
|
Layout,
|
|
31
27
|
TransformData } from '../types'
|
|
32
|
-
import {
|
|
33
|
-
import { createAxisLinearScale, createAxisPointScale, createAxisQuantizeScale } from '../utils/d3Utils'
|
|
28
|
+
import type { ContextObserverGridDetail } from '../types'
|
|
34
29
|
import {
|
|
35
30
|
highlightObservable,
|
|
36
31
|
seriesDataMapObservable,
|
|
@@ -38,11 +33,17 @@ import {
|
|
|
38
33
|
import {
|
|
39
34
|
gridAxesTransformObservable,
|
|
40
35
|
gridGraphicTransformObservable,
|
|
41
|
-
|
|
36
|
+
gridGraphicReverseScaleObservable,
|
|
37
|
+
gridAxesReverseTransformObservable,
|
|
42
38
|
gridAxesSizeObservable,
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
existedSeriesLabelsObservable,
|
|
40
|
+
gridVisibleComputedDataObservable,
|
|
41
|
+
isSeriesPositionSeprateObservable,
|
|
42
|
+
gridContainerObservable } from '../grid/gridObservables'
|
|
43
|
+
import { DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT } from '../defaults'
|
|
44
|
+
import { calcGridContainerPosition } from '../utils/orbchartsUtils'
|
|
45
45
|
|
|
46
|
+
// 每一個grid計算出來的所有Observable
|
|
46
47
|
export const multiGridEachDetailObservable = ({ fullDataFormatter$, computedData$, layout$, fullChartParams$, event$ }: {
|
|
47
48
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'multiGrid'>>
|
|
48
49
|
computedData$: Observable<ComputedDataTypeMap<'multiGrid'>>
|
|
@@ -50,6 +51,122 @@ export const multiGridEachDetailObservable = ({ fullDataFormatter$, computedData
|
|
|
50
51
|
fullChartParams$: Observable<ChartParams>
|
|
51
52
|
event$: Subject<EventMultiGrid>
|
|
52
53
|
}) => {
|
|
54
|
+
|
|
55
|
+
// 建立Observables
|
|
56
|
+
function detailObservables ({ gridDataFormatter$, gridComputedData$, layout$, fullChartParams$, event$ }: {
|
|
57
|
+
// fullDataFormatter$: Observable<DataFormatterTypeMap<'multiGrid'>>
|
|
58
|
+
// computedData$: Observable<ComputedDataTypeMap<'multiGrid'>>
|
|
59
|
+
gridDataFormatter$: Observable<DataFormatterGrid>
|
|
60
|
+
gridComputedData$: Observable<ComputedDataGrid>
|
|
61
|
+
layout$: Observable<Layout>
|
|
62
|
+
fullChartParams$: Observable<ChartParams>
|
|
63
|
+
event$: Subject<EventMultiGrid>
|
|
64
|
+
}): ContextObserverGridDetail {
|
|
65
|
+
|
|
66
|
+
const isSeriesPositionSeprate$ = isSeriesPositionSeprateObservable({
|
|
67
|
+
computedData$: gridComputedData$,
|
|
68
|
+
fullDataFormatter$: gridDataFormatter$,
|
|
69
|
+
}).pipe(
|
|
70
|
+
shareReplay(1)
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
const gridContainer$ = gridContainerObservable({
|
|
74
|
+
computedData$: gridComputedData$,
|
|
75
|
+
fullDataFormatter$: gridDataFormatter$,
|
|
76
|
+
fullChartParams$,
|
|
77
|
+
layout$
|
|
78
|
+
}).pipe(
|
|
79
|
+
shareReplay(1)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
const gridAxesTransform$ = gridAxesTransformObservable({
|
|
83
|
+
fullDataFormatter$: gridDataFormatter$,
|
|
84
|
+
layout$: layout$
|
|
85
|
+
}).pipe(
|
|
86
|
+
shareReplay(1)
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
const gridAxesReverseTransform$ = gridAxesReverseTransformObservable({
|
|
91
|
+
gridAxesTransform$
|
|
92
|
+
}).pipe(
|
|
93
|
+
shareReplay(1)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const gridGraphicTransform$ = gridGraphicTransformObservable({
|
|
97
|
+
computedData$: gridComputedData$,
|
|
98
|
+
fullDataFormatter$: gridDataFormatter$,
|
|
99
|
+
layout$: layout$
|
|
100
|
+
}).pipe(
|
|
101
|
+
shareReplay(1)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const gridGraphicReverseScale$ = gridGraphicReverseScaleObservable({
|
|
105
|
+
gridContainer$: gridContainer$,
|
|
106
|
+
gridAxesTransform$: gridAxesTransform$,
|
|
107
|
+
gridGraphicTransform$: gridGraphicTransform$,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const gridAxesSize$ = gridAxesSizeObservable({
|
|
111
|
+
fullDataFormatter$: gridDataFormatter$,
|
|
112
|
+
layout$: layout$
|
|
113
|
+
}).pipe(
|
|
114
|
+
shareReplay(1)
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
const datumList$ = gridComputedData$.pipe(
|
|
118
|
+
map(d => d.flat())
|
|
119
|
+
).pipe(
|
|
120
|
+
shareReplay(1)
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
const gridHighlight$ = highlightObservable({
|
|
124
|
+
datumList$,
|
|
125
|
+
fullChartParams$: fullChartParams$,
|
|
126
|
+
event$: event$
|
|
127
|
+
}).pipe(
|
|
128
|
+
shareReplay(1)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
const existedSeriesLabels$ = existedSeriesLabelsObservable({
|
|
132
|
+
computedData$: gridComputedData$,
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const SeriesDataMap$ = seriesDataMapObservable({
|
|
136
|
+
datumList$: datumList$
|
|
137
|
+
}).pipe(
|
|
138
|
+
shareReplay(1)
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
const GroupDataMap$ = groupDataMapObservable({
|
|
142
|
+
datumList$: datumList$
|
|
143
|
+
}).pipe(
|
|
144
|
+
shareReplay(1)
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
const visibleComputedData$ = gridVisibleComputedDataObservable({
|
|
148
|
+
computedData$: gridComputedData$,
|
|
149
|
+
}).pipe(
|
|
150
|
+
shareReplay(1)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
isSeriesPositionSeprate$,
|
|
156
|
+
gridContainer$,
|
|
157
|
+
gridAxesTransform$,
|
|
158
|
+
gridAxesReverseTransform$,
|
|
159
|
+
gridGraphicTransform$,
|
|
160
|
+
gridGraphicReverseScale$,
|
|
161
|
+
gridAxesSize$,
|
|
162
|
+
gridHighlight$,
|
|
163
|
+
existedSeriesLabels$,
|
|
164
|
+
SeriesDataMap$,
|
|
165
|
+
GroupDataMap$,
|
|
166
|
+
visibleComputedData$,
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
53
170
|
const destroy$ = new Subject()
|
|
54
171
|
|
|
55
172
|
return combineLatest({
|
|
@@ -57,19 +174,29 @@ export const multiGridEachDetailObservable = ({ fullDataFormatter$, computedData
|
|
|
57
174
|
computedData: computedData$,
|
|
58
175
|
}).pipe(
|
|
59
176
|
switchMap(async (d) => d),
|
|
60
|
-
distinctUntilChanged((a, b) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}),
|
|
177
|
+
// distinctUntilChanged((a, b) => {
|
|
178
|
+
// // 只有當computedData的長度改變時,才重新計算
|
|
179
|
+
// return a.computedData.length === b.computedData.length
|
|
180
|
+
// }),
|
|
64
181
|
map(data => {
|
|
65
182
|
// 每次重新計算時,清除之前的訂閱
|
|
66
183
|
destroy$.next(undefined)
|
|
67
184
|
|
|
185
|
+
const defaultGrid = data.fullDataFormatter.gridList[0] ?? DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT
|
|
186
|
+
|
|
68
187
|
return data.computedData.map((gridComputedData, gridIndex) => {
|
|
69
188
|
|
|
70
189
|
// -- 取得該grid的data和dataFormatter
|
|
71
|
-
const
|
|
72
|
-
|
|
190
|
+
const grid = data.fullDataFormatter.gridList[gridIndex] ?? defaultGrid
|
|
191
|
+
const gridDataFormatter: DataFormatterGrid = {
|
|
192
|
+
type: 'grid',
|
|
193
|
+
grid: {
|
|
194
|
+
...grid
|
|
195
|
+
},
|
|
196
|
+
container: {
|
|
197
|
+
...data.fullDataFormatter.container
|
|
198
|
+
}
|
|
199
|
+
}
|
|
73
200
|
const gridDataFormatter$ = of(gridDataFormatter).pipe(
|
|
74
201
|
takeUntil(destroy$),
|
|
75
202
|
shareReplay(1)
|
|
@@ -80,104 +207,26 @@ export const multiGridEachDetailObservable = ({ fullDataFormatter$, computedData
|
|
|
80
207
|
)
|
|
81
208
|
|
|
82
209
|
// -- 建立Observables --
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const gridGraphicTransform$ = gridGraphicTransformObservable({
|
|
91
|
-
computedData$: gridComputedData$,
|
|
92
|
-
fullDataFormatter$: gridDataFormatter$,
|
|
93
|
-
layout$: layout$
|
|
94
|
-
}).pipe(
|
|
95
|
-
shareReplay(1)
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
const gridAxesOppositeTransform$ = gridAxesOppositeTransformObservable({
|
|
99
|
-
gridAxesTransform$
|
|
100
|
-
}).pipe(
|
|
101
|
-
shareReplay(1)
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
const gridAxesSize$ = gridAxesSizeObservable({
|
|
105
|
-
fullDataFormatter$: gridDataFormatter$,
|
|
106
|
-
layout$: layout$
|
|
107
|
-
}).pipe(
|
|
108
|
-
shareReplay(1)
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
const datumList$ = gridComputedData$.pipe(
|
|
112
|
-
map(d => d.flat())
|
|
113
|
-
).pipe(
|
|
114
|
-
shareReplay(1)
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
const gridHighlight$ = highlightObservable({
|
|
118
|
-
datumList$,
|
|
119
|
-
fullChartParams$: fullChartParams$,
|
|
120
|
-
event$: event$
|
|
121
|
-
}).pipe(
|
|
122
|
-
shareReplay(1)
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
const SeriesDataMap$ = seriesDataMapObservable({
|
|
126
|
-
datumList$: datumList$
|
|
127
|
-
}).pipe(
|
|
128
|
-
shareReplay(1)
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
const GroupDataMap$ = groupDataMapObservable({
|
|
132
|
-
datumList$: datumList$
|
|
133
|
-
}).pipe(
|
|
134
|
-
shareReplay(1)
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
const visibleComputedData$ = gridVisibleComputedDataObservable({
|
|
138
|
-
computedData$: gridComputedData$,
|
|
139
|
-
}).pipe(
|
|
140
|
-
shareReplay(1)
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
gridAxesTransform$,
|
|
145
|
-
gridGraphicTransform$,
|
|
146
|
-
gridAxesOppositeTransform$,
|
|
147
|
-
gridAxesSize$,
|
|
148
|
-
gridHighlight$,
|
|
149
|
-
SeriesDataMap$,
|
|
150
|
-
GroupDataMap$,
|
|
151
|
-
visibleComputedData$
|
|
152
|
-
}
|
|
210
|
+
return detailObservables ({
|
|
211
|
+
gridDataFormatter$,
|
|
212
|
+
gridComputedData$,
|
|
213
|
+
layout$,
|
|
214
|
+
fullChartParams$,
|
|
215
|
+
event$
|
|
216
|
+
})
|
|
153
217
|
})
|
|
154
218
|
})
|
|
155
219
|
)
|
|
156
220
|
}
|
|
157
221
|
|
|
158
222
|
|
|
159
|
-
|
|
160
|
-
// 每一個grid的container位置
|
|
223
|
+
// 所有container位置(對應series)
|
|
161
224
|
export const multiGridContainerObservable = ({ computedData$, fullDataFormatter$, fullChartParams$, layout$ }: {
|
|
162
225
|
computedData$: Observable<ComputedDataTypeMap<'multiGrid'>>
|
|
163
226
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'multiGrid'>>
|
|
164
227
|
fullChartParams$: Observable<ChartParams>
|
|
165
228
|
layout$: Observable<Layout>
|
|
166
229
|
}) => {
|
|
167
|
-
function calcBox (layout: Layout, container: DataFormatterMultiGridContainer, rowIndex: number, columnIndex: number) {
|
|
168
|
-
const { gap, rowAmount, columnAmount } = container
|
|
169
|
-
const width = (layout.width - (gap * (columnAmount - 1))) / columnAmount
|
|
170
|
-
const height = (layout.height - (gap * (rowAmount - 1))) / rowAmount
|
|
171
|
-
const x = columnIndex * width + (columnIndex * gap)
|
|
172
|
-
const y = rowIndex * height + (rowIndex * gap)
|
|
173
|
-
const translate: [number, number] = [x, y]
|
|
174
|
-
const scale: [number, number] = [width / layout.width, height / layout.height]
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
translate,
|
|
178
|
-
scale
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
230
|
|
|
182
231
|
const multiGridContainer$ = combineLatest({
|
|
183
232
|
computedData: computedData$,
|
|
@@ -188,21 +237,46 @@ export const multiGridContainerObservable = ({ computedData$, fullDataFormatter$
|
|
|
188
237
|
switchMap(async (d) => d),
|
|
189
238
|
map(data => {
|
|
190
239
|
|
|
191
|
-
const defaultGrid = data.fullDataFormatter.
|
|
240
|
+
const defaultGrid = data.fullDataFormatter.gridList[0] ?? DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT
|
|
192
241
|
|
|
193
242
|
const boxArr = data.computedData.map((gridData, gridIndex) => {
|
|
194
|
-
const grid = data.fullDataFormatter.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
243
|
+
const grid = data.fullDataFormatter.gridList[gridIndex] ?? defaultGrid
|
|
244
|
+
|
|
245
|
+
// 有設定series定位
|
|
246
|
+
const hasSeriesPosition = grid.seriesSlotIndexes && grid.seriesSlotIndexes.length === gridData.length
|
|
247
|
+
? true
|
|
248
|
+
: false
|
|
249
|
+
|
|
250
|
+
if (hasSeriesPosition) {
|
|
251
|
+
// -- 依seriesSlotIndexes計算 --
|
|
252
|
+
return gridData.map((seriesData, seriesIndex) => {
|
|
253
|
+
const columnIndex = grid.seriesSlotIndexes[seriesIndex] % data.fullDataFormatter.container.columnAmount
|
|
254
|
+
const rowIndex = Math.floor(grid.seriesSlotIndexes[seriesIndex] / data.fullDataFormatter.container.columnAmount)
|
|
255
|
+
const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
|
256
|
+
return {
|
|
257
|
+
slotIndex: grid.seriesSlotIndexes[seriesIndex],
|
|
258
|
+
rowIndex,
|
|
259
|
+
columnIndex,
|
|
260
|
+
translate,
|
|
261
|
+
scale,
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
} else {
|
|
265
|
+
// -- 依grid的slotIndex計算 --
|
|
266
|
+
const columnIndex = grid.slotIndex % data.fullDataFormatter.container.columnAmount
|
|
267
|
+
const rowIndex = Math.floor(grid.slotIndex / data.fullDataFormatter.container.columnAmount)
|
|
268
|
+
return gridData.map((seriesData, seriesIndex) => {
|
|
269
|
+
const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
|
270
|
+
return {
|
|
271
|
+
slotIndex: grid.slotIndex,
|
|
272
|
+
rowIndex,
|
|
273
|
+
columnIndex,
|
|
274
|
+
translate,
|
|
275
|
+
scale,
|
|
276
|
+
}
|
|
277
|
+
})
|
|
205
278
|
}
|
|
279
|
+
|
|
206
280
|
})
|
|
207
281
|
return boxArr
|
|
208
282
|
}),
|