@orbcharts/core 3.0.0-beta.1 → 3.0.0-beta.11

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 (45) hide show
  1. package/dist/orbcharts-core.es.js +3271 -2862
  2. package/dist/orbcharts-core.umd.js +4 -4
  3. package/dist/src/defaults.d.ts +24 -23
  4. package/dist/src/utils/d3Scale.d.ts +28 -0
  5. package/dist/src/utils/gridObservables.d.ts +29 -19
  6. package/dist/src/utils/index.d.ts +1 -1
  7. package/dist/src/utils/multiGridObservables.d.ts +2 -2
  8. package/dist/src/utils/multiValueObservables.d.ts +73 -0
  9. package/dist/src/utils/orbchartsUtils.d.ts +24 -10
  10. package/dist/src/utils/relationshipObservables.d.ts +13 -0
  11. package/dist/src/utils/seriesObservables.d.ts +4 -4
  12. package/dist/src/utils/treeObservables.d.ts +2 -5
  13. package/package.json +2 -2
  14. package/src/GridChart.ts +2 -2
  15. package/src/MultiGridChart.ts +2 -2
  16. package/src/MultiValueChart.ts +2 -2
  17. package/src/RelationshipChart.ts +2 -2
  18. package/src/SeriesChart.ts +2 -2
  19. package/src/TreeChart.ts +2 -2
  20. package/src/base/createBaseChart.ts +13 -13
  21. package/src/base/validators/chartParamsValidator.ts +6 -6
  22. package/src/defaults.ts +87 -47
  23. package/src/grid/computedDataFn.ts +4 -4
  24. package/src/grid/contextObserverCallback.ts +58 -37
  25. package/src/grid/dataFormatterValidator.ts +14 -14
  26. package/src/multiGrid/computedDataFn.ts +2 -2
  27. package/src/multiValue/computedDataFn.ts +81 -147
  28. package/src/multiValue/contextObserverCallback.ts +150 -2
  29. package/src/relationship/computedDataFn.ts +94 -60
  30. package/src/relationship/contextObserverCallback.ts +68 -0
  31. package/src/tree/computedDataFn.ts +9 -10
  32. package/src/tree/contextObserverCallback.ts +6 -9
  33. package/src/utils/d3Scale.ts +198 -0
  34. package/src/utils/gridObservables.ts +320 -248
  35. package/src/utils/index.ts +1 -1
  36. package/src/utils/multiGridObservables.ts +75 -49
  37. package/src/utils/multiValueObservables.ts +662 -0
  38. package/src/utils/observables.ts +30 -12
  39. package/src/utils/orbchartsUtils.ts +90 -65
  40. package/src/utils/relationshipObservables.ts +85 -0
  41. package/src/utils/seriesObservables.ts +7 -7
  42. package/src/utils/treeObservables.ts +44 -33
  43. package/src/utils/validator.ts +5 -4
  44. package/dist/src/utils/d3Utils.d.ts +0 -19
  45. package/src/utils/d3Utils.ts +0 -108
@@ -1,7 +1,6 @@
1
1
  import type { DataMultiValueDatum, ComputedDataFn, ComputedDatumMultiValue } from '../../lib/core-types'
2
- import { formatValueToLabel, createDefaultDatumId } from '../utils/orbchartsUtils'
3
- import { createAxisLinearScale, createAxisPointScale } from '../utils/d3Utils'
4
- import { getMinAndMaxValue } from '../utils/orbchartsUtils'
2
+ import { createDefaultCategoryLabel, createDefaultDatumId, seriesColorPredicate } from '../utils/orbchartsUtils'
3
+ import { isPlainObject } from '../utils'
5
4
 
