@orbcharts/core 3.0.0-beta.4 → 3.0.0-beta.6

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.
@@ -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,102 @@ 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
 
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
+ // })()
107
+
60
108
  // -- edges --
61
109
  computedEdges = edges.map((edge, i) => {
110
+ const categoryLabel = edge.categoryLabel ?? defaultCategoryLabel
111
+ const startNode = NodesMap.get(edge.start)
112
+ const endNode = NodesMap.get(edge.end)
113
+
62
114
  const computedEdge: ComputedEdge = {
63
115
  id: edge.id,
64
116
  index: i,
65
117
  label: edge.label ?? '',
66
118
  description: edge.description ?? '',
67
- // tooltipContent: edge.tooltipContent ? edge.tooltipContent : dataFormatter.tooltipContentFormat(edge, 1, i, context), // 1代表edge
68
119
  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 // 先給預設值
120
+ value: edge.value ?? 0,
121
+ categoryIndex: CategoryIndexMap.get(categoryLabel),
122
+ categoryLabel,
123
+ color: seriesColorPredicate(i, chartParams),
124
+ startNode,
125
+ // startNodeId: edge.start,
126
+ endNode,
127
+ // endNodeId: edge.end,
128
+ visible: startNode.visible && endNode.visible
75
129
  }
76
130
 
77
131
  return computedEdge
78
132
  })
