@orbcharts/core 3.0.0-alpha.42 → 3.0.0-alpha.44
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 +1905 -1896
- package/dist/orbcharts-core.umd.js +2 -2
- package/dist/src/defaults.d.ts +4 -3
- package/dist/src/grid/computeGridData.d.ts +4 -11
- package/dist/src/grid/gridObservables.d.ts +15 -18
- package/dist/src/multiGrid/multiGridObservables.d.ts +4 -11
- package/dist/src/series/seriesObservables.d.ts +26 -1
- package/dist/src/types/ComputedData.d.ts +1 -0
- package/dist/src/types/ComputedDataGrid.d.ts +0 -3
- package/dist/src/types/ComputedDataSeries.d.ts +1 -2
- package/dist/src/types/ContextObserverGrid.d.ts +11 -4
- package/dist/src/types/ContextObserverMultiGrid.d.ts +8 -3
- package/dist/src/types/ContextObserverSeries.d.ts +18 -0
- package/dist/src/types/DataFormatter.d.ts +8 -5
- package/dist/src/types/DataFormatterGrid.d.ts +13 -16
- package/dist/src/types/DataFormatterMultiGrid.d.ts +6 -3
- package/dist/src/types/DataFormatterMultiValue.d.ts +3 -0
- package/dist/src/types/DataFormatterRelationship.d.ts +3 -0
- package/dist/src/types/DataFormatterSeries.d.ts +11 -4
- package/dist/src/utils/orbchartsUtils.d.ts +14 -13
- package/package.json +1 -1
- package/src/base/createBaseChart.ts +10 -10
- package/src/defaults.ts +36 -64
- package/src/grid/computeGridData.ts +15 -86
- package/src/grid/createGridContextObserver.ts +33 -16
- package/src/grid/gridObservables.ts +157 -70
- package/src/multiGrid/computeMultiGridData.ts +77 -120
- package/src/multiGrid/createMultiGridContextObserver.ts +8 -8
- package/src/multiGrid/multiGridObservables.ts +236 -171
- package/src/multiValue/computeMultiValueData.ts +22 -15
- package/src/relationship/computeRelationshipData.ts +16 -4
- package/src/series/computeSeriesData.ts +51 -114
- package/src/series/createSeriesContextObserver.ts +59 -4
- package/src/series/seriesObservables.ts +162 -10
- package/src/tree/computeTreeData.ts +6 -3
- package/src/types/ComputedData.ts +1 -0
- package/src/types/ComputedDataGrid.ts +3 -3
- package/src/types/ComputedDataSeries.ts +2 -2
- package/src/types/ContextObserverGrid.ts +18 -10
- package/src/types/ContextObserverMultiGrid.ts +6 -18
- package/src/types/ContextObserverSeries.ts +21 -1
- package/src/types/DataFormatter.ts +11 -32
- package/src/types/DataFormatterGrid.ts +32 -20
- package/src/types/DataFormatterMultiGrid.ts +6 -4
- package/src/types/DataFormatterMultiValue.ts +3 -0
- package/src/types/DataFormatterRelationship.ts +3 -0
- package/src/types/DataFormatterSeries.ts +11 -21
- package/src/utils/d3Utils.ts +7 -7
- package/src/utils/orbchartsUtils.ts +128 -32
|
@@ -1,149 +1,86 @@
|
|
|
1
1
|
import type { DataSeries, DataSeriesDatum } from '../types/DataSeries'
|
|
2
2
|
import type { ComputedDataFn } from '../types/ComputedData'
|
|
3
|
-
import type {
|
|
3
|
+
import type { ComputedDatumSeries } from '../types/ComputedDataSeries'
|
|
4
4
|
import { formatValueToLabel, createDefaultDatumId, createDefaultSeriesLabel, seriesColorPredicate } from '../utils/orbchartsUtils'
|
|
5
5
|
|
|
6
|
-
interface SortValue {
|
|
7
|
-
rowIndex: number
|
|
8
|
-
columnIndex: number
|
|
9
|
-
index: number
|
|
10
|
-
datum: number | DataSeriesDatum
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
type GetSortedIndex = (computedDataSeries: ComputedDatumSeries[], rowIndex: number, columnIndex: number) => number
|
|
14
|
-
|
|
15
|
-
function createSortedIndexMap (data: DataSeries, sort: (a: number | DataSeriesDatum, b: number | DataSeriesDatum) => number): Map<string, number> {
|
|
16
|
-
|
|
17
|
-
const SortedIndexMap: Map<string, number> = new Map() // Map<[rowIndex, columnIndex], sortedIndex>
|
|
18
|
-
|
|
19
|
-
let _data = Object.assign([], data) as DataSeries
|
|
20
|
-
// 建立排序所需資料的物件
|
|
21
|
-
let sortValueData: SortValue[] = []
|
|
22
|
-
_data.forEach((d, i) => {
|
|
23
|
-
if (Array.isArray(d)) {
|
|
24
|
-
d.forEach((_d, _i) => {
|
|
25
|
-
sortValueData.push({
|
|
26
|
-
rowIndex: i,
|
|
27
|
-
columnIndex: _i,
|
|
28
|
-
index: -1,
|
|
29
|
-
datum: _d
|
|
30
|
-
})
|
|
31
|
-
})
|
|
32
|
-
} else {
|
|
33
|
-
sortValueData.push({
|
|
34
|
-
rowIndex: i,
|
|
35
|
-
columnIndex: 0,
|
|
36
|
-
index: -1,
|
|
37
|
-
datum: d
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
// 排序
|
|
42
|
-
sortValueData.sort((a, b) => sort(a.datum, b.datum))
|
|
43
|
-
// 取得排序後的index
|
|
44
|
-
sortValueData = sortValueData.map((d, i) => {
|
|
45
|
-
return {
|
|
46
|
-
...d,
|
|
47
|
-
index: i
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
// 建立SortedIndexMap
|
|
51
|
-
sortValueData.forEach(d => {
|
|
52
|
-
SortedIndexMap.set(String([d.rowIndex, d.columnIndex]), d.index)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
return SortedIndexMap
|
|
56
|
-
}
|
|
57
|
-
|
|
58
6
|
export const computeSeriesData: ComputedDataFn<'series'> = (context) => {
|
|
59
7
|
const { data = [], dataFormatter, chartParams } = context
|
|
60
8
|
if (!data.length) {
|
|
61
9
|
return []
|
|
62
10
|
}
|
|
63
11
|
|
|
64
|
-
|
|
12
|
+
let computedDataSeries: ComputedDatumSeries[][] = []
|
|
65
13
|
|
|
66
14
|
try {
|
|
67
|
-
// 取得排序後的索引
|
|
68
|
-
const getSortedIndex: GetSortedIndex = ((hasSort: boolean) => {
|
|
69
|
-
if (hasSort) {
|
|
70
|
-
// 資料索引對應排序後的索引 Map<[rowIndex, columnIndex], sortedIndex>
|
|
71
|
-
const SortedIndexMap: Map<string, number> = createSortedIndexMap(data, dataFormatter.sort)
|
|
72
|
-
return (computedDataSeries: ComputedDatumSeries[], rowIndex: number, columnIndex: number) => {
|
|
73
|
-
return SortedIndexMap.get(String([rowIndex, columnIndex]))
|
|
74
|
-
}
|
|
75
|
-
} else {
|
|
76
|
-
return (computedDataSeries: ComputedDatumSeries[], rowIndex: number, columnIndex: number) => {
|
|
77
|
-
return computedDataSeries.length
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
})(dataFormatter.sort != null)
|
|
81
|
-
|
|
82
|
-
// 資料索引對應排序後的索引 Map<[rowIndex, columnIndex], sortedIndex>
|
|
83
|
-
// let SortedIndexMap: Map<string, number> = new Map()
|
|
84
|
-
// if (dataFormatter.sort) {
|
|
85
|
-
// SortedIndexMap = createSortedIndexMap(data, dataFormatter.sort)
|
|
86
|
-
// }
|
|
87
15
|
|
|
88
|
-
const createComputedDatumSeries = (
|
|
89
|
-
const defaultId = createDefaultDatumId(dataFormatter.type,
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
const color = seriesColorPredicate(rowIndex, chartParams)
|
|
94
|
-
const visible = dataFormatter.visibleFilter(detailData, rowIndex, columnIndex, context)
|
|
95
|
-
if (typeof detailData === 'number') {
|
|
16
|
+
const createComputedDatumSeries = (seriesData: number | DataSeriesDatum, seriesIndex: number, itemIndex: number, currentIndex: number): ComputedDatumSeries => {
|
|
17
|
+
const defaultId = createDefaultDatumId(dataFormatter.type, seriesIndex, itemIndex)
|
|
18
|
+
const seriesLabel = dataFormatter.seriesLabels[seriesIndex] || createDefaultSeriesLabel('series', seriesIndex)
|
|
19
|
+
const color = seriesColorPredicate(seriesIndex, chartParams)
|
|
20
|
+
if (typeof seriesData === 'number') {
|
|
96
21
|
return {
|
|
97
22
|
id: defaultId,
|
|
98
23
|
index: currentIndex,
|
|
99
|
-
|
|
24
|
+
seq: 0, // 先給預設值
|
|
100
25
|
label: defaultId,
|
|
101
26
|
description: '',
|
|
102
|
-
// tooltipContent: dataFormatter.tooltipContentFormat(detailData, rowIndex, columnIndex, context),
|
|
103
27
|
data: {},
|
|
104
|
-
value:
|
|
105
|
-
|
|
106
|
-
seriesIndex: rowIndex,
|
|
28
|
+
value: seriesData,
|
|
29
|
+
seriesIndex: seriesIndex,
|
|
107
30
|
seriesLabel,
|
|
108
31
|
color,
|
|
109
|
-
visible
|
|
32
|
+
visible: true // 先給預設值
|
|
110
33
|
}
|
|
111
34
|
} else {
|
|
112
35
|
return {
|
|
113
|
-
id:
|
|
36
|
+
id: seriesData.id ? seriesData.id : defaultId,
|
|
114
37
|
index: currentIndex,
|
|
115
|
-
|
|
116
|
-
label:
|
|
117
|
-
description:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// valueLabel: formatValueToLabel(detailData.value, dataFormatter.valueFormat),
|
|
122
|
-
seriesIndex: rowIndex,
|
|
38
|
+
seq: 0, // 先給預設值
|
|
39
|
+
label: seriesData.label ? seriesData.label : defaultId,
|
|
40
|
+
description: seriesData.description,
|
|
41
|
+
data: seriesData.data ?? {},
|
|
42
|
+
value: seriesData.value,
|
|
43
|
+
seriesIndex: seriesIndex,
|
|
123
44
|
seriesLabel,
|
|
124
45
|
color,
|
|
125
|
-
visible
|
|
46
|
+
visible: true // 先給預設值
|
|
126
47
|
}
|
|
127
48
|
}
|
|
128
49
|
}
|
|
129
50
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
51
|
+
computedDataSeries = data
|
|
52
|
+
.map((seriesData, seriesIndex) => {
|
|
53
|
+
if (Array.isArray(seriesData)) {
|
|
54
|
+
return seriesData.map((item, itemIndex) =>
|
|
55
|
+
createComputedDatumSeries(item, seriesIndex, itemIndex, computedDataSeries.length + itemIndex)
|
|
56
|
+
)
|
|
57
|
+
} else {
|
|
58
|
+
return createComputedDatumSeries(seriesData, seriesIndex, 0, computedDataSeries.length)
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
// 攤為一維陣列
|
|
62
|
+
.flat()
|
|
63
|
+
// 排序後給 seq
|
|
64
|
+
.sort(dataFormatter.sort ?? undefined)
|
|
65
|
+
.map((datum, index) => {
|
|
66
|
+
datum.seq = index
|
|
67
|
+
return datum
|
|
68
|
+
})
|
|
69
|
+
.map(datum => {
|
|
70
|
+
datum.visible = dataFormatter.visibleFilter(datum, context)
|
|
71
|
+
return datum
|
|
72
|
+
})
|
|
73
|
+
// 恢復原排序
|
|
74
|
+
.sort((a, b) => a.index - b.index)
|
|
75
|
+
// 依seriesIndex分組(二維陣列)
|
|
76
|
+
.reduce((acc, datum) => {
|
|
77
|
+
if (!acc[datum.seriesIndex]) {
|
|
78
|
+
acc[datum.seriesIndex] = []
|
|
79
|
+
}
|
|
80
|
+
acc[datum.seriesIndex].push(datum)
|
|
81
|
+
return acc
|
|
82
|
+
}, [])
|
|
143
83
|
|
|
144
|
-
// if (dataFormatter.sort != null) {
|
|
145
|
-
// computedDataSeries.sort((a, b) => a.sortedIndex - b.sortedIndex)
|
|
146
|
-
// }
|
|
147
84
|
} catch (e) {
|
|
148
85
|
// console.error(e)
|
|
149
86
|
throw Error(e)
|
|
@@ -1,26 +1,74 @@
|
|
|
1
|
-
import { shareReplay } from 'rxjs'
|
|
1
|
+
import { map, shareReplay } from 'rxjs'
|
|
2
2
|
import type { ContextObserverFn } from '../types'
|
|
3
3
|
import {
|
|
4
4
|
seriesDataMapObservable,
|
|
5
5
|
groupDataMapObservable } from '../utils/observables'
|
|
6
6
|
import { highlightObservable, textSizePxObservable } from '../utils/observables'
|
|
7
7
|
|
|
8
|
+
import { separateSeriesObservable, visibleComputedDataObservable, computedLayoutDataObservable, seriesLabelsObservable, seriesContainerPositionObservable, seriesContainerPositionMapObservable } from './seriesObservables'
|
|
9
|
+
|
|
8
10
|
export const createSeriesContextObserver: ContextObserverFn<'series'> = ({ subject, observer }) => {
|
|
9
11
|
|
|
10
12
|
const textSizePx$ = textSizePxObservable(observer.fullChartParams$).pipe(
|
|
11
13
|
shareReplay(1)
|
|
12
14
|
)
|
|
13
15
|
|
|
16
|
+
const separateSeries$ = separateSeriesObservable({
|
|
17
|
+
fullDataFormatter$: observer.fullDataFormatter$
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const visibleComputedData$ = visibleComputedDataObservable({
|
|
21
|
+
computedData$: observer.computedData$,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const computedLayoutData$ = computedLayoutDataObservable({
|
|
25
|
+
computedData$: observer.computedData$,
|
|
26
|
+
fullDataFormatter$: observer.fullDataFormatter$
|
|
27
|
+
}).pipe(
|
|
28
|
+
shareReplay(1)
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
const visibleComputedLayoutData$ = visibleComputedDataObservable({
|
|
32
|
+
computedData$: computedLayoutData$,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const datumList$ = observer.computedData$.pipe(
|
|
36
|
+
map(d => d.flat())
|
|
37
|
+
).pipe(
|
|
38
|
+
shareReplay(1)
|
|
39
|
+
)
|
|
40
|
+
|
|
14
41
|
const seriesHighlight$ = highlightObservable({
|
|
15
|
-
datumList
|
|
42
|
+
datumList$,
|
|
16
43
|
fullChartParams$: observer.fullChartParams$,
|
|
17
44
|
event$: subject.event$
|
|
18
45
|
}).pipe(
|
|
19
46
|
shareReplay(1)
|
|
20
47
|
)
|
|
21
48
|
|
|
49
|
+
const seriesLabels$ = seriesLabelsObservable({
|
|
50
|
+
computedData$: observer.computedData$,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
|
|
22
54
|
const SeriesDataMap$ = seriesDataMapObservable({
|
|
23
|
-
datumList
|
|
55
|
+
datumList$
|
|
56
|
+
}).pipe(
|
|
57
|
+
shareReplay(1)
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
const seriesContainerPosition$ = seriesContainerPositionObservable({
|
|
61
|
+
computedData$: observer.computedData$,
|
|
62
|
+
fullDataFormatter$: observer.fullDataFormatter$,
|
|
63
|
+
layout$: observer.layout$,
|
|
64
|
+
}).pipe(
|
|
65
|
+
shareReplay(1)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
const SeriesContainerPositionMap$ = seriesContainerPositionMapObservable({
|
|
69
|
+
seriesContainerPosition$: seriesContainerPosition$,
|
|
70
|
+
seriesLabels$: seriesLabels$,
|
|
71
|
+
separateSeries$: separateSeries$,
|
|
24
72
|
}).pipe(
|
|
25
73
|
shareReplay(1)
|
|
26
74
|
)
|
|
@@ -32,7 +80,14 @@ export const createSeriesContextObserver: ContextObserverFn<'series'> = ({ subje
|
|
|
32
80
|
computedData$: observer.computedData$,
|
|
33
81
|
layout$: observer.layout$,
|
|
34
82
|
textSizePx$,
|
|
83
|
+
visibleComputedData$,
|
|
84
|
+
visibleComputedLayoutData$,
|
|
85
|
+
separateSeries$,
|
|
86
|
+
computedLayoutData$,
|
|
35
87
|
seriesHighlight$,
|
|
36
|
-
|
|
88
|
+
seriesLabels$,
|
|
89
|
+
SeriesDataMap$,
|
|
90
|
+
seriesContainerPosition$,
|
|
91
|
+
SeriesContainerPositionMap$,
|
|
37
92
|
}
|
|
38
93
|
}
|
|
@@ -12,13 +12,165 @@ import {
|
|
|
12
12
|
import type {
|
|
13
13
|
ChartParams,
|
|
14
14
|
ComputedDatumSeries,
|
|
15
|
-
ComputedDataTypeMap
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
ComputedDataTypeMap,
|
|
16
|
+
DataFormatterTypeMap,
|
|
17
|
+
SeriesContainerPosition,
|
|
18
|
+
Layout } from '../types'
|
|
19
|
+
import { calcSeriesContainerLayout } from '../utils/orbchartsUtils'
|
|
20
|
+
|
|
21
|
+
export const separateSeriesObservable = ({ fullDataFormatter$ }: { fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>> }) => {
|
|
22
|
+
return fullDataFormatter$.pipe(
|
|
23
|
+
map(data => data.separateSeries),
|
|
24
|
+
distinctUntilChanged(),
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const seriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
|
|
29
|
+
return computedData$.pipe(
|
|
30
|
+
map(data => {
|
|
31
|
+
return data
|
|
32
|
+
.filter(series => series.length)
|
|
33
|
+
.map(series => {
|
|
34
|
+
return series[0].seriesLabel
|
|
35
|
+
})
|
|
36
|
+
}),
|
|
37
|
+
distinctUntilChanged((a, b) => {
|
|
38
|
+
return JSON.stringify(a).length === JSON.stringify(b).length
|
|
39
|
+
}),
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const visibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'series'>> }) => {
|
|
44
|
+
return computedData$.pipe(
|
|
45
|
+
map(data => {
|
|
46
|
+
return data.map(series => {
|
|
47
|
+
return series.filter(datum => datum.visible != false)
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const computedLayoutDataObservable = ({ computedData$, fullDataFormatter$ }: {
|
|
54
|
+
computedData$: Observable<ComputedDataTypeMap<'series'>>,
|
|
55
|
+
fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
|
|
56
|
+
}) => {
|
|
57
|
+
return combineLatest({
|
|
58
|
+
computedData: computedData$,
|
|
59
|
+
fullDataFormatter: fullDataFormatter$
|
|
60
|
+
}).pipe(
|
|
61
|
+
switchMap(async (d) => d),
|
|
62
|
+
map(data => {
|
|
63
|
+
const sumData: ComputedDatumSeries[][] = data.fullDataFormatter.sumSeries == true
|
|
64
|
+
? data.computedData.map(d => {
|
|
65
|
+
return [
|
|
66
|
+
// 加總為一筆資料
|
|
67
|
+
d.reduce((acc, current) => {
|
|
68
|
+
if (acc == null) {
|
|
69
|
+
return current // 取得第一筆資料
|
|
70
|
+
}
|
|
71
|
+
acc.value = acc.value + current.value
|
|
72
|
+
return acc
|
|
73
|
+
}, null)
|
|
74
|
+
]
|
|
75
|
+
})
|
|
76
|
+
: data.computedData
|
|
77
|
+
|
|
78
|
+
return data.fullDataFormatter.separateSeries == true
|
|
79
|
+
// 有拆分的話每個series為一組
|
|
80
|
+
? sumData
|
|
81
|
+
.map(series => {
|
|
82
|
+
return series.sort((a, b) => a.seq - b.seq)
|
|
83
|
+
})
|
|
84
|
+
// 無拆分的話所有資料為一組
|
|
85
|
+
: [
|
|
86
|
+
sumData
|
|
87
|
+
.flat()
|
|
88
|
+
.sort((a, b) => a.seq - b.seq)
|
|
89
|
+
]
|
|
90
|
+
})
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
// 所有container位置(對應series)
|
|
96
|
+
export const seriesContainerPositionObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
|
|
97
|
+
computedData$: Observable<ComputedDataTypeMap<'series'>>
|
|
98
|
+
fullDataFormatter$: Observable<DataFormatterTypeMap<'series'>>
|
|
99
|
+
layout$: Observable<Layout>
|
|
100
|
+
}): Observable<SeriesContainerPosition[]> => {
|
|
101
|
+
|
|
102
|
+
const gridContainerPosition$ = combineLatest({
|
|
103
|
+
computedData: computedData$,
|
|
104
|
+
fullDataFormatter: fullDataFormatter$,
|
|
105
|
+
layout: layout$,
|
|
106
|
+
}).pipe(
|
|
107
|
+
switchMap(async (d) => d),
|
|
108
|
+
map(data => {
|
|
109
|
+
|
|
110
|
+
if (data.fullDataFormatter.separateSeries) {
|
|
111
|
+
// -- 依slotIndexes計算 --
|
|
112
|
+
return calcSeriesContainerLayout(data.layout, data.fullDataFormatter.container, data.computedData.length)
|
|
113
|
+
// return data.computedData.map((seriesData, seriesIndex) => {
|
|
114
|
+
// const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
|
|
115
|
+
// const rowIndex = Math.floor(seriesIndex / data.fullDataFormatter.container.columnAmount)
|
|
116
|
+
// const { startX, startY, centerX, centerY, width, height } = calcSeriesContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
|
117
|
+
// return {
|
|
118
|
+
// slotIndex: seriesIndex,
|
|
119
|
+
// rowIndex,
|
|
120
|
+
// columnIndex,
|
|
121
|
+
// startX,
|
|
122
|
+
// startY,
|
|
123
|
+
// centerX,
|
|
124
|
+
// centerY,
|
|
125
|
+
// width,
|
|
126
|
+
// height,
|
|
127
|
+
// }
|
|
128
|
+
// })
|
|
129
|
+
} else {
|
|
130
|
+
// -- 無拆分 --
|
|
131
|
+
return calcSeriesContainerLayout(data.layout, data.fullDataFormatter.container, 1)
|
|
132
|
+
// const columnIndex = 0
|
|
133
|
+
// const rowIndex = 0
|
|
134
|
+
// return data.computedData.map((seriesData, seriesIndex) => {
|
|
135
|
+
// const { startX, startY, centerX, centerY, width, height } = calcSeriesContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
|
136
|
+
// return {
|
|
137
|
+
// slotIndex: 0,
|
|
138
|
+
// rowIndex,
|
|
139
|
+
// columnIndex,
|
|
140
|
+
// startX,
|
|
141
|
+
// startY,
|
|
142
|
+
// centerX,
|
|
143
|
+
// centerY,
|
|
144
|
+
// width,
|
|
145
|
+
// height,
|
|
146
|
+
// }
|
|
147
|
+
// })
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
return gridContainerPosition$
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export const seriesContainerPositionMapObservable = ({ seriesContainerPosition$, seriesLabels$, separateSeries$ }: {
|
|
156
|
+
seriesContainerPosition$: Observable<SeriesContainerPosition[]>
|
|
157
|
+
seriesLabels$: Observable<string[]>
|
|
158
|
+
separateSeries$: Observable<boolean>
|
|
159
|
+
}) => {
|
|
160
|
+
return combineLatest({
|
|
161
|
+
seriesContainerPosition: seriesContainerPosition$,
|
|
162
|
+
seriesLabels: seriesLabels$,
|
|
163
|
+
separateSeries: separateSeries$,
|
|
164
|
+
}).pipe(
|
|
165
|
+
switchMap(async (d) => d),
|
|
166
|
+
map(data => {
|
|
167
|
+
return data.separateSeries
|
|
168
|
+
? new Map<string, SeriesContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
|
|
169
|
+
return [seriesLabel, data.seriesContainerPosition[seriesIndex] ?? data.seriesContainerPosition[0]]
|
|
170
|
+
}))
|
|
171
|
+
: new Map<string, SeriesContainerPosition>(data.seriesLabels.map((seriesLabel, seriesIndex) => {
|
|
172
|
+
return [seriesLabel, data.seriesContainerPosition[0]]
|
|
173
|
+
}))
|
|
174
|
+
})
|
|
175
|
+
)
|
|
176
|
+
}
|
|
@@ -85,7 +85,6 @@ export const computeTreeData: ComputedDataFn<'tree'> = (context) => {
|
|
|
85
85
|
|
|
86
86
|
const formatBranchData = (branch: DataTreeObj, level: number, seq: number): ComputedDataTree => {
|
|
87
87
|
const childLayer = level + 1
|
|
88
|
-
const visible = dataFormatter.visibleFilter(branch, level, seq, context)
|
|
89
88
|
const categoryLabel: string | null = branch.categoryLabel ?? null
|
|
90
89
|
let categoryIndex = 0
|
|
91
90
|
if (categoryLabel != null) {
|
|
@@ -97,7 +96,7 @@ export const computeTreeData: ComputedDataFn<'tree'> = (context) => {
|
|
|
97
96
|
|
|
98
97
|
const currentIndex = index
|
|
99
98
|
index++
|
|
100
|
-
|
|
99
|
+
const formattedBranchData: ComputedDataTree = {
|
|
101
100
|
id: branch.id,
|
|
102
101
|
index: currentIndex,
|
|
103
102
|
level,
|
|
@@ -110,12 +109,16 @@ export const computeTreeData: ComputedDataFn<'tree'> = (context) => {
|
|
|
110
109
|
data: branch.data ?? {},
|
|
111
110
|
// tooltipContent: branch.tooltipContent ? branch.tooltipContent : dataFormatter.tooltipContentFormat(branch, level, seq, context),
|
|
112
111
|
value: branch.value,
|
|
113
|
-
visible,
|
|
112
|
+
visible: true, // 先給預設值
|
|
114
113
|
children: (branch.children ?? []).map((d, i) => {
|
|
115
114
|
// 遞迴
|
|
116
115
|
return formatBranchData(d, childLayer, i)
|
|
117
116
|
})
|
|
118
117
|
}
|
|
118
|
+
|
|
119
|
+
formattedBranchData.visible = dataFormatter.visibleFilter(formattedBranchData, context)
|
|
120
|
+
|
|
121
|
+
return formattedBranchData
|
|
119
122
|
}
|
|
120
123
|
computedBranchData = formatBranchData(dataTreeObj, 0, 0)
|
|
121
124
|
} catch (e) {
|
|
@@ -6,9 +6,9 @@ export interface ComputedDatumGrid
|
|
|
6
6
|
// gridIndex: number
|
|
7
7
|
// groupIndex: number
|
|
8
8
|
// groupLabel: string
|
|
9
|
-
axisX: number
|
|
10
|
-
axisY: number
|
|
11
|
-
axisYFromZero: number
|
|
9
|
+
// axisX: number
|
|
10
|
+
// axisY: number
|
|
11
|
+
// axisYFromZero: number
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export type ComputedDataGrid = ComputedDatumGrid[][]
|
|
@@ -2,7 +2,7 @@ import { ComputedDatumBase, ComputedDatumSeriesValue } from './ComputedData'
|
|
|
2
2
|
|
|
3
3
|
export interface ComputedDatumSeries
|
|
4
4
|
extends ComputedDatumBase, ComputedDatumSeriesValue {
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export type ComputedDataSeries = ComputedDatumSeries[]
|
|
8
|
+
export type ComputedDataSeries = ComputedDatumSeries[][]
|
|
@@ -3,29 +3,37 @@ import type { ContextObserverBase } from './ContextObserver'
|
|
|
3
3
|
import type { ComputedDataGrid, ComputedDatumGrid } from './ComputedDataGrid'
|
|
4
4
|
import type { TransformData } from './TransformData'
|
|
5
5
|
|
|
6
|
-
export interface ContextObserverGrid<PluginParams>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
textSizePx$: Observable<number>
|
|
11
|
-
}
|
|
6
|
+
export interface ContextObserverGrid<PluginParams> extends
|
|
7
|
+
ContextObserverBase<'grid', PluginParams>, ContextObserverGridDetail {
|
|
8
|
+
textSizePx$: Observable<number>
|
|
9
|
+
}
|
|
12
10
|
|
|
13
11
|
export interface ContextObserverGridDetail {
|
|
14
|
-
|
|
12
|
+
gridContainerPosition$: Observable<GridContainerPosition[]>
|
|
15
13
|
gridAxesTransform$: Observable<TransformData>
|
|
16
14
|
gridAxesReverseTransform$: Observable<TransformData>
|
|
17
15
|
gridGraphicTransform$: Observable<TransformData>
|
|
18
16
|
gridGraphicReverseScale$: Observable<[number, number][]>
|
|
19
17
|
gridAxesSize$: Observable<{ width: number; height: number; }>
|
|
20
18
|
gridHighlight$: Observable<ComputedDatumGrid[]>
|
|
21
|
-
|
|
19
|
+
seriesLabels$: Observable<string[]>
|
|
22
20
|
SeriesDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
|
|
23
21
|
GroupDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
|
|
22
|
+
computedLayoutData$: Observable<ComputedLayoutDataGrid>
|
|
24
23
|
visibleComputedData$: Observable<ComputedDataGrid>
|
|
25
|
-
|
|
24
|
+
visibleComputedLayoutData$: Observable<ComputedLayoutDataGrid>
|
|
25
|
+
// isSeriesSeprate$: Observable<boolean>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ComputedLayoutDataGrid = ComputedLayoutDatumGrid[][]
|
|
29
|
+
|
|
30
|
+
export interface ComputedLayoutDatumGrid extends ComputedDatumGrid {
|
|
31
|
+
axisX: number
|
|
32
|
+
axisY: number
|
|
33
|
+
axisYFromZero: number
|
|
26
34
|
}
|
|
27
35
|
|
|
28
|
-
export interface
|
|
36
|
+
export interface GridContainerPosition {
|
|
29
37
|
slotIndex: number
|
|
30
38
|
rowIndex: number
|
|
31
39
|
columnIndex: number
|
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
import { Observable } from 'rxjs'
|
|
2
2
|
import type { ContextObserverBase } from './ContextObserver'
|
|
3
3
|
import type { ComputedDataGrid, ComputedDatumGrid } from './ComputedDataGrid'
|
|
4
|
-
import type {
|
|
5
|
-
import type { TransformData } from './TransformData'
|
|
4
|
+
import type { DataFormatterGrid } from './DataFormatterGrid'
|
|
6
5
|
import type { ContextObserverGridDetail } from './ContextObserverGrid'
|
|
7
6
|
|
|
8
7
|
export interface ContextObserverMultiGrid<PluginParams> extends ContextObserverBase<'multiGrid', PluginParams> {
|
|
9
8
|
textSizePx$: Observable<number>
|
|
10
|
-
multiGridEachDetail$: Observable<
|
|
11
|
-
multiGridContainer$: Observable<ContainerPosition[][]>
|
|
9
|
+
multiGridEachDetail$: Observable<ContextObserverMultiGridDetail[]>
|
|
12
10
|
}
|
|
13
11
|
|
|
14
|
-
// export interface MultiGridObservableAll {
|
|
15
|
-
// isSeriesPositionSeprate$: Observable<boolean>
|
|
16
|
-
// gridContainer$: Observable<ContainerPosition[]>
|
|
17
|
-
// gridAxesTransform$: Observable<TransformData>
|
|
18
|
-
// gridAxesReverseTransform$: Observable<TransformData>
|
|
19
|
-
// gridGraphicTransform$: Observable<TransformData>
|
|
20
|
-
// gridGraphicReverseScale$: Observable<[number, number][]>
|
|
21
|
-
// gridAxesSize$: Observable<{ width: number; height: number; }>
|
|
22
|
-
// gridHighlight$: Observable<string[]>
|
|
23
|
-
// existSeriesLabels$: Observable<string[]>
|
|
24
|
-
// SeriesDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
|
|
25
|
-
// GroupDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
|
|
26
|
-
// visibleComputedData$: Observable<ComputedDataGrid>
|
|
27
|
-
// }
|
|
28
12
|
|
|
13
|
+
export interface ContextObserverMultiGridDetail extends ContextObserverGridDetail {
|
|
14
|
+
computedData$: Observable<ComputedDataGrid>
|
|
15
|
+
dataFormatter$: Observable<DataFormatterGrid>
|
|
16
|
+
}
|
|
@@ -4,6 +4,26 @@ import type { ComputedDatumSeries } from './ComputedDataSeries'
|
|
|
4
4
|
|
|
5
5
|
export interface ContextObserverSeries<PluginParams> extends ContextObserverBase<'series', PluginParams> {
|
|
6
6
|
textSizePx$: Observable<number>
|
|
7
|
+
separateSeries$: Observable<boolean>
|
|
8
|
+
visibleComputedData$: Observable<ComputedDatumSeries[][]>
|
|
9
|
+
computedLayoutData$: Observable<ComputedDatumSeries[][]>
|
|
10
|
+
visibleComputedLayoutData$: Observable<ComputedDatumSeries[][]>
|
|
7
11
|
seriesHighlight$: Observable<ComputedDatumSeries[]>
|
|
12
|
+
seriesLabels$: Observable<string[]>
|
|
8
13
|
SeriesDataMap$: Observable<Map<string, ComputedDatumSeries[]>>
|
|
9
|
-
|
|
14
|
+
seriesContainerPosition$: Observable<SeriesContainerPosition[]>
|
|
15
|
+
SeriesContainerPositionMap$: Observable<Map<string, SeriesContainerPosition>>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SeriesContainerPosition {
|
|
19
|
+
slotIndex: number
|
|
20
|
+
rowIndex: number
|
|
21
|
+
columnIndex: number
|
|
22
|
+
// translate: [number, number]
|
|
23
|
+
startX: number
|
|
24
|
+
startY: number
|
|
25
|
+
centerX: number
|
|
26
|
+
centerY: number
|
|
27
|
+
width: number
|
|
28
|
+
height: number
|
|
29
|
+
}
|