6
5
  export const computedDataFn: ComputedDataFn<'multiValue'> = (context) => {
7
6
  const { data, dataFormatter, chartParams } = context
@@ -9,163 +8,98 @@ export const computedDataFn: ComputedDataFn<'multiValue'> = (context) => {
9
8
  return []
10
9
  }
11
10
 
12
- // @Q@ 假資料待改寫
13
- const layout = {
14
- width: 1000,
15
- height: 1000
16
- }
11
+ const defaultCategoryLabel = createDefaultCategoryLabel()
17
12
 
18
13
  let computedDataMultiValue: ComputedDatumMultiValue[][] = []
19
14
 
20
15
  try {
21
- const dataMultiValue: DataMultiValueDatum[][] = data.map((d, i) => {
22
- return d.map((_d, _i) => {
23
- const datum: DataMultiValueDatum = typeof _d === 'number'
24
- ? {
25
- id: '',
26
- label: '',
27
- description: '',
28
- // tooltipContent: '',
29
- data: {},
30
- categoryLabel: '',
31
- value: _d
32
- }
33
- : {
34
- id: _d.id ?? '',
35
- label: _d.label ?? '',
36
- description: _d.description ?? '',
37
- // tooltipContent: _d.tooltipContent ?? '',
38
- data: _d.data ?? {},
39
- categoryLabel: _d.categoryLabel ??'',
40
- value: _d.value
41
- }
42
-
43
- return datum
44
- })
45
- })
46
-
47
- // x軸資料最小及最大值(第二維陣列中的第1筆為x軸資料)
48
- const [xMinValue, xMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[0]))
49
- // y軸資料最小及最大值(第二維陣列中的第2筆為y軸資料)
50
- const [yMinValue, yMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[1]))
51
-
52
- // const axisWidth = layout.width - dataFormatter.padding.left - dataFormatter.padding.right
53
- // const axisHeight = layout.height - dataFormatter.padding.top - dataFormatter.padding.bottom
54
- // const axisWidth = layout.width
55
- // const axisHeight = layout.height
56
- const xAxisWidth = (dataFormatter.xAxis.position === 'top' || dataFormatter.xAxis.position === 'bottom')
57
- ? layout.width
58
- : layout.height
59
- const yAxisWidth = (dataFormatter.yAxis.position === 'left' || dataFormatter.yAxis.position === 'right')
60
- ? layout.height
61
- : layout.width
62
-
63
- const xScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
64
- maxValue: xMaxValue,
65
- minValue: xMinValue,
66
- axisWidth: xAxisWidth,
67
- // scaleDomain: dataFormatter.xAxis.scaleDomain,
68
- // scaleRange: dataFormatter.xAxis.scaleRange
69
- scaleDomain: [xMinValue, xMaxValue],
70
- scaleRange: [0, 1]
71
- })
72
- const yScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
73
- maxValue: yMaxValue,
74
- minValue: yMinValue,
75
- axisWidth: yAxisWidth,
76
- // scaleDomain: dataFormatter.yAxis.scaleDomain,
77
- // scaleRange: dataFormatter.yAxis.scaleRange
78
- scaleDomain: [yMinValue, yMaxValue],
79
- scaleRange: [0, 1]
80
- })
81
-
82
- const _xScaleDoamin: [number, number] = [
83
- // dataFormatter.xAxis.scaleDomain[0] === 'auto' ? xMinValue : dataFormatter.xAxis.scaleDomain[0],
84
- (() => {
85
- if (dataFormatter.xAxis.scaleDomain[0] === 'auto') {
86
- return xMinValue < 0 ? xMinValue : 0
87
- } else if (dataFormatter.xAxis.scaleDomain[0] === 'min') {
88
- return xMinValue
89
- } else {
90
- return dataFormatter.xAxis.scaleDomain[0]
16
+ const dataMultiValue: DataMultiValueDatum[] = data.map((d, i) => {
17
+ if (Array.isArray(d)) {
18
+ return {
19
+ id: '',
20
+ label: '',
21
+ description: '',
22
+ // tooltipContent: '',
23
+ data: {},
24
+ categoryLabel: defaultCategoryLabel,
25
+ value: d
91
26
  }
92
- })(),
93
- // dataFormatter.xAxis.scaleDomain[1] === 'auto' ? xMaxValue : dataFormatter.xAxis.scaleDomain[1]
94
- (() => {
95
- if (dataFormatter.xAxis.scaleDomain[1] === 'auto') {
96
- return xMaxValue >= 0 ? xMaxValue : 0
97
- } else if (dataFormatter.xAxis.scaleDomain[1] === 'max') {
98
- return xMaxValue
99
- } else {
100
- return dataFormatter.xAxis.scaleDomain[1]
27
+ } else if (isPlainObject(d)) {
28
+ return {
29
+ id: d.id ?? '',
30
+ label: d.label ?? '',
31
+ description: d.description ?? '',
32
+ // tooltipContent: _d.tooltipContent ?? '',
33
+ data: d.data ?? {},
34
+ categoryLabel: d.categoryLabel ?? defaultCategoryLabel,
35
+ value: d.value
101
36
  }
102
- })()
103
- ]
104
- const _yScaleDoamin: [number, number] = [
105
- // dataFormatter.yAxis.scaleDomain[0] === 'auto' ? yMinValue : dataFormatter.yAxis.scaleDomain[0],
106
- (() => {
107
- if (dataFormatter.yAxis.scaleDomain[0] === 'auto') {
108
- return xMinValue < 0 ? xMinValue : 0
109
- } else if (dataFormatter.yAxis.scaleDomain[0] === 'min') {
110
- return xMinValue
111
- } else {
112
- return dataFormatter.yAxis.scaleDomain[0]
37
+ } else {
38
+ return {
39
+ id: '',
40
+ label: '',
41
+ description: '',
42
+ // tooltipContent: '',
43
+ data: {},
44
+ categoryLabel: defaultCategoryLabel,
45
+ value: []
113
46
  }
114
- })(),
115
- // dataFormatter.yAxis.scaleDomain[1] === 'auto' ? yMaxValue : dataFormatter.yAxis.scaleDomain[1]
116
- (() => {
117
- if (dataFormatter.yAxis.scaleDomain[1] === 'auto') {
118
- return xMaxValue >= 0 ? xMaxValue : 0
119
- } else if (dataFormatter.yAxis.scaleDomain[1] === 'max') {
120
- return xMaxValue
121
- } else {
122
- return dataFormatter.yAxis.scaleDomain[1]
123
- }
124
- })()
125
- ]
47
+ }
48
+ })
49
+
50
+ const categoryLabels = (() => {
51
+ // 先使用 dataFormatter.categoryLabels
52
+ const CategoryLabelsSet = new Set(dataFormatter.categoryLabels)
53
+ // 再加入 datum 中的 categoryLabel
54
+ for (let datum of dataMultiValue) {
55
+ const categoryLabel = datum.categoryLabel ?? defaultCategoryLabel
56
+ CategoryLabelsSet.add(categoryLabel) // 不重覆
57
+ }
58
+ return Array.from(CategoryLabelsSet)
59
+ })()
126
60
 
127
- // // 篩選顯示狀態
128
- // const visibleFilter = (datum: DataMultiValueDatum, rowIndex: number, columnIndex: number, context: DataFormatterContext<"multiValue">) => {
129
- // // 如果不在scale的範圍內則為false,不再做visibleFilter的判斷
130
- // if (columnIndex === 0 && datum.value != null && ((datum.value as number) < _xScaleDoamin[0] || datum.value > _xScaleDoamin[1])) {
131
- // return false
132
- // }
133
- // if (columnIndex === 1 && datum.value != null && (datum.value < _yScaleDoamin[0] || datum.value > _yScaleDoamin[1])) {
134
- // return false
135
- // }
136
-
137
- // return dataFormatter.visibleFilter(datum, rowIndex, columnIndex, context)
138
- // }
61
+ // <categoryLabel, categoryIndex>
62
+ const CategoryIndexMap = new Map<string, number>(
63
+ categoryLabels.map((label, index) => [label, index])
64
+ )
65
+
139
66
 
140
67
  let index = 0
141
68
 
142
- computedDataMultiValue = dataMultiValue.map((d, i) => {
143
- return d.map((_d, _i) => {
144
- const currentIndex = index
145
- index++
146
-
147
- const defaultId = createDefaultDatumId(dataFormatter.type, i, _i)
148
-
149
- const computedDatum: ComputedDatumMultiValue = {
150
- id: _d.id ? _d.id : defaultId,
151
- index: currentIndex,
152
- label: _d.label ? _d.label : defaultId,
153
- description: _d.description ?? '',
154
- // tooltipContent: _d.tooltipContent ? _d.tooltipContent : dataFormatter.tooltipContentFormat(_d, i, _i, context),
155
- data: _d.data,
156
- value: _d.value,
157
- categoryIndex: 0, // @Q@ 未完成
158
- categoryLabel: '', // @Q@ 未完成
159
- // valueLabel: formatValueToLabel(_d.value, dataFormatter.multiValue[_i].valueFormat),
160
- axis: _i == 0 ? xScale(_d.value) : yScale(_d.value),
161
- visible: true, // 先給預設值
162
- color: '' // @Q@ 未完成
163
- }
69
+ dataMultiValue.forEach((d, i) => {
70
+ const currentIndex = index
71
+ index++
72
+
73
+ const defaultId = createDefaultDatumId(dataFormatter.type, i)
74
+
75
+ const categoryIndex = CategoryIndexMap.get(d.categoryLabel) ?? 0
76
+
77
+ const color = seriesColorPredicate(categoryIndex, chartParams)
78
+
79
+ const computedDatum: ComputedDatumMultiValue = {
80
+ id: d.id ? d.id : defaultId,
81
+ index: currentIndex,
82
+ label: d.label ? d.label : defaultId,
83
+ description: d.description ?? '',
84
+ // tooltipContent: _d.tooltipContent ? _d.tooltipContent : dataFormatter.tooltipContentFormat(_d, i, _i, context),
85
+ data: d.data,
86
+ datumIndex: i,
87
+ value: d.value,
88
+ categoryIndex,
89
+ categoryLabel: d.categoryLabel,
90
+ // valueLabel: formatValueToLabel(_d.value, dataFormatter.multiValue[_i].valueFormat),
91
+ // axis: _i == 0 ? xScale(_d.value) : yScale(_d.value),
92
+ visible: true, // 先給預設值
93
+ color
94
+ }
164
95
 
165
- computedDatum.visible = dataFormatter.visibleFilter(computedDatum, context)
96
+ computedDatum.visible = dataFormatter.visibleFilter(computedDatum, context)
166
97
 
167
- return computedDatum
168
- })
98
+ // 依 categoryIndex 分組
99
+ if (!computedDataMultiValue[categoryIndex]) {
100
+ computedDataMultiValue[categoryIndex] = []
101
+ }
102
+ computedDataMultiValue[categoryIndex].push(computedDatum)
169
103
  })
170
104
  } catch (e) {
171
105
  // console.error(e)
@@ -1,12 +1,160 @@
1
- import type { ContextObserverCallback } from '../../lib/core-types'
1
+ import { map, shareReplay, distinctUntilChanged } from 'rxjs'
2
+ import type { ContextObserverCallback, ContextObserverTypeMap } from '../../lib/core-types'
3
+ import {
4
+ highlightObservable,
5
+ categoryDataMapObservable,
6
+ textSizePxObservable
7
+ } from '../utils/observables'
8
+ import {
9
+ multiValueComputedLayoutDataObservable,
10
+ // multiValueAxesTransformObservable,
11
+ // multiValueAxesReverseTransformObservable,
12
+ multiValueGraphicTransformObservable,
13
+ multiValueGraphicReverseScaleObservable,
14
+ multiValueCategoryLabelsObservable,
15
+ multiValueVisibleComputedDataObservable,
16
+ multiValueVisibleComputedLayoutDataObservable,
17
+ multiValueContainerPositionObservable,
18
+ minMaxXYObservable,
19
+ filteredMinMaxXYDataObservable
20
+ } from '../utils/multiValueObservables'
2
21
 
3
22
  export const contextObserverCallback: ContextObserverCallback<'multiValue'> = ({ subject, observer }) => {
4
23
 
5
- return {
24
+ const textSizePx$ = textSizePxObservable(observer.fullChartParams$).pipe(
25
+ shareReplay(1)
26
+ )
27
+
28
+ const isCategorySeprate$ = observer.fullDataFormatter$.pipe(
29
+ map(d => d.separateCategory),
30
+ distinctUntilChanged(),
31
+ shareReplay(1)
32
+ )
33
+
34
+ const multiValueContainerPosition$ = multiValueContainerPositionObservable({
35
+ computedData$: observer.computedData$,
36
+ fullDataFormatter$: observer.fullDataFormatter$,
37
+ layout$: observer.layout$,
38
+ })
39
+
40
+ // const multiValueAxesSize$ = multiValueAxesSizeObservable({
41
+ // fullDataFormatter$: observer.fullDataFormatter$,
42
+ // layout$: observer.layout$
43
+ // }).pipe(
44
+ // shareReplay(1)
45
+ // )
46
+
47
+ const datumList$ = observer.computedData$.pipe(
48
+ map(d => d.flat().flat())
49
+ ).pipe(
50
+ shareReplay(1)
51
+ )
52
+
53
+ const multiValueHighlight$ = highlightObservable({
54
+ datumList$,
55
+ fullChartParams$: observer.fullChartParams$,
56
+ event$: subject.event$
57
+ }).pipe(
58
+ shareReplay(1)
59
+ )
60
+
61
+ const categoryLabels$ = multiValueCategoryLabelsObservable({
62
+ computedData$: observer.computedData$,
63
+ fullDataFormatter$: observer.fullDataFormatter$,
64
+ })
65
+
66
+ const CategoryDataMap$ = categoryDataMapObservable({
67
+ datumList$: datumList$
68
+ }).pipe(
69
+ shareReplay(1)
70
+ )
71
+
72
+ const minMaxXY$ = minMaxXYObservable({
73
+ computedData$: observer.computedData$
74
+ }).pipe(
75
+ shareReplay(1)
76
+ )
77
+
78
+
79
+ const computedLayoutData$ = multiValueComputedLayoutDataObservable({
80
+ computedData$: observer.computedData$,
81
+ minMaxXY$,
82
+ fullDataFormatter$: observer.fullDataFormatter$,
83
+ layout$: observer.layout$,
84
+ }).pipe(
85
+ shareReplay(1)
86
+ )
87
+
88
+ const visibleComputedData$ = multiValueVisibleComputedDataObservable({
89
+ computedData$: observer.computedData$,
90
+ }).pipe(
91
+ shareReplay(1)
92
+ )
93
+
94
+ const visibleComputedLayoutData$ = multiValueVisibleComputedLayoutDataObservable({
95
+ computedLayoutData$: computedLayoutData$,
96
+ }).pipe(
97
+ shareReplay(1)
98
+ )
99
+
100
+ const filteredMinMaxXYData$ = filteredMinMaxXYDataObservable({
101
+ visibleComputedLayoutData$: visibleComputedLayoutData$,
102
+ minMaxXY$,
103
+ fullDataFormatter$: observer.fullDataFormatter$,
104
+ }).pipe(
105
+ shareReplay(1)
106
+ )
107
+
108
+ // const multiValueAxesTransform$ = multiValueAxesTransformObservable({
109
+ // fullDataFormatter$: observer.fullDataFormatter$,
110
+ // layout$: observer.layout$
111
+ // }).pipe(
112
+ // shareReplay(1)
113
+ // )
114
+
115
+ // const multiValueAxesReverseTransform$ = multiValueAxesReverseTransformObservable({
116
+ // multiValueAxesTransform$
117
+ // }).pipe(
118
+ // shareReplay(1)
119
+ // )
120
+
121
+ const multiValueGraphicTransform$ = multiValueGraphicTransformObservable({
122
+ minMaxXY$,
123
+ filteredMinMaxXYData$,
124
+ fullDataFormatter$: observer.fullDataFormatter$,
125
+ layout$: observer.layout$
126
+ }).pipe(
127
+ shareReplay(1)
128
+ )
129
+
130
+ const multiValueGraphicReverseScale$ = multiValueGraphicReverseScaleObservable({
131
+ multiValueContainerPosition$: multiValueContainerPosition$,
132
+ // multiValueAxesTransform$: multiValueAxesTransform$,
133
+ multiValueGraphicTransform$: multiValueGraphicTransform$,
134
+ })
135
+
136
+
137
+ return <ContextObserverTypeMap<'multiValue', any>>{
6
138
  fullParams$: observer.fullParams$,
7
139
  fullChartParams$: observer.fullChartParams$,
8
140
  fullDataFormatter$: observer.fullDataFormatter$,
9
141
  computedData$: observer.computedData$,
10
142
  layout$: observer.layout$,
143
+ textSizePx$,
144
+ isCategorySeprate$,
145
+ multiValueContainerPosition$,
146
+ // multiValueAxesSize$,
147
+ multiValueHighlight$,
148
+ categoryLabels$,
149
+ CategoryDataMap$,
150
+ minMaxXY$,
151
+ computedLayoutData$,
152
+ visibleComputedData$,
153
+ visibleComputedLayoutData$,
154
+ filteredMinMaxXYData$,
155
+ // multiValueAxesTransform$,
156
+ // multiValueAxesReverseTransform$,
157
+ multiValueGraphicTransform$,
158
+ multiValueGraphicReverseScale$,
11
159
  }
12
160
  }
@@ -8,10 +8,13 @@ import type {
8
8
  ComputedNode,
9
9
  ComputedEdge
10
10
  } from '../../lib/core-types'
11
+ import { createDefaultCategoryLabel, seriesColorPredicate } from '../utils/orbchartsUtils'
11
12
 
12
13
  export const computedDataFn: ComputedDataFn<'relationship'> = (context) => {
13
14
  const { data, dataFormatter, chartParams } = context
14
15
 
16
+ const defaultCategoryLabel = createDefaultCategoryLabel()
17
+
15
18
  let computedNodes: ComputedNode[] = []
16
19
  let computedEdges: ComputedEdge[] = []
17
20
 
@@ -33,86 +36,117 @@ export const computedDataFn: ComputedDataFn<'relationship'> = (context) => {
33
36
  } as ComputedDataRelationship
34
37
  }
35
38
 
39
+ const categoryLabels = (() => {
40
+ // 先使用 dataFormatter.categoryLabels
41
+ const CategoryLabelsSet = new Set(dataFormatter.categoryLabels)
42
+ // 再加入 datum 中的 categoryLabel
43
+ for (let datum of nodes) {
44
+ const categoryLabel = datum.categoryLabel ?? defaultCategoryLabel
45
+ CategoryLabelsSet.add(categoryLabel) // 不重覆
46
+ }
47
+ for (let datum of edges) {
48
+ const categoryLabel = datum.categoryLabel ?? defaultCategoryLabel
49
+ CategoryLabelsSet.add(categoryLabel) // 不重覆
50
+ }
51
+ return Array.from(CategoryLabelsSet)
52
+ })()
53
+
54
+ // <categoryLabel, categoryIndex>
55
+ const CategoryIndexMap = new Map<string, number>(
56
+ categoryLabels.map((label, index) => [label, index])
57
+ )
58
+
36
59
  // -- nodes --
37
60
  computedNodes = nodes.map((node, i) => {
61
+ const categoryLabel = node.categoryLabel ?? defaultCategoryLabel
62
+ const categoryIndex = CategoryIndexMap.get(categoryLabel) ?? 0
63
+
38
64
  const computedNode: ComputedNode = {
39
65
  id: node.id,
40
66
  index: i,
41
67
  label: node.label ?? '',
42
68
  description: node.description ?? '',
43
- // tooltipContent: node.tooltipContent ? node.tooltipContent : dataFormatter.tooltipContentFormat(node, 0, i, context), // 0代表node
44
69
  data: node.data ?? {},
45
70
  value: node.value ?? 0,
46
- categoryIndex: 0, // @Q@ 未完成
47
- categoryLabel: '', // @Q@ 未完成
48
- color: '', // @Q@ 未完成
49
- startNodes: [], // 後面再取得資料
50
- startNodeIds: [], // 後面再取得資料
51
- endNodes: [], // 後面再取得資料
52
- endNodeIds: [], // 後面再取得資料
53
- visible: true // 後面再取得資料
71
+ categoryIndex,
72
+ categoryLabel,
73
+ color: seriesColorPredicate(categoryIndex, chartParams),
74
+ // startNodes: [], // 後面再取得資料
75
+ // startNodeIds: [], // 後面再取得資料
76
+ // endNodes: [], // 後面再取得資料
77
+ // endNodeIds: [], // 後面再取得資料
78
+ visible: true // 先給預設值
54
79
  }
80
+
81
+ computedNode.visible = dataFormatter.visibleFilter(computedNode, context)
82
+
55
83
  return computedNode
56
84
  })
57
85
 
58
86
  const NodesMap: Map<string, ComputedNode> = new Map(computedNodes.map(d => [d.id, d]))
59
87
 
60
- // -- edges --
61
- computedEdges = edges.map((edge, i) => {
62
- const computedEdge: ComputedEdge = {
63
- id: edge.id,
64
- index: i,
65
- label: edge.label ?? '',
66
- description: edge.description ?? '',
67
- // tooltipContent: edge.tooltipContent ? edge.tooltipContent : dataFormatter.tooltipContentFormat(edge, 1, i, context), // 1代表edge
68
- data: edge.data ?? {},
69
- value: edge.value ?? 0,
70
- startNode: NodesMap.get(edge.start),
71
- startNodeId: edge.start,
72
- endNode: NodesMap.get(edge.end),
73
- endNodeId: edge.end,
74
- visible: true // 先給預設值
75
- }
76
-
77
- return computedEdge
78
- })
88
+ // const StartNodesMap: Map<string, ComputedNode[]> = (function () {
89
+ // const _StartNodesMap = new Map()
90
+ // computedEdges.forEach(edge => {
91
+ // const startNodes: ComputedNode[] = _StartNodesMap.get(edge.endNodeId) ?? []
92
+ // startNodes.push(edge.startNode)
93
+ // _StartNodesMap.set(edge.endNodeId, startNodes)
94
+ // })
95
+ // return _StartNodesMap
96
+ // })()
97
+
98
+ // const EndNodesMap: Map<string, ComputedNode[]> = (function () {
99
+ // const _EndNodesMap = new Map()
100
+ // computedEdges.forEach(edge => {
101
+ // const endNodes: ComputedNode[] = _EndNodesMap.get(edge.startNodeId) ?? []
102
+ // endNodes.push(edge.endNode)
103
+ // _EndNodesMap.set(edge.startNodeId, endNodes)
104
+ // })
105
+ // return _EndNodesMap
106
+ // })()
79
107
 
80
- const StartNodesMap: Map<string, ComputedNode[]> = (function () {
81
- const _StartNodesMap = new Map()
82
- computedEdges.forEach(edge => {
83
- const startNodes: ComputedNode[] = _StartNodesMap.get(edge.endNodeId) ?? []
84
- startNodes.push(edge.startNode)
85
- _StartNodesMap.set(edge.endNodeId, startNodes)
108
+ // -- edges --
109
+ computedEdges = edges
110
+ .map((edge, i) => {
111
+ const startNode = NodesMap.get(edge.start)
112
+ const endNode = NodesMap.get(edge.end)
113
+ return {
114
+ edge,
115
+ startNode,
116
+ endNode
117
+ }
86
118
  })
87
- return _StartNodesMap
88
- })()
89
-
90
- const EndNodesMap: Map<string, ComputedNode[]> = (function () {
91
- const _EndNodesMap = new Map()
92
- computedEdges.forEach(edge => {
93
- const endNodes: ComputedNode[] = _EndNodesMap.get(edge.startNodeId) ?? []
94
- endNodes.push(edge.endNode)
95
- _EndNodesMap.set(edge.startNodeId, endNodes)
119
+ .filter(({ edge }) => {
120
+ const startNode = NodesMap.get(edge.start)
121
+ const endNode = NodesMap.get(edge.end)
122
+ return startNode != null && endNode != null
96
123
  })
97
- return _EndNodesMap
98
- })()
124
+ .map(({ edge, startNode, endNode }, i) => {
125
+ const categoryLabel = edge.categoryLabel ?? defaultCategoryLabel
126
+ // const startNode = NodesMap.get(edge.start)
127
+ // const endNode = NodesMap.get(edge.end)
99
128
 
100
- // -- 補齊nodes資料 --
101
- Array.from(NodesMap).forEach(([nodeId, node]) => {
102
- node.startNodes = StartNodesMap.get(nodeId)
103
- node.startNodeIds = node.startNodes.map(d => d.id)
104
- node.endNodes = EndNodesMap.get(nodeId)
105
- node.endNodeIds = node.endNodes.map(d => d.id)
106
- node.visible = dataFormatter.visibleFilter(node, context)
107
- })
129
+ const computedEdge: ComputedEdge = {
130
+ id: edge.id,
131
+ index: i,
132
+ label: edge.label ?? '',
133
+ description: edge.description ?? '',
134
+ data: edge.data ?? {},
135
+ value: edge.value ?? 0,
136
+ categoryIndex: CategoryIndexMap.get(categoryLabel),
137
+ categoryLabel,
138
+ color: seriesColorPredicate(i, chartParams),
139
+ startNode,
140
+ // startNodeId: edge.start,
141
+ endNode,
142
+ // endNodeId: edge.end,
143
+ visible: startNode.visible && endNode.visible
144
+ }
108
145
 
109
- // -- 補齊edges資料 --
110
- computedEdges = computedEdges.map(edge => {
111
- edge.visible = edge.startNode.visible && edge.endNode.visible
112
- ? true
113
- : false
114
- return edge
115
- })
146
+ return computedEdge
147
+ })
148
+
149
+
116
150
  } catch (e) {
117
151
  // console.error(e)
118
152
  throw Error(e)