79
133
 
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)
86
- })
87
- return _StartNodesMap
88
- })()
89
134
 
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)
96
- })
97
- return _EndNodesMap
98
- })()
99
-
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
- })
108
-
109
- // -- 補齊edges資料 --
110
- computedEdges = computedEdges.map(edge => {
111
- edge.visible = edge.startNode.visible && edge.endNode.visible
112
- ? true
113
- : false
114
- return edge
115
- })
116
135
  } catch (e) {
117
136
  // console.error(e)
118
137
  throw Error(e)
@@ -1,12 +1,80 @@
1
+ import { map, shareReplay } from 'rxjs'
1
2
  import type { ContextObserverCallback } from '../../lib/core-types'
3
+ import { highlightObservable, categoryDataMapObservable, textSizePxObservable } from '../utils/observables'
4
+ import {
5
+ categoryLabelsObservable,
6
+ NodeMapObservable,
7
+ EdgeMapObservable,
8
+ relationshipVisibleComputedDataObservable
9
+ } from '../utils/relationshipObservables'
2
10
 
3
11
  export const contextObserverCallback: ContextObserverCallback<'relationship'> = ({ subject, observer }) => {
4
12
 
13
+ const textSizePx$ = textSizePxObservable(observer.fullChartParams$).pipe(
14
+ shareReplay(1)
15
+ )
16
+
17
+ const relationshipHighlightNodes$ = highlightObservable({
18
+ datumList$: observer.computedData$.pipe(map(data => data.nodes)),
19
+ fullChartParams$: observer.fullChartParams$,
20
+ event$: subject.event$
21
+ }).pipe(
22
+ shareReplay(1)
23
+ )
24
+
25
+ const relationshipHighlightEdges$ = highlightObservable({
26
+ datumList$: observer.computedData$.pipe(map(data => data.edges)),
27
+ fullChartParams$: observer.fullChartParams$,
28
+ event$: subject.event$
29
+ }).pipe(
30
+ shareReplay(1)
31
+ )
32
+
33
+ const CategoryNodeMap$ = categoryDataMapObservable({
34
+ datumList$: observer.computedData$.pipe(map(data => data.nodes))
35
+ }).pipe(
36
+ shareReplay(1)
37
+ )
38
+
39
+ const CategoryEdgeMap$ = categoryDataMapObservable({
40
+ datumList$: observer.computedData$.pipe(map(data => data.edges))
41
+ }).pipe(
42
+ shareReplay(1)
43
+ )
44
+
45
+ const NodeMap$ = NodeMapObservable(observer.computedData$).pipe(
46
+ shareReplay(1)
47
+ )
48
+
49
+ const EdgeMap$ = EdgeMapObservable(observer.computedData$).pipe(
50
+ shareReplay(1)
51
+ )
52
+
53
+ const categoryLabels$ = categoryLabelsObservable(CategoryNodeMap$, CategoryEdgeMap$).pipe(
54
+ shareReplay(1)
55
+ )
56
+
57
+ const visibleComputedData$ = relationshipVisibleComputedDataObservable({
58
+ computedData$: observer.computedData$,
59
+ NodeMap$
60
+ }).pipe(
61
+ shareReplay(1)
62
+ )
63
+
5
64
  return {
6
65
  fullParams$: observer.fullParams$,
7
66
  fullChartParams$: observer.fullChartParams$,
8
67
  fullDataFormatter$: observer.fullDataFormatter$,
9
68
  computedData$: observer.computedData$,
10
69
  layout$: observer.layout$,
70
+ textSizePx$,
71
+ relationshipHighlightNodes$,
72
+ relationshipHighlightEdges$,
73
+ categoryLabels$,
74
+ CategoryNodeMap$,
75
+ CategoryEdgeMap$,
76
+ NodeMap$,
77
+ EdgeMap$,
78
+ visibleComputedData$
11
79
  }
12
80
  }
@@ -1,13 +1,13 @@
1
1
  import * as d3 from 'd3'
2
- import { DATA_FORMATTER_VALUE_AXIS_DEFAULT } from '../defaults'
2
+ import { DEFAULT_DATA_FORMATTER_VALUE_AXIS } from '../defaults'
3
3
 
4
4
  // scaleLinear - 連續資料 -> 座標
5
5
  export const createValueToAxisScale = ({
6
6
  maxValue = 1,
7
7
  minValue = 0,
8
8
  axisWidth,
9
- scaleDomain = DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain,
10
- scaleRange = DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange,
9
+ scaleDomain = DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleDomain,
10
+ scaleRange = DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleRange,
11
11
  reverse = false
12
12
  }: {
13
13
  maxValue: number
@@ -17,16 +17,16 @@ export const createValueToAxisScale = ({
17
17
  scaleRange: [number, number] // 0-1
18
18
  reverse?: boolean
19
19
  }) => {
20
- if (minValue === maxValue) {
21
- maxValue += 1 // 避免最大及最小值相同造成無法計算scale
22
- minValue -= 1
23
- }
20
+ // if (minValue === maxValue) {
21
+ // maxValue += 1 // 避免最大及最小值相同造成無法計算scale
22
+ // minValue -= 1
23
+ // }
24
24
 
25
25
  // -- 無值補上預設值 --
26
- const domainMin: number | 'min' | 'auto' = scaleDomain[0] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain[0]
27
- const domainMax: number | 'max' | 'auto' = scaleDomain[1] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain[1]
28
- const rangeMin: number = scaleRange[0] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange[0]
29
- const rangeMax: number = scaleRange[1] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange[1]
26
+ const domainMin: number | 'min' | 'auto' = scaleDomain[0] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleDomain[0]
27
+ const domainMax: number | 'max' | 'auto' = scaleDomain[1] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleDomain[1]
28
+ const rangeMin: number = scaleRange[0] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleRange[0]
29
+ const rangeMax: number = scaleRange[1] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleRange[1]
30
30
 
31
31
  // -- 'auto' | 'max' | 'min' 替換成實際值 --
32
32
  let domainMinValue: number = (() => {
@@ -83,8 +83,8 @@ export const createAxisToValueScale = ({
83
83
  maxValue = 1,
84
84
  minValue = 0,
85
85
  axisWidth,
86
- scaleDomain = DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain,
87
- scaleRange = DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange,
86
+ scaleDomain = DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleDomain,
87
+ scaleRange = DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleRange,
88
88
  reverse = false
89
89
  }: {
90
90
  maxValue: number
@@ -100,10 +100,10 @@ export const createAxisToValueScale = ({
100
100
  }
101
101
 
102
102
  // -- 無值補上預設值 --
103
- const domainMin: number | 'min' | 'auto' = scaleDomain[0] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain[0]
104
- const domainMax: number | 'max' | 'auto' = scaleDomain[1] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleDomain[1]
105
- const rangeMin: number = scaleRange[0] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange[0]
106
- const rangeMax: number = scaleRange[1] ?? DATA_FORMATTER_VALUE_AXIS_DEFAULT.scaleRange[1]
103
+ const domainMin: number | 'min' | 'auto' = scaleDomain[0] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleDomain[0]
104
+ const domainMax: number | 'max' | 'auto' = scaleDomain[1] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleDomain[1]
105
+ const rangeMin: number = scaleRange[0] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleRange[0]
106
+ const rangeMax: number = scaleRange[1] ?? DEFAULT_DATA_FORMATTER_VALUE_AXIS.scaleRange[1]
107
107
 
108
108
  // -- 'auto' | 'max' | 'min' 替換成實際值 --
109
109
  let domainMinValue: number = (() => {
@@ -30,10 +30,10 @@ import type {
30
30
  HighlightTarget,
31
31
  Layout,
32
32
  TransformData } from '../../lib/core-types'
33
- import { getMinAndMaxGrid } from './orbchartsUtils'
33
+ import { getMinMaxGrid } from './orbchartsUtils'
34
34
  import { createValueToAxisScale, createLabelToAxisScale, createAxisToLabelIndexScale } from './d3Scale'
35
35
  import { calcGridContainerLayout } from './orbchartsUtils'
36
- import { getMinAndMaxValue } from './orbchartsUtils'
36
+ import { getMinMaxValue } from './orbchartsUtils'
37
37
 
38
38
  export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
39
39
  computedData$: Observable<ComputedDataTypeMap<'grid'>>
@@ -43,7 +43,7 @@ export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormat
43
43
 
44
44
  // 未篩選group範圍前的group scale( * 不受到dataFormatter設定影響)
45
45
  function createOriginGroupScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
46
- const groupAxisWidth = (dataFormatter.grid.groupAxis.position === 'top' || dataFormatter.grid.groupAxis.position === 'bottom')
46
+ const groupAxisWidth = (dataFormatter.groupAxis.position === 'top' || dataFormatter.groupAxis.position === 'bottom')
47
47
  ? layout.width
48
48
  : layout.height
49
49
  const groupEndIndex = computedData[0] ? computedData[0].length - 1 : 0
@@ -60,12 +60,16 @@ export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormat
60
60
 
61
61
  // 未篩選group範圍及visible前的value scale( * 不受到dataFormatter設定影響)
62
62
  function createOriginValueScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
63
- const valueAxisWidth = (dataFormatter.grid.valueAxis.position === 'left' || dataFormatter.grid.valueAxis.position === 'right')
63
+ const valueAxisWidth = (dataFormatter.valueAxis.position === 'left' || dataFormatter.valueAxis.position === 'right')
64
64
  ? layout.height
65
65
  : layout.width
66
66
 
67
67
  const listData = computedData.flat()
68
- const [minValue, maxValue] = getMinAndMaxValue(listData)
68
+ let [minValue, maxValue] = getMinMaxValue(listData)
69
+ if (minValue === maxValue && maxValue === 0) {
70
+ // 避免最大及最小值相同造成無法計算scale
71
+ maxValue = 1
72
+ }
69
73
 
70
74
  const valueScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
71
75
  maxValue,
@@ -144,8 +148,8 @@ export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
144
148
  ).subscribe(data => {
145
149
 
146
150
  const axisSize = calcAxesSize({
147
- xAxisPosition: data.fullDataFormatter.grid.groupAxis.position,
148
- yAxisPosition: data.fullDataFormatter.grid.valueAxis.position,
151
+ xAxisPosition: data.fullDataFormatter.groupAxis.position,
152
+ yAxisPosition: data.fullDataFormatter.valueAxis.position,
149
153
  width: data.layout.width,
150
154
  height: data.layout.height,
151
155
  })
@@ -230,7 +234,7 @@ export const gridContainerPositionObservable = ({ computedData$, fullDataFormatt
230
234
  switchMap(async (d) => d),
231
235
  map(data => {
232
236
 
233
- if (data.fullDataFormatter.grid.separateSeries) {
237
+ if (data.fullDataFormatter.separateSeries) {
234
238
  // -- 依slotIndexes計算 --
235
239
  return calcGridContainerLayout(data.layout, data.fullDataFormatter.container, data.computedData.length)
236
240
  // return data.computedData.map((seriesData, seriesIndex) => {
@@ -319,7 +323,7 @@ export const groupScaleDomainValueObservable = ({ computedData$, fullDataFormatt
319
323
  }).pipe(
320
324
  switchMap(async (d) => d),
321
325
  map(data => {
322
- const groupAxis = data.fullDataFormatter.grid.groupAxis
326
+ const groupAxis = data.fullDataFormatter.groupAxis
323
327
  const groupMin = 0
324
328
  const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
325
329
  // const groupScaleDomainMin = groupAxis.scaleDomain[0] === 'min'
@@ -352,11 +356,11 @@ export const filteredMinMaxValueObservable = ({ computedData$, groupScaleDomainV
352
356
  })
353
357
  })
354
358
 
355
- const filteredMinAndMax = getMinAndMaxGrid(filteredData)
356
- // if (filteredMinAndMax[0] === filteredMinAndMax[1]) {
357
- // filteredMinAndMax[0] = filteredMinAndMax[1] - 1 // 避免最大及最小值相同造成無法計算scale
359
+ const filteredMinMax = getMinMaxGrid(filteredData)
360
+ // if (filteredMinMax[0] === filteredMinMax[1]) {
361
+ // filteredMinMax[0] = filteredMinMax[1] - 1 // 避免最大及最小值相同造成無法計算scale
358
362
  // }
359
- return filteredMinAndMax
363
+ return filteredMinMax
360
364
  }),
361
365
  )
362
366
  }
@@ -468,8 +472,8 @@ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
468
472
  switchMap(async (d) => d),
469
473
  ).subscribe(data => {
470
474
  const axesTransformData = calcAxesTransform({
471
- xAxis: data.fullDataFormatter.grid.groupAxis,
472
- yAxis: data.fullDataFormatter.grid.valueAxis,
475
+ xAxis: data.fullDataFormatter.groupAxis,
476
+ yAxis: data.fullDataFormatter.valueAxis,
473
477
  width: data.layout.width,
474
478
  height: data.layout.height
475
479
  })
@@ -570,10 +574,11 @@ export const gridGraphicTransformObservable = ({ computedData$, groupScaleDomain
570
574
  // })
571
575
  // })
572
576
 
573
- // const filteredMinAndMax = getMinAndMaxGrid(filteredData)
574
- // if (filteredMinAndMax[0] === filteredMinAndMax[1]) {
575
- // filteredMinAndMax[0] = filteredMinAndMax[1] - 1 // 避免最大及最小值相同造成無法計算scale
576
- // }
577
+ // const filteredMinMax = getMinMaxGrid(filteredData)
578
+ if (filteredMinMaxValue[0] === filteredMinMaxValue[1] && filteredMinMaxValue[1] === 0) {
579
+ // filteredMinMaxValue[0] = filteredMinMaxValue[1] - 1 // 避免最大及最小值相同造成無法計算scale
580
+ filteredMinMaxValue[1] = 1 // 避免最大及最小值同等於 0 造成無法計算scale
581
+ }
577
582
 
578
583
  const valueAxisWidth = (valueAxis.position === 'left' || valueAxis.position === 'right')
579
584
  ? height
@@ -586,15 +591,22 @@ export const gridGraphicTransformObservable = ({ computedData$, groupScaleDomain
586
591
  scaleDomain: valueAxis.scaleDomain,
587
592
  scaleRange: valueAxis.scaleRange
588
593
  })
589
-
594
+ // console.log({
595
+ // maxValue: filteredMinMaxValue[1],
596
+ // minValue: filteredMinMaxValue[0],
597
+ // axisWidth: valueAxisWidth,
598
+ // scaleDomain: valueAxis.scaleDomain,
599
+ // scaleRange: valueAxis.scaleRange
600
+ // })
590
601
  // -- translateY, scaleY --
591
- const minAndMax = getMinAndMaxGrid(data)
592
- if (minAndMax[0] === minAndMax[1]) {
593
- minAndMax[0] = minAndMax[1] - 1 // 避免最大及最小值相同造成無法計算scale
602
+ const minMax = getMinMaxGrid(data)
603
+ if (minMax[0] === minMax[1] && minMax[1] === 0) {
604
+ // minMax[0] = minMax[1] - 1 // 避免最大及最小值相同造成無法計算scale
605
+ minMax[1] = 1 // 避免最大及最小值同等於 0 造成無法計算scale
594
606
  }
595
- // const rangeMinY = valueScale(minAndMax[0])
596
- const rangeMinY = valueScale(minAndMax[0] > 0 ? 0 : minAndMax[0]) // * 因為原本的座標就是以 0 到最大值或最小值範範圍計算的,所以這邊也是用同樣的方式計算
597
- const rangeMaxY = valueScale(minAndMax[1] < 0 ? 0 : minAndMax[1]) // * 因為原本的座標就是以 0 到最大值或最小值範範圍計算的,所以這邊也是用同樣的方式計算
607
+ // const rangeMinY = valueScale(minMax[0])
608
+ const rangeMinY = valueScale(minMax[0] > 0 ? 0 : minMax[0]) // * 因為原本的座標就是以 0 到最大值或最小值範範圍計算的,所以這邊也是用同樣的方式計算
609
+ const rangeMaxY = valueScale(minMax[1] < 0 ? 0 : minMax[1]) // * 因為原本的座標就是以 0 到最大值或最小值範範圍計算的,所以這邊也是用同樣的方式計算
598
610
  translateY = rangeMinY
599
611
  const gHeight = rangeMaxY - rangeMinY
600
612
  scaleY = gHeight / valueAxisWidth
@@ -622,8 +634,8 @@ export const gridGraphicTransformObservable = ({ computedData$, groupScaleDomain
622
634
  ).subscribe(data => {
623
635
  const dataAreaTransformData = calcGridDataAreaTransform ({
624
636
  data: data.computedData,
625
- groupAxis: data.fullDataFormatter.grid.groupAxis,
626
- valueAxis: data.fullDataFormatter.grid.valueAxis,
637
+ groupAxis: data.fullDataFormatter.groupAxis,
638
+ valueAxis: data.fullDataFormatter.valueAxis,
627
639
  groupScaleDomainValue: data.groupScaleDomainValue,
628
640
  filteredMinMaxValue: data.filteredMinMaxValue,
629
641
  width: data.layout.width,
@@ -47,7 +47,7 @@ import {
47
47
  gridGraphicTransformObservable,
48
48
  gridGraphicReverseScaleObservable,
49
49
  } from './gridObservables'
50
- import { DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT } from '../defaults'
50
+ import { DEFAULT_DATA_FORMATTER_MULTI_GRID_GRID } from '../defaults'
51
51
  import { calcGridContainerLayout } from './orbchartsUtils'
52
52
 
53
53
  // 每一個grid計算出來的所有Observable
@@ -95,7 +95,7 @@ export const multiGridEachDetailObservable = ({ fullDataFormatter$, computedData
95
95
  // 每次重新計算時,清除之前的訂閱
96
96
  destroy$.next(undefined)
97
97
 
98
- const defaultGrid = data.fullDataFormatter.gridList[0] ?? DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT
98
+ const defaultGrid = data.fullDataFormatter.gridList[0] ?? DEFAULT_DATA_FORMATTER_MULTI_GRID_GRID
99
99
 
100
100
  return data.computedData.map((gridComputedData, gridIndex) => {
101
101
 
@@ -104,9 +104,9 @@ export const multiGridEachDetailObservable = ({ fullDataFormatter$, computedData
104
104
  const gridDataFormatter: DataFormatterGrid = {
105
105
  type: 'grid',
106
106
  visibleFilter: data.fullDataFormatter.visibleFilter as any,
107
- grid: {
108
- ...grid
109
- },
107
+ // grid: {
108
+ ...grid,
109
+ // },
110
110
  container: {
111
111
  ...data.fullDataFormatter.container
112
112
  }
@@ -137,7 +137,7 @@ export const multiGridEachDetailObservable = ({ fullDataFormatter$, computedData
137
137
  // )
138
138
 
139
139
  const isSeriesSeprate$ = gridDataFormatter$.pipe(
140
- map(d => d.grid.separateSeries),
140
+ map(d => d.separateSeries),
141
141
  distinctUntilChanged(),
142
142
  shareReplay(1)
143
143
  )
@@ -314,7 +314,7 @@ export const multiGridContainerObservable = ({ computedData$, fullDataFormatter$
314
314
  switchMap(async (d) => d),
315
315
  map(data => {
316
316
 
317
- const defaultGrid = data.fullDataFormatter.gridList[0] ?? DATA_FORMATTER_MULTI_GRID_GRID_DEFAULT
317
+ const defaultGrid = data.fullDataFormatter.gridList[0] ?? DEFAULT_DATA_FORMATTER_MULTI_GRID_GRID
318
318
  const slotAmount = data.computedData.reduce((acc, gridData, gridIndex) => {
319
319
  const grid = data.fullDataFormatter.gridList[gridIndex] ?? defaultGrid
320
320
  const gridSlotAmount = grid.separateSeries
@@ -27,7 +27,7 @@ import type {
27
27
  HighlightTarget,
28
28
  Layout,
29
29
  TransformData } from '../../lib/core-types'
30
- import { getMinAndMax, getMinAndMaxMultiValue } from './orbchartsUtils'
30
+ import { getMinMax, getMinMaxMultiValue } from './orbchartsUtils'
31
31
  import { createValueToAxisScale, createLabelToAxisScale, createAxisToLabelIndexScale } from './d3Scale'
32
32
  import { calcGridContainerLayout } from './orbchartsUtils'
33
33
 
@@ -35,8 +35,8 @@ export const minMaxXYObservable = ({ computedData$ }: { computedData$: Observabl
35
35
  return computedData$.pipe(
36
36
  map(data => {
37
37
  const flatData = data.flat()
38
- const [minX, maxX] = getMinAndMax(flatData.map(d => d.value[0]))
39
- const [minY, maxY] = getMinAndMax(flatData.map(d => d.value[1]))
38
+ const [minX, maxX] = getMinMax(flatData.map(d => d.value[0]))
39
+ const [minY, maxY] = getMinMax(flatData.map(d => d.value[1]))
40
40
  return { minX, maxX, minY, maxY }
41
41
  })
42
42
  )
@@ -51,9 +51,15 @@ export const multiValueComputedLayoutDataObservable = ({ computedData$, minMaxXY
51
51
 
52
52
  // 未篩選範圍前的 scale
53
53
  function createOriginXScale (minMaxXY: { minX: number, maxX: number, minY: number, maxY: number }, layout: Layout) {
54
+ let maxValue = minMaxXY.maxX
55
+ let minValue = minMaxXY.minX
56
+ if (minValue === maxValue && maxValue === 0) {
57
+ // 避免最大及最小值相同造成無法計算scale
58
+ maxValue = 1
59
+ }
54
60
  const valueScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
55
- maxValue: minMaxXY.maxX,
56
- minValue: minMaxXY.minX,
61
+ maxValue,
62
+ minValue,
57
63
  axisWidth: layout.width,
58
64
  scaleDomain: ['auto', 'auto'], // 不使用dataFormatter設定 --> 以0為基準到最大或最小值為範圍( * 如果是使用[minValue, maxValue]的話,在兩者很接近的情況下有可能造成scale倍率過高而svg變型時失真的情況)
59
65
  scaleRange: [0, 1] // 不使用dataFormatter設定
@@ -64,9 +70,15 @@ export const multiValueComputedLayoutDataObservable = ({ computedData$, minMaxXY
64
70
 
65
71
  // 未篩選範圍及visible前的 scale
66
72
  function createOriginYScale (minMaxXY: { minX: number, maxX: number, minY: number, maxY: number }, layout: Layout) {
73
+ let maxValue = minMaxXY.maxY
74
+ let minValue = minMaxXY.minY
75
+ if (minValue === maxValue && maxValue === 0) {
76
+ // 避免最大及最小值相同造成無法計算scale
77
+ maxValue = 1
78
+ }
67
79
  const valueScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
68
- maxValue: minMaxXY.maxY,
69
- minValue: minMaxXY.minY,
80
+ maxValue,
81
+ minValue,
70
82
  axisWidth: layout.height,
71
83
  scaleDomain: ['auto', 'auto'], // 不使用dataFormatter設定 --> 以0為基準到最大或最小值為範圍( * 如果是使用[minValue, maxValue]的話,在兩者很接近的情況下有可能造成scale倍率過高而svg變型時失真的情況)
72
84
  scaleRange: [0, 1], // 不使用dataFormatter設定
@@ -402,7 +414,7 @@ export const filteredMinMaxXYDataObservable = ({ visibleComputedLayoutData$, min
402
414
  let maxYDatum: ComputedLayoutDatumMultiValue | null = null
403
415
  // console.log('data.visibleComputedLayoutData', data.visibleComputedLayoutData)
404
416
  // minX, maxX, minY, maxY 範圍內的最大最小值資料
405
-
417
+ // console.log({ minX, maxX, minY, maxY })
406
418
  for (let categoryData of data.visibleComputedLayoutData) {
407
419
  for (let datum of categoryData) {
408
420
  // 比較矩形範圍(所以 minX, maxX, minY, maxY 要同時比較)
@@ -471,7 +483,7 @@ export const multiValueGraphicTransformObservable = ({ minMaxXY$, filteredMinMax
471
483
  // // minX, maxX, filteredMinX, filteredMaxX
472
484
  // let filteredMinX = 0
473
485
  // let filteredMaxX = 0
474
- // let [minX, maxX] = getMinAndMax(flatData.map(d => d.value[0]))
486
+ // let [minX, maxX] = getMinMax(flatData.map(d => d.value[0]))
475
487
  // if (minX === maxX) {
476
488
  // minX = maxX - 1 // 避免最大及最小值相同造成無法計算scale
477
489
  // }
@@ -496,7 +508,7 @@ export const multiValueGraphicTransformObservable = ({ minMaxXY$, filteredMinMax
496
508
  // // minY, maxY, filteredMinY, filteredMaxY
497
509
  // let filteredMinY = 0
498
510
  // let filteredMaxY = 0
499
- // let [minY, maxY] = getMinAndMax(flatData.map(d => d.value[1]))
511
+ // let [minY, maxY] = getMinMax(flatData.map(d => d.value[1]))
500
512
  // console.log('filteredMinMaxXYData', filteredMinMaxXYData)
501
513
  let { minX, maxX, minY, maxY } = minMaxXY
502
514
  // console.log({ minX, maxX, minY, maxY })
@@ -505,14 +517,6 @@ export const multiValueGraphicTransformObservable = ({ minMaxXY$, filteredMinMax
505
517
  let filteredMinY = filteredMinMaxXYData.minYDatum.value[1] ?? 0
506
518
  let filteredMaxY = filteredMinMaxXYData.maxYDatum.value[1] ?? 0
507
519
 
508
- if (minX === maxX) {
509
- maxX += 1 // 避免最大及最小值相同造成無法計算scale
510
- minX -= 1
511
- }
512
- if (minY === maxY) {
513
- maxY += 1 // 避免最大及最小值相同造成無法計算scale
514
- minY -= 1
515
- }
516
520
  // if (yAxis.scaleDomain[0] === 'auto' && filteredMinY > 0) {
517
521
  // filteredMinY = 0
518
522
  // } else if (typeof yAxis.scaleDomain[0] === 'number') {
@@ -527,15 +531,24 @@ export const multiValueGraphicTransformObservable = ({ minMaxXY$, filteredMinMax
527
531
  // } else {
528
532
  // filteredMaxY = maxY
529
533
  // }
530
- // if (filteredMinX === filteredMaxX) {
531
- // filteredMaxX += 1 // 避免最大及最小值相同造成無法計算scale
532
- // filteredMinX -= 1
533
- // }
534
- // if (filteredMinY === filteredMaxY) {
535
- // filteredMaxY += 1 // 避免最大及最小值相同造成無法計算scale
536
- // filteredMinY -= 1
537
- // }
534
+
538
535
  // console.log({ minX, maxX, minY, maxY, filteredMinX, filteredMaxX, filteredMinY, filteredMaxY })
536
+ if (filteredMinX === filteredMaxX && filteredMaxX === 0) {
537
+ // 避免最大及最小值相同造成無法計算scale
538
+ filteredMaxX = 1
539
+ }
540
+ if (filteredMinY === filteredMaxY && filteredMaxY === 0) {
541
+ // 避免最大及最小值相同造成無法計算scale
542
+ filteredMaxY = 1
543
+ }
544
+ if (minX === maxX && maxX === 0) {
545
+ // 避免最大及最小值相同造成無法計算scale
546
+ maxX = 1
547
+ }
548
+ if (minY === maxY && maxY === 0) {
549
+ // 避免最大及最小值相同造成無法計算scale
550
+ maxY = 1
551
+ }
539
552
  // -- xScale --
540
553
  const xScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
541
554
  maxValue: filteredMaxX,
@@ -568,7 +581,6 @@ export const multiValueGraphicTransformObservable = ({ minMaxXY$, filteredMinMax
568
581
  translateY = rangeMaxY // 最大值的 y 最小(最上方)
569
582
  const gHeight = rangeMinY - rangeMaxY // 最大的 y 減最小的 y
570
583
  scaleY = gHeight / height
571
- // console.log({ gHeight, height, rangeMaxY, rangeMinY, scaleY, translateY })
572
584
 
573
585
  return {
574
586
  translate: [translateX, translateY],
@@ -590,6 +602,13 @@ export const multiValueGraphicTransformObservable = ({ minMaxXY$, filteredMinMax
590
602
  takeUntil(destroy$),
591
603
  switchMap(async (d) => d),
592
604
  ).subscribe(data => {
605
+ if (!data.filteredMinMaxXYData.minXDatum || !data.filteredMinMaxXYData.maxXDatum
606
+ || data.filteredMinMaxXYData.minXDatum.value[0] == null || data.filteredMinMaxXYData.maxXDatum.value[0] == null
607
+ || !data.filteredMinMaxXYData.minYDatum || !data.filteredMinMaxXYData.maxYDatum
608
+ || data.filteredMinMaxXYData.minYDatum.value[1] == null || data.filteredMinMaxXYData.maxYDatum.value[1] == null
609
+ ) {
610
+ return
611
+ }
593
612
  const dataAreaTransformData = calcDataAreaTransform({
594
613
  minMaxXY: data.minMaxXY,
595
614
  filteredMinMaxXYData: data.filteredMinMaxXYData,