@orbcharts/plugins-basic 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.
Files changed (192) hide show
  1. package/LICENSE +200 -200
  2. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseBarStack.d.ts +2 -2
  3. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseBars.d.ts +2 -2
  4. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseBarsTriangle.d.ts +2 -2
  5. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseDots.d.ts +2 -2
  6. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseGroupAxis.d.ts +2 -2
  7. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseLegend.d.ts +1 -1
  8. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseLineAreas.d.ts +3 -3
  9. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseLines.d.ts +3 -3
  10. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseValueAxis.d.ts +3 -2
  11. package/dist/{src → orbcharts-plugins-basic/src}/grid/defaults.d.ts +1 -1
  12. package/dist/{src → orbcharts-plugins-basic/src}/grid/gridObservables.d.ts +5 -5
  13. package/dist/orbcharts-plugins-basic/src/index.d.ts +6 -0
  14. package/dist/orbcharts-plugins-basic/src/multiValue/defaults.d.ts +9 -0
  15. package/dist/orbcharts-plugins-basic/src/multiValue/index.d.ts +8 -0
  16. package/dist/orbcharts-plugins-basic/src/multiValue/multiValueObservables.d.ts +33 -0
  17. package/dist/orbcharts-plugins-basic/src/multiValue/plugins/MultiValueLegend.d.ts +1 -0
  18. package/dist/orbcharts-plugins-basic/src/multiValue/plugins/MultiValueTooltip.d.ts +1 -0
  19. package/dist/orbcharts-plugins-basic/src/multiValue/plugins/Scatter.d.ts +3 -0
  20. package/dist/orbcharts-plugins-basic/src/multiValue/plugins/ScatterBubbles.d.ts +3 -0
  21. package/dist/orbcharts-plugins-basic/src/multiValue/plugins/XYAux.d.ts +3 -0
  22. package/dist/orbcharts-plugins-basic/src/multiValue/plugins/XYAxes.d.ts +3 -0
  23. package/dist/orbcharts-plugins-basic/src/multiValue/plugins/XYZoom.d.ts +1 -0
  24. package/dist/{src → orbcharts-plugins-basic/src}/series/seriesObservables.d.ts +3 -3
  25. package/dist/{src → orbcharts-plugins-basic/src}/utils/observables.d.ts +1 -1
  26. package/dist/{src → orbcharts-plugins-basic/src}/utils/orbchartsUtils.d.ts +3 -3
  27. package/dist/orbcharts-plugins-basic.es.js +11809 -10185
  28. package/dist/orbcharts-plugins-basic.umd.js +66 -34
  29. package/dist/src/index.d.ts +1 -5
  30. package/lib/core-types.ts +7 -7
  31. package/lib/core.ts +6 -6
  32. package/lib/plugins-basic-types.ts +6 -6
  33. package/package.json +44 -44
  34. package/src/base/BaseBarStack.ts +780 -780
  35. package/src/base/BaseBars.ts +765 -765
  36. package/src/base/BaseBarsTriangle.ts +674 -674
  37. package/src/base/BaseDots.ts +464 -515
  38. package/src/base/BaseGroupAxis.ts +679 -679
  39. package/src/base/BaseLegend.ts +684 -680
  40. package/src/base/BaseLineAreas.ts +629 -629
  41. package/src/base/BaseLines.ts +706 -706
  42. package/src/base/BaseTooltip.ts +385 -385
  43. package/src/base/BaseValueAxis.ts +583 -580
  44. package/src/base/types.ts +2 -2
  45. package/src/const.ts +30 -30
  46. package/src/grid/defaults.ts +244 -244
  47. package/src/grid/gridObservables.ts +554 -545
  48. package/src/grid/index.ts +16 -16
  49. package/src/grid/plugins/BarStack.ts +64 -64
  50. package/src/grid/plugins/Bars.ts +69 -69
  51. package/src/grid/plugins/BarsPN.ts +66 -66
  52. package/src/grid/plugins/BarsTriangle.ts +73 -73
  53. package/src/grid/plugins/Dots.ts +68 -68
  54. package/src/grid/plugins/GridLegend.ts +107 -107
  55. package/src/grid/plugins/GridTooltip.ts +66 -66
  56. package/src/grid/plugins/GridZoom.ts +218 -218
  57. package/src/grid/plugins/GroupAux.ts +1103 -1098
  58. package/src/grid/plugins/GroupAxis.ts +97 -97
  59. package/src/grid/plugins/LineAreas.ts +65 -65
  60. package/src/grid/plugins/Lines.ts +59 -59
  61. package/src/grid/plugins/ValueAxis.ts +94 -93
  62. package/src/grid/plugins/ValueStackAxis.ts +96 -95
  63. package/src/index.ts +10 -9
  64. package/src/multiGrid/defaults.ts +224 -224
  65. package/src/multiGrid/index.ts +14 -14
  66. package/src/multiGrid/multiGridObservables.ts +49 -49
  67. package/src/multiGrid/plugins/MultiBarStack.ts +106 -106
  68. package/src/multiGrid/plugins/MultiBars.ts +108 -108
  69. package/src/multiGrid/plugins/MultiBarsTriangle.ts +114 -114
  70. package/src/multiGrid/plugins/MultiDots.ts +102 -102
  71. package/src/multiGrid/plugins/MultiGridLegend.ts +159 -159
  72. package/src/multiGrid/plugins/MultiGridTooltip.ts +66 -66
  73. package/src/multiGrid/plugins/MultiGroupAxis.ts +137 -137
  74. package/src/multiGrid/plugins/MultiLineAreas.ts +107 -107
  75. package/src/multiGrid/plugins/MultiLines.ts +101 -101
  76. package/src/multiGrid/plugins/MultiValueAxis.ts +134 -133
  77. package/src/multiGrid/plugins/MultiValueStackAxis.ts +134 -133
  78. package/src/multiGrid/plugins/OverlappingValueAxes.ts +300 -299
  79. package/src/multiGrid/plugins/OverlappingValueStackAxes.ts +299 -298
  80. package/src/multiValue/defaults.ts +163 -0
  81. package/src/multiValue/index.ts +9 -0
  82. package/src/multiValue/multiValueObservables.ts +258 -0
  83. package/src/multiValue/plugins/MultiValueLegend.ts +107 -0
  84. package/src/multiValue/plugins/MultiValueTooltip.ts +66 -0
  85. package/src/multiValue/plugins/Scatter.ts +426 -0
  86. package/src/multiValue/plugins/ScatterBubbles.ts +551 -0
  87. package/src/multiValue/plugins/XYAux.ts +682 -0
  88. package/src/multiValue/plugins/XYAxes.ts +677 -0
  89. package/src/multiValue/plugins/XYZoom.ts +300 -0
  90. package/src/noneData/defaults.ts +102 -102
  91. package/src/noneData/index.ts +3 -3
  92. package/src/noneData/plugins/Container.ts +27 -27
  93. package/src/noneData/plugins/Tooltip.ts +373 -373
  94. package/src/series/defaults.ts +206 -206
  95. package/src/series/index.ts +9 -9
  96. package/src/series/plugins/Bubbles.ts +603 -603
  97. package/src/series/plugins/Pie.ts +623 -623
  98. package/src/series/plugins/PieEventTexts.ts +283 -283
  99. package/src/series/plugins/PieLabels.ts +640 -640
  100. package/src/series/plugins/Rose.ts +516 -516
  101. package/src/series/plugins/RoseLabels.ts +600 -600
  102. package/src/series/plugins/SeriesLegend.ts +107 -107
  103. package/src/series/plugins/SeriesTooltip.ts +66 -66
  104. package/src/series/seriesObservables.ts +145 -145
  105. package/src/series/seriesUtils.ts +51 -51
  106. package/src/tree/defaults.ts +78 -78
  107. package/src/tree/index.ts +4 -4
  108. package/src/tree/plugins/TreeLegend.ts +100 -107
  109. package/src/tree/plugins/TreeMap.ts +333 -333
  110. package/src/tree/plugins/TreeTooltip.ts +66 -66
  111. package/src/utils/commonUtils.ts +21 -21
  112. package/src/utils/d3Graphics.ts +174 -174
  113. package/src/utils/d3Utils.ts +74 -73
  114. package/src/utils/observables.ts +14 -14
  115. package/src/utils/orbchartsUtils.ts +101 -100
  116. package/tsconfig.base.json +13 -13
  117. package/tsconfig.json +2 -2
  118. package/vite.config.js +22 -22
  119. package/dist/src/base/BaseGroupArea.d.ts +0 -0
  120. package/dist/src/multiValue/plugins/Scatter.d.ts +0 -0
  121. package/dist/src/multiValue/plugins/ScatterAxes.d.ts +0 -0
  122. package/dist/src/relationship/index.d.ts +0 -0
  123. package/src/base/BaseGroupArea.ts +0 -0
  124. package/src/multiValue/plugins/ScatterAxes.ts +0 -0
  125. /package/dist/{lib → orbcharts-plugins-basic/lib}/core-types.d.ts +0 -0
  126. /package/dist/{lib → orbcharts-plugins-basic/lib}/core.d.ts +0 -0
  127. /package/dist/{lib → orbcharts-plugins-basic/lib}/plugins-basic-types.d.ts +0 -0
  128. /package/dist/{src → orbcharts-plugins-basic/src}/base/BaseTooltip.d.ts +0 -0
  129. /package/dist/{src → orbcharts-plugins-basic/src}/base/types.d.ts +0 -0
  130. /package/dist/{src → orbcharts-plugins-basic/src}/const.d.ts +0 -0
  131. /package/dist/{src → orbcharts-plugins-basic/src}/grid/index.d.ts +0 -0
  132. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/BarStack.d.ts +0 -0
  133. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/Bars.d.ts +0 -0
  134. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/BarsPN.d.ts +0 -0
  135. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/BarsTriangle.d.ts +0 -0
  136. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/Dots.d.ts +0 -0
  137. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GridLegend.d.ts +0 -0
  138. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GridTooltip.d.ts +0 -0
  139. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GridZoom.d.ts +0 -0
  140. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GroupAux.d.ts +0 -0
  141. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GroupAxis.d.ts +0 -0
  142. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/LineAreas.d.ts +0 -0
  143. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/Lines.d.ts +0 -0
  144. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/ValueAxis.d.ts +0 -0
  145. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/ValueStackAxis.d.ts +0 -0
  146. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/defaults.d.ts +0 -0
  147. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/index.d.ts +0 -0
  148. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/multiGridObservables.d.ts +0 -0
  149. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiBarStack.d.ts +0 -0
  150. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiBars.d.ts +0 -0
  151. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiBarsTriangle.d.ts +0 -0
  152. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiDots.d.ts +0 -0
  153. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiGridLegend.d.ts +0 -0
  154. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiGridTooltip.d.ts +0 -0
  155. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiGroupAxis.d.ts +0 -0
  156. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiLineAreas.d.ts +0 -0
  157. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiLines.d.ts +0 -0
  158. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiValueAxis.d.ts +0 -0
  159. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiValueStackAxis.d.ts +0 -0
  160. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/OverlappingValueAxes.d.ts +0 -0
  161. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/OverlappingValueStackAxes.d.ts +0 -0
  162. /package/dist/{src/grid → orbcharts-plugins-basic/src/multiValue}/plugins/Ranking.d.ts +0 -0
  163. /package/dist/{src/grid → orbcharts-plugins-basic/src/multiValue}/plugins/RankingAxis.d.ts +0 -0
  164. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/defaults.d.ts +0 -0
  165. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/index.d.ts +0 -0
  166. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/plugins/Container.d.ts +0 -0
  167. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/plugins/Tooltip.d.ts +0 -0
  168. /package/dist/{src/multiValue → orbcharts-plugins-basic/src/relationship}/index.d.ts +0 -0
  169. /package/dist/{src → orbcharts-plugins-basic/src}/relationship/plugins/Relationship.d.ts +0 -0
  170. /package/dist/{src → orbcharts-plugins-basic/src}/series/defaults.d.ts +0 -0
  171. /package/dist/{src → orbcharts-plugins-basic/src}/series/index.d.ts +0 -0
  172. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/Bubbles.d.ts +0 -0
  173. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/Pie.d.ts +0 -0
  174. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/PieEventTexts.d.ts +0 -0
  175. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/PieLabels.d.ts +0 -0
  176. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/Rose.d.ts +0 -0
  177. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/RoseLabels.d.ts +0 -0
  178. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/SeriesLegend.d.ts +0 -0
  179. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/SeriesTooltip.d.ts +0 -0
  180. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/Waffle.d.ts +0 -0
  181. /package/dist/{src → orbcharts-plugins-basic/src}/series/seriesUtils.d.ts +0 -0
  182. /package/dist/{src → orbcharts-plugins-basic/src}/tree/defaults.d.ts +0 -0
  183. /package/dist/{src → orbcharts-plugins-basic/src}/tree/index.d.ts +0 -0
  184. /package/dist/{src → orbcharts-plugins-basic/src}/tree/plugins/TreeLegend.d.ts +0 -0
  185. /package/dist/{src → orbcharts-plugins-basic/src}/tree/plugins/TreeMap.d.ts +0 -0
  186. /package/dist/{src → orbcharts-plugins-basic/src}/tree/plugins/TreeTooltip.d.ts +0 -0
  187. /package/dist/{src → orbcharts-plugins-basic/src}/utils/commonUtils.d.ts +0 -0
  188. /package/dist/{src → orbcharts-plugins-basic/src}/utils/d3Graphics.d.ts +0 -0
  189. /package/dist/{src → orbcharts-plugins-basic/src}/utils/d3Utils.d.ts +0 -0
  190. /package/dist/{vite.config.d.ts → orbcharts-plugins-basic/vite.config.d.ts} +0 -0
  191. /package/src/{grid → multiValue}/plugins/Ranking.ts +0 -0
  192. /package/src/{grid → multiValue}/plugins/RankingAxis.ts +0 -0
@@ -1,1099 +1,1104 @@
1
- import * as d3 from 'd3'
2
- import {
3
- // of,
4
- iif,
5
- EMPTY,
6
- combineLatest,
7
- switchMap,
8
- map,
9
- filter,
10
- first,
11
- takeUntil,
12
- distinctUntilChanged,
13
- shareReplay,
14
- Subject,
15
- Observable } from 'rxjs'
16
- import {
17
- defineGridPlugin } from '../../../lib/core'
18
- import type { DefinePluginConfig } from '../../../lib/core-types'
19
- import type {
20
- TransformData,
21
- DataFormatterGrid,
22
- ChartParams } from '../../../lib/core-types'
23
- import { DEFAULT_GROUP_AREA_PARAMS } from '../defaults'
24
- import { parseTickFormatValue } from '../../utils/d3Utils'
25
- import { measureTextWidth } from '../../utils/commonUtils'
26
- import { getColor, getClassName, getUniID } from '../../utils/orbchartsUtils'
27
- import { d3EventObservable } from '../../utils/observables'
28
- import { gridGroupPosition } from '../gridObservables'
29
- import type { GroupAuxParams } from '../../../lib/plugins-basic-types'
30
- import { gridSelectionsObservable } from '../gridObservables'
31
- import { renderTspansOnAxis } from '../../utils/d3Graphics'
32
- import { LAYER_INDEX_OF_AUX } from '../../const'
33
-
34
- interface LineDatum {
35
- id: string
36
- x1: number
37
- x2: number
38
- y1: number
39
- y2: number
40
- }
41
-
42
- interface LabelDatum {
43
- id: string
44
- text: string
45
- textArr: string[]
46
- textWidth: number
47
- textHeight: number
48
- x: number
49
- y: number
50
- }
51
-
52
- const pluginName = 'GroupAux'
53
- const labelClassName = getClassName(pluginName, 'label-box')
54
-
55
- const pluginConfig: DefinePluginConfig<typeof pluginName, typeof DEFAULT_GROUP_AREA_PARAMS> = {
56
- name: pluginName,
57
- defaultParams: DEFAULT_GROUP_AREA_PARAMS,
58
- layerIndex: LAYER_INDEX_OF_AUX,
59
- validator: (params, { validateColumns }) => {
60
- const result = validateColumns(params, {
61
- showLine: {
62
- toBeTypes: ['boolean']
63
- },
64
- showLabel: {
65
- toBeTypes: ['boolean']
66
- },
67
- lineDashArray: {
68
- toBeTypes: ['string']
69
- },
70
- lineColorType: {
71
- toBeOption: 'ColorType'
72
- },
73
- labelColorType: {
74
- toBeOption: 'ColorType'
75
- },
76
- labelTextColorType: {
77
- toBeOption: 'ColorType'
78
- },
79
- labelTextFormat: {
80
- toBeTypes: ['string', 'Function']
81
- },
82
- labelPadding: {
83
- toBeTypes: ['number']
84
- },
85
- labelRotate: {
86
- toBeTypes: ['number']
87
- }
88
- })
89
- return result
90
- }
91
- }
92
-
93
- function createLineData ({ groupLabel, axisX, axisHeight, fullParams }: {
94
- groupLabel: string
95
- axisX: number
96
- axisHeight: number
97
- fullParams: GroupAuxParams
98
- }): LineDatum[] {
99
- return fullParams.showLine && groupLabel
100
- ? [{
101
- id: groupLabel,
102
- x1: axisX,
103
- x2: axisX,
104
- y1: 0,
105
- y2: axisHeight
106
- }]
107
- : []
108
- }
109
-
110
- function createLabelData ({ groupLabel, axisX, fullParams, textSizePx }: {
111
- groupLabel: string
112
- axisX: number
113
- fullParams: GroupAuxParams
114
- textSizePx: number
115
- }) {
116
- const text = parseTickFormatValue(groupLabel, fullParams.labelTextFormat)
117
- const textArr = text.split('\n')
118
- const maxLengthText = textArr.reduce((acc, current) => current.length > acc.length ? current : acc, '')
119
- const textWidth = measureTextWidth(maxLengthText, textSizePx)
120
- const textHeight = textSizePx * textArr.length
121
- return fullParams.showLabel && groupLabel
122
- ? [{
123
- id: groupLabel,
124
- x: axisX,
125
- y: - fullParams.labelPadding,
126
- text,
127
- textArr,
128
- textWidth,
129
- textHeight
130
- }]
131
- : []
132
- }
133
-
134
- function renderLine ({ selection, pluginName, lineData, fullParams, fullChartParams }: {
135
- selection: d3.Selection<any, string, any, unknown>
136
- pluginName: string
137
- lineData: LineDatum[]
138
- fullParams: GroupAuxParams
139
- fullChartParams: ChartParams
140
- }) {
141
- const gClassName = getClassName(pluginName, 'auxline')
142
- const update = selection
143
- .selectAll<SVGLineElement, LineDatum>(`line.${gClassName}`)
144
- .data(lineData)
145
- const enter = update
146
- .enter()
147
- .append('line')
148
- .classed(gClassName, true)
149
- // .style('stroke', '#E4E7ED')
150
- .style('stroke', d => getColor(fullParams.lineColorType, fullChartParams))
151
- .style('stroke-width', 1)
152
- .style('stroke-dasharray', fullParams.lineDashArray ?? 'none')
153
- .style('pointer-events', 'none')
154
- // .attr('opacity', 0)
155
- const auxLineSelection = update.merge(enter)
156
- // .attr('opacity', (d) => {
157
- // return d.active == true ? 1 : 0
158
- // })
159
- update.exit().remove()
160
- enter
161
- .attr('x1', d => d.x1)
162
- .attr('y1', d => d.y1)
163
- .attr('x2', d => d.x2)
164
- .attr('y2', d => d.y2)
165
- update
166
- .transition()
167
- .duration(50)
168
- .attr('x1', d => d.x1)
169
- .attr('y1', d => d.y1)
170
- .attr('x2', d => d.x2)
171
- .attr('y2', d => d.y2)
172
-
173
- return auxLineSelection
174
- }
175
-
176
- function removeLine (selection: d3.Selection<any, string, any, unknown>) {
177
- const update = selection
178
- .selectAll<SVGLineElement, LineDatum>('line')
179
- .data([])
180
-
181
- update.exit().remove()
182
- }
183
-
184
- function renderLabel ({ selection, labelData, fullParams, fullDataFormatter, fullChartParams, textReverseTransformWithRotate, textSizePx }: {
185
- selection: d3.Selection<any, string, any, unknown>
186
- labelData: LabelDatum[]
187
- fullParams: GroupAuxParams
188
- fullDataFormatter: DataFormatterGrid
189
- fullChartParams: ChartParams
190
- // gridAxesReverseTransformValue: string
191
- textReverseTransformWithRotate: string
192
- textSizePx: number
193
- }) {
194
- // const rectHeight = textSizePx + 6
195
-
196
- const gUpdate = selection
197
- .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
198
- .data(labelData)
199
- const gEnter = gUpdate
200
- .enter()
201
- .append('g')
202
- .classed(labelClassName, true)
203
- .style('cursor', 'pointer')
204
- const axisLabelSelection = gEnter.merge(gUpdate)
205
- gEnter
206
- .attr("transform", (d, i) => {
207
- return `translate(${d.x}, ${d.y})`
208
- })
209
- gUpdate
210
- .transition()
211
- .duration(50)
212
- .attr("transform", (d, i) => {
213
- return `translate(${d.x}, ${d.y})`
214
- })
215
- gUpdate.exit().remove()
216
-
217
- axisLabelSelection.each((datum, i, n) => {
218
- // const rectWidth = measureTextWidth(datum.text, textSizePx) + 12
219
- const rectWidth = datum.textWidth + 12
220
- const rectHeight = datum.textHeight + 6
221
- // -- label偏移位置 --
222
- let rectX = - rectWidth / 2
223
- let rectY = -2
224
- if (fullDataFormatter.grid.groupAxis.position === 'bottom') {
225
- rectX = fullParams.labelRotate
226
- ? - rectWidth + rectHeight // 有傾斜時以末端對齊(+height是為了修正移動太多)
227
- : - rectWidth / 2
228
- rectY = 2
229
- } else if (fullDataFormatter.grid.groupAxis.position === 'left') {
230
- rectX = - rectWidth + 2
231
- rectY = - rectHeight / 2
232
- } else if (fullDataFormatter.grid.groupAxis.position === 'right') {
233
- rectX = - 2
234
- rectY = - rectHeight / 2
235
- } else if (fullDataFormatter.grid.groupAxis.position === 'top') {
236
- rectX = fullParams.labelRotate
237
- ? - rectWidth + rectHeight // 有傾斜時以末端對齊(+height是為了修正移動太多)
238
- : - rectWidth / 2
239
- rectY = - rectHeight + 2
240
- }
241
-
242
- // -- rect --
243
- d3.select(n[i])
244
- .selectAll<SVGRectElement, LabelDatum>('rect')
245
- .data([datum])
246
- .join(
247
- enter => enter.append('rect')
248
- .style('cursor', 'pointer')
249
- .attr('rx', 5)
250
- .attr('ry', 5),
251
- update => update,
252
- exit => exit.remove()
253
- )
254
- .attr('width', d => `${rectWidth}px`)
255
- .attr('height', `${rectHeight}px`)
256
- .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
257
- .attr('x', rectX)
258
- .attr('y', rectY - 3) // 奇怪的偏移修正
259
- .style('transform', textReverseTransformWithRotate)
260
-
261
- // const rectUpdate = d3.select(n[i])
262
- // .selectAll<SVGRectElement, LabelDatum>('rect')
263
- // .data([datum])
264
- // const rectEnter = rectUpdate
265
- // .enter()
266
- // .append('rect')
267
- // .attr('height', `${rectHeight}px`)
268
- // .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
269
- // .attr('x', rectX)
270
- // .attr('y', rectY - 3) // 奇怪的偏移修正
271
- // .attr('rx', 5)
272
- // .attr('ry', 5)
273
- // .style('cursor', 'pointer')
274
- // // .style('pointer-events', 'none')
275
- // const rect = rectUpdate.merge(rectEnter)
276
- // .attr('width', d => `${rectWidth}px`)
277
- // .style('transform', textReverseTransformWithRotate)
278
- // rectUpdate.exit().remove()
279
-
280
- // -- text --
281
- d3.select(n[i])
282
- .selectAll<SVGTextElement, LabelDatum>('text')
283
- .data([datum])
284
- .join(
285
- enter => enter.append('text')
286
- .style('dominant-baseline', 'hanging')
287
- .style('cursor', 'pointer'),
288
- update => update,
289
- exit => exit.remove()
290
- )
291
- .style('transform', textReverseTransformWithRotate)
292
- .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
293
- .attr('font-size', fullChartParams.styles.textSize)
294
- .attr('x', rectX + 6)
295
- .attr('y', rectY)
296
- .each((d, i, n) => {
297
- renderTspansOnAxis(d3.select(n[i]), {
298
- textArr: datum.textArr,
299
- textSizePx,
300
- groupAxisPosition: fullDataFormatter.grid.groupAxis.position
301
- })
302
- })
303
-
304
- // const textUpdate = d3.select(n[i])
305
- // .selectAll<SVGTextElement, LabelDatum>('text')
306
- // .data([datum])
307
- // const textEnter = textUpdate
308
- // .enter()
309
- // .append('text')
310
- // .style('dominant-baseline', 'hanging')
311
- // .style('cursor', 'pointer')
312
- // // .style('pointer-events', 'none')
313
- // const text = textUpdate.merge(textEnter)
314
- // // .text(d => d.text)
315
- // .style('transform', textReverseTransformWithRotate)
316
- // .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
317
- // .attr('font-size', fullChartParams.styles.textSize)
318
- // .attr('x', rectX + 6)
319
- // .attr('y', rectY)
320
- // textUpdate.exit().remove()
321
-
322
- // text.each((d, i, n) => {
323
- // renderTspansOnAxis(d3.select(n[i]), {
324
- // textArr: datum.textArr,
325
- // textSizePx,
326
- // groupAxisPosition: fullDataFormatter.grid.groupAxis.position
327
- // })
328
- // })
329
- })
330
-
331
- return axisLabelSelection
332
- }
333
-
334
- function removeLabel (selection: d3.Selection<any, string, any, unknown>) {
335
- const gUpdate = selection
336
- .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
337
- .data([])
338
-
339
- gUpdate.exit().remove()
340
- }
341
-
342
-
343
- export const GroupAux = defineGridPlugin(pluginConfig)(({ selection, rootSelection, name, subject, observer }) => {
344
- const destroy$ = new Subject()
345
-
346
- let isLabelMouseover = false
347
-
348
- const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
349
- .insert('rect', 'g')
350
- .classed(getClassName(pluginName, 'rect'), true)
351
- .attr('opacity', 0)
352
-
353
- // const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
354
- // .append('g')
355
-
356
- const {
357
- seriesSelection$,
358
- axesSelection$,
359
- defsSelection$,
360
- graphicGSelection$
361
- } = gridSelectionsObservable({
362
- selection,
363
- pluginName,
364
- clipPathID: 'test',
365
- seriesLabels$: observer.isSeriesSeprate$.pipe(
366
- switchMap(isSeriesSeprate => {
367
- return iif(
368
- () => isSeriesSeprate,
369
- observer.seriesLabels$,
370
- // 如果沒分開的話只取一筆
371
- observer.seriesLabels$.pipe(
372
- map(d => [d[0]])
373
- )
374
- )
375
- })
376
- ),
377
- gridContainerPosition$: observer.gridContainerPosition$,
378
- gridAxesTransform$: observer.gridAxesTransform$,
379
- gridGraphicTransform$: observer.gridGraphicTransform$
380
- })
381
-
382
- observer.layout$.pipe(
383
- takeUntil(destroy$),
384
- ).subscribe(d => {
385
- rootRectSelection
386
- .attr('width', d.rootWidth)
387
- .attr('height', d.rootHeight)
388
- })
389
-
390
- // observer.gridAxesTransform$
391
- // .pipe(
392
- // takeUntil(destroy$),
393
- // map(d => d.value),
394
- // distinctUntilChanged()
395
- // ).subscribe(d => {
396
- // axisSelection
397
- // .style('transform', d)
398
- // })
399
-
400
- // const visibleComputedData$ = observer.computedData$.pipe(
401
- // takeUntil(destroy$),
402
- // map(data => {
403
- // const visibleComputedData = data
404
- // .map(d => {
405
- // return d.filter(_d => {
406
- // return _d.visible == true
407
- // })
408
- // })
409
- // .filter(d => d.length)
410
- // // console.log('visibleComputedData', visibleComputedData)
411
- // return visibleComputedData
412
- // })
413
- // )
414
-
415
- // const SeriesDataMap$ = visibleComputedData$.pipe(
416
- // map(d => makeGridSeriesDataMap(d))
417
- // )
418
-
419
- // const GroupDataMap$ = visibleComputedData$.pipe(
420
- // map(d => makeGridGroupDataMap(d))
421
- // )
422
-
423
- // const contentTransform$: Observable<string> = new Observable(subscriber => {
424
- // combineLatest({
425
- // fullParams: observer.fullParams$,
426
- // gridAxesTransform: observer.gridAxesTransform$
427
- // }).pipe(
428
- // takeUntil(destroy$),
429
- // // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
430
- // switchMap(async (d) => d),
431
- // ).subscribe(data => {
432
-
433
- // const transformData = Object.assign({}, data.gridAxesTransform)
434
-
435
- // // const value = getAxesTransformValue({
436
- // // translate: [0, 0],
437
- // // scale: [transformData.scale[0] * -1, transformData.scale[1] * -1],
438
- // // rotate: transformData.rotate * -1,
439
- // // rotateX: transformData.rotateX * -1,
440
- // // rotateY: transformData.rotateY * -1
441
- // // })
442
-
443
- // subscriber.next(transformData.value)
444
- // })
445
- // })
446
- // const reverseTransform$: Observable<TransformData> = observer.gridAxesTransform$.pipe(
447
- // takeUntil(destroy$),
448
- // map(d => {
449
- // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
450
- // const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
451
- // const rotate = d.rotate * -1
452
- // const rotateX = d.rotateX * -1
453
- // const rotateY = d.rotateY * -1
454
- // return {
455
- // translate,
456
- // scale,
457
- // rotate,
458
- // rotateX,
459
- // rotateY,
460
- // value: ''
461
- // }
462
- // }),
463
- // )
464
- // const contentTransform$ = combineLatest({
465
- // fullParams: observer.fullParams$,
466
- // reverseTransform: reverseTransform$
467
- // }).pipe(
468
- // takeUntil(destroy$),
469
- // switchMap(async data => {
470
- // const translate = [0, 0]
471
- // return `translate(${translate[0]}px, ${translate[1]}px) rotate(${data.reverseTransform.rotate}deg) rotateX(${data.reverseTransform.rotateX}deg) rotateY(${data.reverseTransform.rotateY}deg)`
472
- // }),
473
- // distinctUntilChanged()
474
- // )
475
-
476
- // const groupScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
477
- // combineLatest({
478
- // fullDataFormatter: observer.fullDataFormatter$,
479
- // gridAxesSize: observer.gridAxesSize$,
480
- // computedData: observer.computedData$
481
- // }).pipe(
482
- // takeUntil(destroy$),
483
- // switchMap(async (d) => d),
484
- // ).subscribe(data => {
485
- // const groupMin = 0
486
- // const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
487
- // const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
488
- // ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
489
- // : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
490
- // const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
491
- // ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
492
- // : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
493
-
494
- // const groupingLength = data.computedData[0]
495
- // ? data.computedData[0].length
496
- // : 0
497
-
498
- // let _labels = data.fullDataFormatter.grid.seriesDirection === 'row'
499
- // // ? data.fullDataFormatter.grid.columnLabels
500
- // // : data.fullDataFormatter.grid.rowLabels
501
- // ? (data.computedData[0] ?? []).map(d => d.groupLabel)
502
- // : data.computedData.map(d => d[0].groupLabel)
503
-
504
- // const axisLabels = new Array(groupingLength).fill(0)
505
- // .map((d, i) => {
506
- // return _labels[i] != null
507
- // ? _labels[i]
508
- // : String(i) // 沒有label則用序列號填充
509
- // })
510
- // .filter((d, i) => {
511
- // return i >= groupScaleDomainMin && i <= groupScaleDomainMax
512
- // })
513
-
514
-
515
- // const padding = data.fullDataFormatter.grid.groupAxis.scalePadding
516
-
517
- // const groupScale = createAxisPointScale({
518
- // axisLabels,
519
- // axisWidth: data.gridAxesSize.width,
520
- // padding
521
- // })
522
-
523
- // subscriber.next(groupScale)
524
- // })
525
- // })
526
-
527
- const groupScaleDomain$ = combineLatest({
528
- fullDataFormatter: observer.fullDataFormatter$,
529
- gridAxesSize: observer.gridAxesSize$,
530
- computedData: observer.computedData$
531
- }).pipe(
532
- takeUntil(destroy$),
533
- switchMap(async (d) => d),
534
- map(data => {
535
- const groupMin = 0
536
- const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
537
- // const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
538
- // ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
539
- // : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
540
- const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] - data.fullDataFormatter.grid.groupAxis.scalePadding
541
- const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'max'
542
- ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
543
- : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
544
-
545
- return [groupScaleDomainMin, groupScaleDomainMax]
546
- }),
547
- shareReplay(1)
548
- )
549
-
550
- const groupScale$ = combineLatest({
551
- groupScaleDomain: groupScaleDomain$,
552
- gridAxesSize: observer.gridAxesSize$
553
- }).pipe(
554
- takeUntil(destroy$),
555
- switchMap(async (d) => d),
556
- map(data => {
557
- const groupScale: d3.ScaleLinear<number, number> = d3.scaleLinear()
558
- .domain(data.groupScaleDomain)
559
- .range([0, data.gridAxesSize.width])
560
- return groupScale
561
- })
562
- )
563
-
564
- // // 取得事件座標的group資料
565
- // const gridGroupPositionFn$ = gridGroupPositionFnObservable({
566
- // fullDataFormatter$: observer.fullDataFormatter$,
567
- // gridAxesSize$: observer.gridAxesSize$,
568
- // computedData$: observer.computedData$,
569
- // fullChartParams$: observer.fullChartParams$,
570
- // })
571
-
572
- const highlightTarget$ = observer.fullChartParams$.pipe(
573
- takeUntil(destroy$),
574
- map(d => d.highlightTarget),
575
- distinctUntilChanged()
576
- )
577
-
578
- // combineLatest({
579
- // computedData: observer.computedData$,
580
- // gridAxesSize: observer.gridAxesSize$,
581
- // fullParams: observer.fullParams$,
582
- // fullChartParams: observer.fullChartParams$,
583
- // highlightTarget: highlightTarget$,
584
- // SeriesDataMap: observer.SeriesDataMap$,
585
- // GroupDataMap: observer.GroupDataMap$,
586
- // gridGroupPositionFn: gridGroupPositionFn$,
587
- // groupScale: groupScale$,
588
- // }).pipe(
589
- // takeUntil(destroy$),
590
- // switchMap(async (d) => d),
591
- // ).subscribe(data => {
592
-
593
- // // store.selection
594
- // rootSelection
595
- // .on('mouseover', (event, datum) => {
596
- // // event.stopPropagation()
597
-
598
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
599
-
600
- // subject.event$.next({
601
- // type: 'grid',
602
- // pluginName: name,
603
- // eventName: 'mouseover',
604
- // highlightTarget: data.highlightTarget,
605
- // datum: null,
606
- // gridIndex: 0, // @Q@ 暫不處理
607
- // series: [],
608
- // seriesIndex: -1,
609
- // seriesLabel: '',
610
- // groups: data.GroupDataMap.get(groupLabel) ?? [],
611
- // // groups: [],
612
- // groupIndex,
613
- // groupLabel,
614
- // event,
615
- // data: data.computedData
616
- // })
617
- // })
618
- // .on('mousemove', (event, datum) => {
619
- // // event.stopPropagation()
620
-
621
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
622
-
623
- // subject.event$.next({
624
- // type: 'grid',
625
- // pluginName: name,
626
- // eventName: 'mousemove',
627
- // highlightTarget: data.highlightTarget,
628
- // datum: null,
629
- // gridIndex: 0, // @Q@ 暫不處理
630
- // series: [],
631
- // seriesIndex: -1,
632
- // seriesLabel: '',
633
- // groups: data.GroupDataMap.get(groupLabel) ?? [],
634
- // // groups: [],
635
- // groupIndex,
636
- // groupLabel,
637
- // event,
638
- // data: data.computedData
639
- // })
640
- // })
641
- // .on('mouseout', (event, datum) => {
642
- // // event.stopPropagation()
643
-
644
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
645
-
646
- // subject.event$.next({
647
- // type: 'grid',
648
- // pluginName: name,
649
- // eventName: 'mouseout',
650
- // highlightTarget: data.highlightTarget,
651
- // datum: null,
652
- // gridIndex: 0, // @Q@ 暫不處理
653
- // series: [],
654
- // seriesIndex: -1,
655
- // seriesLabel: '',
656
- // groups: data.GroupDataMap.get(groupLabel) ?? [],
657
- // // groups: [],
658
- // groupIndex,
659
- // groupLabel,
660
- // event,
661
- // data: data.computedData
662
- // })
663
- // })
664
- // .on('click', (event, datum) => {
665
- // event.stopPropagation()
666
-
667
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
668
-
669
- // subject.event$.next({
670
- // type: 'grid',
671
- // pluginName: name,
672
- // eventName: 'click',
673
- // highlightTarget: data.highlightTarget,
674
- // datum: null,
675
- // gridIndex: 0, // @Q@ 暫不處理
676
- // series: [],
677
- // seriesIndex: -1,
678
- // seriesLabel: '',
679
- // // groups: data.GroupDataMap.get(groupLabel) ?? [],
680
- // groups: [],
681
- // groupIndex,
682
- // groupLabel,
683
- // event,
684
- // data: data.computedData
685
- // })
686
- // })
687
-
688
- // // barSelection$.next(barSelection!)
689
- // })
690
-
691
- const rootMousemove$: Observable<any> = d3EventObservable(rootSelection, 'mousemove').pipe(
692
- takeUntil(destroy$),
693
- )
694
-
695
- // const mousemoveGroupLabel$ = combineLatest({
696
- // rootMousemove: rootMousemove$,
697
- // gridGroupPositionFn: gridGroupPositionFn$,
698
- // }).pipe(
699
- // takeUntil(destroy$),
700
- // switchMap(async d => d),
701
- // map(data => {
702
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(data.rootMousemove)
703
- // return { groupIndex, groupLabel }
704
- // }),
705
- // shareReplay(1)
706
- // )
707
-
708
-
709
- const textReverseTransform$ = combineLatest({
710
- gridAxesReverseTransform: observer.gridAxesReverseTransform$,
711
- gridContainerPosition: observer.gridContainerPosition$
712
- }).pipe(
713
- takeUntil(destroy$),
714
- switchMap(async (d) => d),
715
- map(data => {
716
- // const axisReverseTranslateValue = `translate(${data.gridAxesReverseTransform.translate[0]}px, ${data.gridAxesReverseTransform.translate[1]}px)`
717
- const axesRotateXYReverseValue = `rotateX(${data.gridAxesReverseTransform.rotateX}deg) rotateY(${data.gridAxesReverseTransform.rotateY}deg)`
718
- const axesRotateReverseValue = `rotate(${data.gridAxesReverseTransform.rotate}deg)`
719
- const containerScaleReverseValue = `scale(${1 / data.gridContainerPosition[0].scale[0]}, ${1 / data.gridContainerPosition[0].scale[1]})`
720
- // 必須按照順序(先抵消外層rotate,再抵消最外層scale)
721
- return `${axesRotateXYReverseValue} ${axesRotateReverseValue} ${containerScaleReverseValue}`
722
- }),
723
- distinctUntilChanged()
724
- )
725
-
726
- const textReverseTransformWithRotate$ = combineLatest({
727
- textReverseTransform: textReverseTransform$,
728
- fullParams: observer.fullParams$,
729
- }).pipe(
730
- takeUntil(destroy$),
731
- switchMap(async (d) => d),
732
- map(data => {
733
- // 必須按照順序(先抵消外層rotate,再抵消最外層scale,最後再做本身的rotate)
734
- return `${data.textReverseTransform} rotate(${data.fullParams.labelRotate}deg)`
735
- })
736
- )
737
-
738
- const columnAmount$ = observer.gridContainerPosition$.pipe(
739
- takeUntil(destroy$),
740
- map(gridContainerPosition => {
741
- const maxColumnIndex = gridContainerPosition.reduce((acc, current) => {
742
- return current.columnIndex > acc ? current.columnIndex : acc
743
- }, 0)
744
- return maxColumnIndex + 1
745
- }),
746
- distinctUntilChanged()
747
- )
748
-
749
- const rowAmount$ = observer.gridContainerPosition$.pipe(
750
- takeUntil(destroy$),
751
- map(gridContainerPosition => {
752
- const maxRowIndex = gridContainerPosition.reduce((acc, current) => {
753
- return current.rowIndex > acc ? current.rowIndex : acc
754
- }, 0)
755
- return maxRowIndex + 1
756
- }),
757
- distinctUntilChanged()
758
- )
759
-
760
- const gridGroupPosition$ = gridGroupPosition({
761
- rootSelection,
762
- fullDataFormatter$: observer.fullDataFormatter$,
763
- gridAxesSize$: observer.gridAxesSize$,
764
- computedData$: observer.computedData$,
765
- fullChartParams$: observer.fullChartParams$,
766
- gridContainerPosition$: observer.gridContainerPosition$,
767
- layout$: observer.layout$
768
- }).pipe(
769
- takeUntil(destroy$)
770
- )
771
-
772
- combineLatest({
773
- axesSelection: axesSelection$,
774
- columnAmount: columnAmount$,
775
- rowAmount: rowAmount$,
776
- layout: observer.layout$,
777
- rootMousemove: rootMousemove$,
778
- // gridGroupPositionFn: gridGroupPositionFn$,
779
- gridGroupPosition: gridGroupPosition$,
780
- computedData: observer.computedData$,
781
- groupScale: groupScale$,
782
- gridAxesSize: observer.gridAxesSize$,
783
- fullParams: observer.fullParams$,
784
- fullDataFormatter: observer.fullDataFormatter$,
785
- fullChartParams: observer.fullChartParams$,
786
- highlightTarget: highlightTarget$,
787
- // gridAxesReverseTransform: observer.gridAxesReverseTransform$,
788
- textReverseTransformWithRotate: textReverseTransformWithRotate$,
789
- GroupDataMap: observer.GroupDataMap$,
790
- textSizePx: observer.textSizePx$
791
- }).pipe(
792
- takeUntil(destroy$),
793
- switchMap(async d => d),
794
- ).subscribe(data => {
795
- // // 由於event座標是基於底層的,但是container會有多欄,所以要重新計算
796
- // const eventData = {
797
- // offsetX: data.rootMousemove.offsetX * data.columnAmount % data.layout.rootWidth,
798
- // offsetY: data.rootMousemove.offsetY * data.rowAmount % data.layout.rootHeight
799
- // }
800
- // 依event的座標取得group資料
801
- const { groupIndex, groupLabel } = data.gridGroupPosition
802
- // console.log('gridGroupPosition', groupIndex, groupLabel)
803
- const axisX = data.groupScale(groupIndex) ?? 0
804
- // console.log('axisX', axisX)
805
- const lineData = createLineData({
806
- groupLabel: groupLabel,
807
- axisX,
808
- axisHeight: data.gridAxesSize.height,
809
- fullParams: data.fullParams,
810
- })
811
- // console.log('lineData', lineData)
812
- renderLine({
813
- // selection: axisSelection,
814
- selection: data.axesSelection,
815
- pluginName: name,
816
- lineData,
817
- fullParams: data.fullParams,
818
- fullChartParams: data.fullChartParams
819
- })
820
- const labelData = createLabelData({
821
- groupLabel: groupLabel,
822
- axisX,
823
- fullParams: data.fullParams,
824
- textSizePx: data.textSizePx
825
- })
826
- const labelSelection = renderLabel({
827
- // selection: axisSelection,
828
- selection: data.axesSelection,
829
- labelData,
830
- fullParams: data.fullParams,
831
- fullDataFormatter: data.fullDataFormatter,
832
- fullChartParams: data.fullChartParams,
833
- // gridAxesReverseTransformValue: data.gridAxesReverseTransform.value,
834
- textReverseTransformWithRotate: data.textReverseTransformWithRotate,
835
- textSizePx: data.textSizePx
836
- })
837
-
838
- // label的事件
839
- labelSelection
840
- .on('mouseover', (event, datum) => {
841
- event.stopPropagation()
842
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
843
-
844
- isLabelMouseover = true
845
-
846
- subject.event$.next({
847
- type: 'grid',
848
- pluginName: name,
849
- eventName: 'mouseover',
850
- highlightTarget: data.highlightTarget,
851
- datum: null,
852
- gridIndex: 0, // @Q@ 暫不處理
853
- series: [],
854
- seriesIndex: -1,
855
- seriesLabel: '',
856
- groups: data.GroupDataMap.get(groupLabel) ?? [],
857
- groupIndex,
858
- groupLabel,
859
- event,
860
- data: data.computedData
861
- })
862
- })
863
- .on('mousemove', (event, datum) => {
864
- event.stopPropagation()
865
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
866
-
867
- subject.event$.next({
868
- type: 'grid',
869
- pluginName: name,
870
- eventName: 'mousemove',
871
- highlightTarget: data.highlightTarget,
872
- datum: null,
873
- gridIndex: 0, // @Q@ 暫不處理
874
- series: [],
875
- seriesIndex: -1,
876
- seriesLabel: '',
877
- groups: data.GroupDataMap.get(groupLabel) ?? [],
878
- groupIndex,
879
- groupLabel,
880
- event,
881
- data: data.computedData
882
- })
883
- })
884
- .on('mouseout', (event, datum) => {
885
- event.stopPropagation()
886
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
887
-
888
- isLabelMouseover = false
889
-
890
- subject.event$.next({
891
- type: 'grid',
892
- pluginName: name,
893
- eventName: 'mouseout',
894
- highlightTarget: data.highlightTarget,
895
- datum: null,
896
- gridIndex: 0, // @Q@ 暫不處理
897
- series: [],
898
- seriesIndex: -1,
899
- seriesLabel: '',
900
- groups: data.GroupDataMap.get(groupLabel) ?? [],
901
- groupIndex,
902
- groupLabel,
903
- event,
904
- data: data.computedData
905
- })
906
- })
907
- .on('click', (event, datum) => {
908
- event.stopPropagation()
909
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
910
-
911
- subject.event$.next({
912
- type: 'grid',
913
- pluginName: name,
914
- eventName: 'click',
915
- highlightTarget: data.highlightTarget,
916
- datum: null,
917
- gridIndex: 0, // @Q@ 暫不處理
918
- series: [],
919
- seriesIndex: -1,
920
- seriesLabel: '',
921
- groups: data.GroupDataMap.get(groupLabel) ?? [],
922
- groupIndex,
923
- groupLabel,
924
- event,
925
- data: data.computedData
926
- })
927
- })
928
-
929
- })
930
-
931
- // // -- highlight(無論highlightTarget設定為何,一律依從groupLabel來顯示) --
932
- // combineLatest({
933
- // event: subject.event$.pipe(
934
- // filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove')
935
- // ),
936
- // computedData: observer.computedData$,
937
- // groupScale: groupScale$,
938
- // gridAxesSize: observer.gridAxesSize$,
939
- // fullParams: observer.fullParams$,
940
- // fullChartParams: observer.fullChartParams$,
941
- // highlightTarget: highlightTarget$,
942
- // gridAxesReverseTransform: observer.gridAxesReverseTransform$,
943
- // GroupDataMap: observer.GroupDataMap$,
944
- // gridGroupPositionFn: gridGroupPositionFn$,
945
- // textSizePx: observer.textSizePx$
946
- // }).pipe(
947
- // takeUntil(destroy$),
948
- // switchMap(async d => d)
949
- // ).subscribe(data => {
950
- // // const groups = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
951
- // // ? data.event.groups
952
- // // : []
953
-
954
- // // const groupLabel = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
955
- // // ? data.event.groupLabel
956
- // // : ''
957
- // const axisX = data.groupScale(data.event.groupLabel) ?? 0
958
-
959
- // const lineData = createLineData({
960
- // groupLabel: data.event.groupLabel,
961
- // axisX,
962
- // axisHeight: data.gridAxesSize.height,
963
- // fullParams: data.fullParams,
964
- // })
965
- // renderLine({
966
- // selection: axisSelection,
967
- // pluginName: name,
968
- // lineData,
969
- // fullParams: data.fullParams,
970
- // fullChartParams: data.fullChartParams
971
- // })
972
- // const labelData = createLabelData({
973
- // groupLabel: data.event.groupLabel,
974
- // axisX,
975
- // fullParams: data.fullParams
976
- // })
977
- // const labelSelection = renderLabel({
978
- // selection: axisSelection,
979
- // labelData,
980
- // fullParams: data.fullParams,
981
- // fullChartParams: data.fullChartParams,
982
- // gridAxesReverseTransformValue: data.gridAxesReverseTransform.value,
983
- // textSizePx: data.textSizePx
984
- // })
985
-
986
- // // label的事件
987
- // labelSelection
988
- // .on('mouseover', (event, datum) => {
989
-
990
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
991
-
992
- // subject.event$.next({
993
- // type: 'grid',
994
- // pluginName: name,
995
- // eventName: 'mouseover',
996
- // highlightTarget: data.highlightTarget,
997
- // datum: null,
998
- // gridIndex: 0, // @Q@ 暫不處理
999
- // series: [],
1000
- // seriesIndex: -1,
1001
- // seriesLabel: '',
1002
- // groups: data.event.groups,
1003
- // groupIndex,
1004
- // groupLabel,
1005
- // event,
1006
- // data: data.computedData
1007
- // })
1008
- // })
1009
- // .on('mousemove', (event, datum) => {
1010
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
1011
-
1012
- // subject.event$.next({
1013
- // type: 'grid',
1014
- // pluginName: name,
1015
- // eventName: 'mousemove',
1016
- // highlightTarget: data.highlightTarget,
1017
- // datum: null,
1018
- // gridIndex: 0, // @Q@ 暫不處理
1019
- // series: [],
1020
- // seriesIndex: -1,
1021
- // seriesLabel: '',
1022
- // groups: data.event.groups,
1023
- // groupIndex,
1024
- // groupLabel,
1025
- // event,
1026
- // data: data.computedData
1027
- // })
1028
- // })
1029
- // .on('mouseout', (event, datum) => {
1030
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
1031
-
1032
- // subject.event$.next({
1033
- // type: 'grid',
1034
- // pluginName: name,
1035
- // eventName: 'mouseout',
1036
- // highlightTarget: data.highlightTarget,
1037
- // datum: null,
1038
- // gridIndex: 0, // @Q@ 暫不處理
1039
- // series: [],
1040
- // seriesIndex: -1,
1041
- // seriesLabel: '',
1042
- // groups: data.event.groups,
1043
- // groupIndex,
1044
- // groupLabel,
1045
- // event,
1046
- // data: data.computedData
1047
- // })
1048
- // })
1049
- // .on('click', (event, datum) => {
1050
- // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
1051
-
1052
- // subject.event$.next({
1053
- // type: 'grid',
1054
- // pluginName: name,
1055
- // eventName: 'click',
1056
- // highlightTarget: data.highlightTarget,
1057
- // datum: null,
1058
- // gridIndex: 0, // @Q@ 暫不處理
1059
- // series: [],
1060
- // seriesIndex: -1,
1061
- // seriesLabel: '',
1062
- // groups: data.event.groups,
1063
- // groupIndex,
1064
- // groupLabel,
1065
- // event,
1066
- // data: data.computedData
1067
- // })
1068
- // })
1069
- // })
1070
-
1071
-
1072
-
1073
- const rootRectMouseout$ = d3EventObservable(rootRectSelection, 'mouseout').pipe(
1074
- takeUntil(destroy$),
1075
- )
1076
-
1077
- combineLatest({
1078
- rootRectMouseout: rootRectMouseout$,
1079
- axesSelection: axesSelection$,
1080
- }).pipe(
1081
- takeUntil(destroy$),
1082
- switchMap(async d => d)
1083
- ).subscribe(data => {
1084
- setTimeout(() => {
1085
- // @Q@ workaround - 不知為何和 label 會有衝突,當滑鼠移動到 label 上時,會觸發 mouseout 事件
1086
- if (isLabelMouseover == true) {
1087
- return
1088
- }
1089
-
1090
- removeLine(data.axesSelection)
1091
- removeLabel(data.axesSelection)
1092
- })
1093
- })
1094
-
1095
- return () => {
1096
- destroy$.next(undefined)
1097
- rootRectSelection.remove()
1098
- }
1
+ import * as d3 from 'd3'
2
+ import {
3
+ // of,
4
+ iif,
5
+ EMPTY,
6
+ combineLatest,
7
+ switchMap,
8
+ map,
9
+ filter,
10
+ first,
11
+ takeUntil,
12
+ distinctUntilChanged,
13
+ shareReplay,
14
+ Subject,
15
+ Observable } from 'rxjs'
16
+ import {
17
+ defineGridPlugin } from '../../../lib/core'
18
+ import type { DefinePluginConfig } from '../../../lib/core-types'
19
+ import type {
20
+ TransformData,
21
+ DataFormatterGrid,
22
+ ChartParams } from '../../../lib/core-types'
23
+ import { DEFAULT_GROUP_AUX_PARAMS } from '../defaults'
24
+ import { parseTickFormatValue } from '../../utils/d3Utils'
25
+ import { measureTextWidth } from '../../utils/commonUtils'
26
+ import { getColor, getClassName, getUniID } from '../../utils/orbchartsUtils'
27
+ import { d3EventObservable } from '../../utils/observables'
28
+ import { gridGroupPositionObservable } from '../gridObservables'
29
+ import type { GroupAuxParams } from '../../../lib/plugins-basic-types'
30
+ import { gridSelectionsObservable } from '../gridObservables'
31
+ import { renderTspansOnAxis } from '../../utils/d3Graphics'
32
+ import { LAYER_INDEX_OF_AUX } from '../../const'
33
+
34
+ interface LineDatum {
35
+ id: string
36
+ x1: number
37
+ x2: number
38
+ y1: number
39
+ y2: number
40
+ }
41
+
42
+ interface LabelDatum {
43
+ id: string
44
+ text: string
45
+ textArr: string[]
46
+ textWidth: number
47
+ textHeight: number
48
+ x: number
49
+ y: number
50
+ }
51
+
52
+ const pluginName = 'GroupAux'
53
+ const labelClassName = getClassName(pluginName, 'label-box')
54
+
55
+ const pluginConfig: DefinePluginConfig<typeof pluginName, typeof DEFAULT_GROUP_AUX_PARAMS> = {
56
+ name: pluginName,
57
+ defaultParams: DEFAULT_GROUP_AUX_PARAMS,
58
+ layerIndex: LAYER_INDEX_OF_AUX,
59
+ validator: (params, { validateColumns }) => {
60
+ const result = validateColumns(params, {
61
+ showLine: {
62
+ toBeTypes: ['boolean']
63
+ },
64
+ showLabel: {
65
+ toBeTypes: ['boolean']
66
+ },
67
+ lineDashArray: {
68
+ toBeTypes: ['string']
69
+ },
70
+ lineColorType: {
71
+ toBeOption: 'ColorType'
72
+ },
73
+ labelColorType: {
74
+ toBeOption: 'ColorType'
75
+ },
76
+ labelTextColorType: {
77
+ toBeOption: 'ColorType'
78
+ },
79
+ labelTextFormat: {
80
+ toBeTypes: ['string', 'Function']
81
+ },
82
+ labelPadding: {
83
+ toBeTypes: ['number']
84
+ },
85
+ labelRotate: {
86
+ toBeTypes: ['number']
87
+ }
88
+ })
89
+ return result
90
+ }
91
+ }
92
+
93
+ function createLineData ({ groupLabel, axisX, axisHeight, fullParams }: {
94
+ groupLabel: string
95
+ axisX: number
96
+ axisHeight: number
97
+ fullParams: GroupAuxParams
98
+ }): LineDatum[] {
99
+ return fullParams.showLine && groupLabel
100
+ ? [{
101
+ id: groupLabel,
102
+ x1: axisX,
103
+ x2: axisX,
104
+ y1: 0,
105
+ y2: axisHeight
106
+ }]
107
+ : []
108
+ }
109
+
110
+ function createLabelData ({ groupLabel, axisX, fullParams, textSizePx, rowAmount }: {
111
+ groupLabel: string
112
+ axisX: number
113
+ fullParams: GroupAuxParams
114
+ textSizePx: number
115
+ rowAmount: number
116
+ }) {
117
+ const text = parseTickFormatValue(groupLabel, fullParams.labelTextFormat)
118
+ const textArr = text.split('\n')
119
+ const maxLengthText = textArr.reduce((acc, current) => current.length > acc.length ? current : acc, '')
120
+ const textWidth = measureTextWidth(maxLengthText, textSizePx)
121
+ const textHeight = textSizePx * textArr.length
122
+ return fullParams.showLabel && groupLabel
123
+ ? [{
124
+ id: groupLabel,
125
+ x: axisX,
126
+ y: - fullParams.labelPadding * rowAmount, // rowAmount 是為了把外部 container 的變形逆轉回來
127
+ text,
128
+ textArr,
129
+ textWidth,
130
+ textHeight
131
+ }]
132
+ : []
133
+ }
134
+
135
+ function renderLine ({ selection, pluginName, lineData, fullParams, fullChartParams }: {
136
+ selection: d3.Selection<any, string, any, unknown>
137
+ pluginName: string
138
+ lineData: LineDatum[]
139
+ fullParams: GroupAuxParams
140
+ fullChartParams: ChartParams
141
+ }) {
142
+ const gClassName = getClassName(pluginName, 'auxline')
143
+ const auxLineSelection = selection
144
+ .selectAll<SVGLineElement, LineDatum>(`line.${gClassName}`)
145
+ .data(lineData)
146
+ .join(
147
+ enter => {
148
+ return enter
149
+ .append('line')
150
+ .classed(gClassName, true)
151
+ .style('stroke-width', 1)
152
+ .style('pointer-events', 'none')
153
+ .style('vector-effect', 'non-scaling-stroke')
154
+ .attr('x1', d => d.x1)
155
+ .attr('y1', d => d.y1)
156
+ .attr('x2', d => d.x2)
157
+ .attr('y2', d => d.y2)
158
+ },
159
+ update => {
160
+ const updateSelection = update
161
+ .transition()
162
+ .duration(50)
163
+ .attr('x1', d => d.x1)
164
+ .attr('y1', d => d.y1)
165
+ .attr('x2', d => d.x2)
166
+ .attr('y2', d => d.y2)
167
+ return updateSelection
168
+ },
169
+ exit => exit.remove()
170
+ )
171
+ .style('stroke', d => getColor(fullParams.lineColorType, fullChartParams))
172
+ .style('stroke-dasharray', fullParams.lineDashArray ?? 'none')
173
+
174
+ return auxLineSelection
175
+ }
176
+
177
+ function removeLine (selection: d3.Selection<any, string, any, unknown>) {
178
+ const update = selection
179
+ .selectAll<SVGLineElement, LineDatum>('line')
180
+ .data([])
181
+
182
+ update.exit().remove()
183
+ }
184
+
185
+ function renderLabel ({ selection, labelData, fullParams, fullDataFormatter, fullChartParams, textReverseTransformWithRotate, textSizePx }: {
186
+ selection: d3.Selection<any, string, any, unknown>
187
+ labelData: LabelDatum[]
188
+ fullParams: GroupAuxParams
189
+ fullDataFormatter: DataFormatterGrid
190
+ fullChartParams: ChartParams
191
+ // gridAxesReverseTransformValue: string
192
+ textReverseTransformWithRotate: string
193
+ textSizePx: number
194
+ }) {
195
+ // const rectHeight = textSizePx + 6
196
+
197
+ const axisLabelSelection = selection
198
+ .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
199
+ .data(labelData)
200
+ .join(
201
+ enter => {
202
+ return enter
203
+ .append('g')
204
+ .classed(labelClassName, true)
205
+ .style('cursor', 'pointer')
206
+ .attr("transform", (d, i) => {
207
+ return `translate(${d.x}, ${d.y})`
208
+ })
209
+ },
210
+ update => {
211
+ const updateSelection = update
212
+ .transition()
213
+ .duration(50)
214
+ .attr("transform", (d, i) => {
215
+ return `translate(${d.x}, ${d.y})`
216
+ })
217
+ return updateSelection
218
+ },
219
+ exit => exit.remove()
220
+ )
221
+ .each((datum, i, n) => {
222
+ // const rectWidth = measureTextWidth(datum.text, textSizePx) + 12
223
+ const rectWidth = datum.textWidth + 12
224
+ const rectHeight = datum.textHeight + 6
225
+ // -- label偏移位置 --
226
+ let rectX = - rectWidth / 2
227
+ let rectY = -2
228
+ if (fullDataFormatter.grid.groupAxis.position === 'bottom') {
229
+ rectX = fullParams.labelRotate
230
+ ? - rectWidth + rectHeight // 有傾斜時以末端對齊(+height是為了修正移動太多)
231
+ : - rectWidth / 2
232
+ rectY = 2
233
+ } else if (fullDataFormatter.grid.groupAxis.position === 'left') {
234
+ rectX = - rectWidth + 2
235
+ rectY = - rectHeight / 2
236
+ } else if (fullDataFormatter.grid.groupAxis.position === 'right') {
237
+ rectX = - 2
238
+ rectY = - rectHeight / 2
239
+ } else if (fullDataFormatter.grid.groupAxis.position === 'top') {
240
+ rectX = fullParams.labelRotate
241
+ ? - rectWidth + rectHeight // 有傾斜時以末端對齊(+height是為了修正移動太多)
242
+ : - rectWidth / 2
243
+ rectY = - rectHeight + 2
244
+ }
245
+
246
+ // -- rect --
247
+ d3.select(n[i])
248
+ .selectAll<SVGRectElement, LabelDatum>('rect')
249
+ .data([datum])
250
+ .join(
251
+ enter => enter.append('rect')
252
+ .style('cursor', 'pointer')
253
+ .attr('rx', 5)
254
+ .attr('ry', 5),
255
+ update => update,
256
+ exit => exit.remove()
257
+ )
258
+ .attr('width', d => `${rectWidth}px`)
259
+ .attr('height', `${rectHeight}px`)
260
+ .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
261
+ .attr('x', rectX)
262
+ .attr('y', rectY - 3) // 奇怪的偏移修正
263
+ .style('transform', textReverseTransformWithRotate)
264
+
265
+ // const rectUpdate = d3.select(n[i])
266
+ // .selectAll<SVGRectElement, LabelDatum>('rect')
267
+ // .data([datum])
268
+ // const rectEnter = rectUpdate
269
+ // .enter()
270
+ // .append('rect')
271
+ // .attr('height', `${rectHeight}px`)
272
+ // .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
273
+ // .attr('x', rectX)
274
+ // .attr('y', rectY - 3) // 奇怪的偏移修正
275
+ // .attr('rx', 5)
276
+ // .attr('ry', 5)
277
+ // .style('cursor', 'pointer')
278
+ // // .style('pointer-events', 'none')
279
+ // const rect = rectUpdate.merge(rectEnter)
280
+ // .attr('width', d => `${rectWidth}px`)
281
+ // .style('transform', textReverseTransformWithRotate)
282
+ // rectUpdate.exit().remove()
283
+
284
+ // -- text --
285
+ d3.select(n[i])
286
+ .selectAll<SVGTextElement, LabelDatum>('text')
287
+ .data([datum])
288
+ .join(
289
+ enter => enter.append('text')
290
+ .style('dominant-baseline', 'hanging')
291
+ .style('cursor', 'pointer'),
292
+ update => update,
293
+ exit => exit.remove()
294
+ )
295
+ .style('transform', textReverseTransformWithRotate)
296
+ .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
297
+ .attr('font-size', fullChartParams.styles.textSize)
298
+ .attr('x', rectX + 6)
299
+ .attr('y', rectY)
300
+ .each((d, i, n) => {
301
+ renderTspansOnAxis(d3.select(n[i]), {
302
+ textArr: datum.textArr,
303
+ textSizePx,
304
+ groupAxisPosition: fullDataFormatter.grid.groupAxis.position
305
+ })
306
+ })
307
+
308
+ // const textUpdate = d3.select(n[i])
309
+ // .selectAll<SVGTextElement, LabelDatum>('text')
310
+ // .data([datum])
311
+ // const textEnter = textUpdate
312
+ // .enter()
313
+ // .append('text')
314
+ // .style('dominant-baseline', 'hanging')
315
+ // .style('cursor', 'pointer')
316
+ // // .style('pointer-events', 'none')
317
+ // const text = textUpdate.merge(textEnter)
318
+ // // .text(d => d.text)
319
+ // .style('transform', textReverseTransformWithRotate)
320
+ // .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
321
+ // .attr('font-size', fullChartParams.styles.textSize)
322
+ // .attr('x', rectX + 6)
323
+ // .attr('y', rectY)
324
+ // textUpdate.exit().remove()
325
+
326
+ // text.each((d, i, n) => {
327
+ // renderTspansOnAxis(d3.select(n[i]), {
328
+ // textArr: datum.textArr,
329
+ // textSizePx,
330
+ // groupAxisPosition: fullDataFormatter.grid.groupAxis.position
331
+ // })
332
+ // })
333
+ })
334
+
335
+ return axisLabelSelection
336
+ }
337
+
338
+ function removeLabel (selection: d3.Selection<any, string, any, unknown>) {
339
+ const gUpdate = selection
340
+ .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
341
+ .data([])
342
+
343
+ gUpdate.exit().remove()
344
+ }
345
+
346
+
347
+ export const GroupAux = defineGridPlugin(pluginConfig)(({ selection, rootSelection, name, subject, observer }) => {
348
+ const destroy$ = new Subject()
349
+
350
+ let isLabelMouseover = false
351
+
352
+ const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
353
+ .insert('rect', 'g')
354
+ .classed(getClassName(pluginName, 'rect'), true)
355
+ .attr('opacity', 0)
356
+
357
+ // const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
358
+ // .append('g')
359
+
360
+ const {
361
+ seriesSelection$,
362
+ axesSelection$,
363
+ defsSelection$,
364
+ graphicGSelection$
365
+ } = gridSelectionsObservable({
366
+ selection,
367
+ pluginName,
368
+ clipPathID: 'test',
369
+ seriesLabels$: observer.isSeriesSeprate$.pipe(
370
+ switchMap(isSeriesSeprate => {
371
+ return iif(
372
+ () => isSeriesSeprate,
373
+ observer.seriesLabels$,
374
+ // 如果沒分開的話只取一筆
375
+ observer.seriesLabels$.pipe(
376
+ map(d => [d[0]])
377
+ )
378
+ )
379
+ })
380
+ ),
381
+ gridContainerPosition$: observer.gridContainerPosition$,
382
+ gridAxesTransform$: observer.gridAxesTransform$,
383
+ gridGraphicTransform$: observer.gridGraphicTransform$
384
+ })
385
+
386
+ observer.layout$.pipe(
387
+ takeUntil(destroy$),
388
+ ).subscribe(d => {
389
+ rootRectSelection
390
+ .attr('width', d.rootWidth)
391
+ .attr('height', d.rootHeight)
392
+ })
393
+
394
+ // observer.gridAxesTransform$
395
+ // .pipe(
396
+ // takeUntil(destroy$),
397
+ // map(d => d.value),
398
+ // distinctUntilChanged()
399
+ // ).subscribe(d => {
400
+ // axisSelection
401
+ // .style('transform', d)
402
+ // })
403
+
404
+ // const visibleComputedData$ = observer.computedData$.pipe(
405
+ // takeUntil(destroy$),
406
+ // map(data => {
407
+ // const visibleComputedData = data
408
+ // .map(d => {
409
+ // return d.filter(_d => {
410
+ // return _d.visible == true
411
+ // })
412
+ // })
413
+ // .filter(d => d.length)
414
+ // // console.log('visibleComputedData', visibleComputedData)
415
+ // return visibleComputedData
416
+ // })
417
+ // )
418
+
419
+ // const SeriesDataMap$ = visibleComputedData$.pipe(
420
+ // map(d => makeGridSeriesDataMap(d))
421
+ // )
422
+
423
+ // const GroupDataMap$ = visibleComputedData$.pipe(
424
+ // map(d => makeGridGroupDataMap(d))
425
+ // )
426
+
427
+ // const contentTransform$: Observable<string> = new Observable(subscriber => {
428
+ // combineLatest({
429
+ // fullParams: observer.fullParams$,
430
+ // gridAxesTransform: observer.gridAxesTransform$
431
+ // }).pipe(
432
+ // takeUntil(destroy$),
433
+ // // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
434
+ // switchMap(async (d) => d),
435
+ // ).subscribe(data => {
436
+
437
+ // const transformData = Object.assign({}, data.gridAxesTransform)
438
+
439
+ // // const value = getAxesTransformValue({
440
+ // // translate: [0, 0],
441
+ // // scale: [transformData.scale[0] * -1, transformData.scale[1] * -1],
442
+ // // rotate: transformData.rotate * -1,
443
+ // // rotateX: transformData.rotateX * -1,
444
+ // // rotateY: transformData.rotateY * -1
445
+ // // })
446
+
447
+ // subscriber.next(transformData.value)
448
+ // })
449
+ // })
450
+ // const reverseTransform$: Observable<TransformData> = observer.gridAxesTransform$.pipe(
451
+ // takeUntil(destroy$),
452
+ // map(d => {
453
+ // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
454
+ // const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
455
+ // const rotate = d.rotate * -1
456
+ // const rotateX = d.rotateX * -1
457
+ // const rotateY = d.rotateY * -1
458
+ // return {
459
+ // translate,
460
+ // scale,
461
+ // rotate,
462
+ // rotateX,
463
+ // rotateY,
464
+ // value: ''
465
+ // }
466
+ // }),
467
+ // )
468
+ // const contentTransform$ = combineLatest({
469
+ // fullParams: observer.fullParams$,
470
+ // reverseTransform: reverseTransform$
471
+ // }).pipe(
472
+ // takeUntil(destroy$),
473
+ // switchMap(async data => {
474
+ // const translate = [0, 0]
475
+ // return `translate(${translate[0]}px, ${translate[1]}px) rotate(${data.reverseTransform.rotate}deg) rotateX(${data.reverseTransform.rotateX}deg) rotateY(${data.reverseTransform.rotateY}deg)`
476
+ // }),
477
+ // distinctUntilChanged()
478
+ // )
479
+
480
+ // const groupScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
481
+ // combineLatest({
482
+ // fullDataFormatter: observer.fullDataFormatter$,
483
+ // gridAxesSize: observer.gridAxesSize$,
484
+ // computedData: observer.computedData$
485
+ // }).pipe(
486
+ // takeUntil(destroy$),
487
+ // switchMap(async (d) => d),
488
+ // ).subscribe(data => {
489
+ // const groupMin = 0
490
+ // const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
491
+ // const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
492
+ // ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
493
+ // : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
494
+ // const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
495
+ // ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
496
+ // : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
497
+
498
+ // const groupingLength = data.computedData[0]
499
+ // ? data.computedData[0].length
500
+ // : 0
501
+
502
+ // let _labels = data.fullDataFormatter.grid.seriesDirection === 'row'
503
+ // // ? data.fullDataFormatter.grid.columnLabels
504
+ // // : data.fullDataFormatter.grid.rowLabels
505
+ // ? (data.computedData[0] ?? []).map(d => d.groupLabel)
506
+ // : data.computedData.map(d => d[0].groupLabel)
507
+
508
+ // const axisLabels = new Array(groupingLength).fill(0)
509
+ // .map((d, i) => {
510
+ // return _labels[i] != null
511
+ // ? _labels[i]
512
+ // : String(i) // 沒有label則用序列號填充
513
+ // })
514
+ // .filter((d, i) => {
515
+ // return i >= groupScaleDomainMin && i <= groupScaleDomainMax
516
+ // })
517
+
518
+
519
+ // const padding = data.fullDataFormatter.grid.groupAxis.scalePadding
520
+
521
+ // const groupScale = createLabelToAxisScale({
522
+ // axisLabels,
523
+ // axisWidth: data.gridAxesSize.width,
524
+ // padding
525
+ // })
526
+
527
+ // subscriber.next(groupScale)
528
+ // })
529
+ // })
530
+
531
+ // const groupScaleDomain$ = combineLatest({
532
+ // fullDataFormatter: observer.fullDataFormatter$,
533
+ // gridAxesSize: observer.gridAxesSize$,
534
+ // computedData: observer.computedData$
535
+ // }).pipe(
536
+ // takeUntil(destroy$),
537
+ // switchMap(async (d) => d),
538
+ // map(data => {
539
+ // const groupMin = 0
540
+ // const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
541
+ // // const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
542
+ // // ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
543
+ // // : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
544
+ // const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] - data.fullDataFormatter.grid.groupAxis.scalePadding
545
+ // const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'max'
546
+ // ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
547
+ // : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
548
+
549
+ // return [groupScaleDomainMin, groupScaleDomainMax]
550
+ // }),
551
+ // shareReplay(1)
552
+ // )
553
+
554
+ const groupScale$ = combineLatest({
555
+ groupScaleDomainValue: observer.groupScaleDomainValue$,
556
+ gridAxesSize: observer.gridAxesSize$
557
+ }).pipe(
558
+ takeUntil(destroy$),
559
+ switchMap(async (d) => d),
560
+ map(data => {
561
+ const groupScale: d3.ScaleLinear<number, number> = d3.scaleLinear()
562
+ .domain(data.groupScaleDomainValue)
563
+ .range([0, data.gridAxesSize.width])
564
+ return groupScale
565
+ })
566
+ )
567
+
568
+ // // 取得事件座標的group資料
569
+ // const gridGroupPositionFn$ = gridGroupPositionFnObservable({
570
+ // fullDataFormatter$: observer.fullDataFormatter$,
571
+ // gridAxesSize$: observer.gridAxesSize$,
572
+ // computedData$: observer.computedData$,
573
+ // fullChartParams$: observer.fullChartParams$,
574
+ // })
575
+
576
+ const highlightTarget$ = observer.fullChartParams$.pipe(
577
+ takeUntil(destroy$),
578
+ map(d => d.highlightTarget),
579
+ distinctUntilChanged()
580
+ )
581
+
582
+ // combineLatest({
583
+ // computedData: observer.computedData$,
584
+ // gridAxesSize: observer.gridAxesSize$,
585
+ // fullParams: observer.fullParams$,
586
+ // fullChartParams: observer.fullChartParams$,
587
+ // highlightTarget: highlightTarget$,
588
+ // SeriesDataMap: observer.SeriesDataMap$,
589
+ // GroupDataMap: observer.GroupDataMap$,
590
+ // gridGroupPositionFn: gridGroupPositionFn$,
591
+ // groupScale: groupScale$,
592
+ // }).pipe(
593
+ // takeUntil(destroy$),
594
+ // switchMap(async (d) => d),
595
+ // ).subscribe(data => {
596
+
597
+ // // store.selection
598
+ // rootSelection
599
+ // .on('mouseover', (event, datum) => {
600
+ // // event.stopPropagation()
601
+
602
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
603
+
604
+ // subject.event$.next({
605
+ // type: 'grid',
606
+ // pluginName: name,
607
+ // eventName: 'mouseover',
608
+ // highlightTarget: data.highlightTarget,
609
+ // datum: null,
610
+ // gridIndex: 0,
611
+ // series: [],
612
+ // seriesIndex: -1,
613
+ // seriesLabel: '',
614
+ // groups: data.GroupDataMap.get(groupLabel) ?? [],
615
+ // // groups: [],
616
+ // groupIndex,
617
+ // groupLabel,
618
+ // event,
619
+ // data: data.computedData
620
+ // })
621
+ // })
622
+ // .on('mousemove', (event, datum) => {
623
+ // // event.stopPropagation()
624
+
625
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
626
+
627
+ // subject.event$.next({
628
+ // type: 'grid',
629
+ // pluginName: name,
630
+ // eventName: 'mousemove',
631
+ // highlightTarget: data.highlightTarget,
632
+ // datum: null,
633
+ // gridIndex: 0,
634
+ // series: [],
635
+ // seriesIndex: -1,
636
+ // seriesLabel: '',
637
+ // groups: data.GroupDataMap.get(groupLabel) ?? [],
638
+ // // groups: [],
639
+ // groupIndex,
640
+ // groupLabel,
641
+ // event,
642
+ // data: data.computedData
643
+ // })
644
+ // })
645
+ // .on('mouseout', (event, datum) => {
646
+ // // event.stopPropagation()
647
+
648
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
649
+
650
+ // subject.event$.next({
651
+ // type: 'grid',
652
+ // pluginName: name,
653
+ // eventName: 'mouseout',
654
+ // highlightTarget: data.highlightTarget,
655
+ // datum: null,
656
+ // gridIndex: 0,
657
+ // series: [],
658
+ // seriesIndex: -1,
659
+ // seriesLabel: '',
660
+ // groups: data.GroupDataMap.get(groupLabel) ?? [],
661
+ // // groups: [],
662
+ // groupIndex,
663
+ // groupLabel,
664
+ // event,
665
+ // data: data.computedData
666
+ // })
667
+ // })
668
+ // .on('click', (event, datum) => {
669
+ // event.stopPropagation()
670
+
671
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
672
+
673
+ // subject.event$.next({
674
+ // type: 'grid',
675
+ // pluginName: name,
676
+ // eventName: 'click',
677
+ // highlightTarget: data.highlightTarget,
678
+ // datum: null,
679
+ // gridIndex: 0,
680
+ // series: [],
681
+ // seriesIndex: -1,
682
+ // seriesLabel: '',
683
+ // // groups: data.GroupDataMap.get(groupLabel) ?? [],
684
+ // groups: [],
685
+ // groupIndex,
686
+ // groupLabel,
687
+ // event,
688
+ // data: data.computedData
689
+ // })
690
+ // })
691
+
692
+ // // barSelection$.next(barSelection!)
693
+ // })
694
+
695
+ const rootMousemove$: Observable<any> = d3EventObservable(rootSelection, 'mousemove').pipe(
696
+ takeUntil(destroy$),
697
+ )
698
+
699
+ // const mousemoveGroupLabel$ = combineLatest({
700
+ // rootMousemove: rootMousemove$,
701
+ // gridGroupPositionFn: gridGroupPositionFn$,
702
+ // }).pipe(
703
+ // takeUntil(destroy$),
704
+ // switchMap(async d => d),
705
+ // map(data => {
706
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(data.rootMousemove)
707
+ // return { groupIndex, groupLabel }
708
+ // }),
709
+ // shareReplay(1)
710
+ // )
711
+
712
+
713
+ const textReverseTransform$ = combineLatest({
714
+ gridAxesReverseTransform: observer.gridAxesReverseTransform$,
715
+ gridContainerPosition: observer.gridContainerPosition$
716
+ }).pipe(
717
+ takeUntil(destroy$),
718
+ switchMap(async (d) => d),
719
+ map(data => {
720
+ // const axisReverseTranslateValue = `translate(${data.gridAxesReverseTransform.translate[0]}px, ${data.gridAxesReverseTransform.translate[1]}px)`
721
+ const axesRotateXYReverseValue = `rotateX(${data.gridAxesReverseTransform.rotateX}deg) rotateY(${data.gridAxesReverseTransform.rotateY}deg)`
722
+ const axesRotateReverseValue = `rotate(${data.gridAxesReverseTransform.rotate}deg)`
723
+ const containerScaleReverseValue = `scale(${1 / data.gridContainerPosition[0].scale[0]}, ${1 / data.gridContainerPosition[0].scale[1]})`
724
+ // 必須按照順序(先抵消外層rotate,再抵消最外層scale)
725
+ return `${axesRotateXYReverseValue} ${axesRotateReverseValue} ${containerScaleReverseValue}`
726
+ }),
727
+ distinctUntilChanged()
728
+ )
729
+
730
+ const textReverseTransformWithRotate$ = combineLatest({
731
+ textReverseTransform: textReverseTransform$,
732
+ fullParams: observer.fullParams$,
733
+ }).pipe(
734
+ takeUntil(destroy$),
735
+ switchMap(async (d) => d),
736
+ map(data => {
737
+ // 必須按照順序(先抵消外層rotate,再抵消最外層scale,最後再做本身的rotate)
738
+ return `${data.textReverseTransform} rotate(${data.fullParams.labelRotate}deg)`
739
+ })
740
+ )
741
+
742
+ const columnAmount$ = observer.gridContainerPosition$.pipe(
743
+ takeUntil(destroy$),
744
+ map(gridContainerPosition => {
745
+ const maxColumnIndex = gridContainerPosition.reduce((acc, current) => {
746
+ return current.columnIndex > acc ? current.columnIndex : acc
747
+ }, 0)
748
+ return maxColumnIndex + 1
749
+ }),
750
+ distinctUntilChanged()
751
+ )
752
+
753
+ const rowAmount$ = observer.gridContainerPosition$.pipe(
754
+ takeUntil(destroy$),
755
+ map(gridContainerPosition => {
756
+ const maxRowIndex = gridContainerPosition.reduce((acc, current) => {
757
+ return current.rowIndex > acc ? current.rowIndex : acc
758
+ }, 0)
759
+ return maxRowIndex + 1
760
+ }),
761
+ distinctUntilChanged()
762
+ )
763
+
764
+ const gridGroupPosition$ = gridGroupPositionObservable({
765
+ rootSelection,
766
+ fullDataFormatter$: observer.fullDataFormatter$,
767
+ gridAxesSize$: observer.gridAxesSize$,
768
+ computedData$: observer.computedData$,
769
+ fullChartParams$: observer.fullChartParams$,
770
+ gridContainerPosition$: observer.gridContainerPosition$,
771
+ layout$: observer.layout$
772
+ }).pipe(
773
+ takeUntil(destroy$)
774
+ )
775
+
776
+ combineLatest({
777
+ axesSelection: axesSelection$,
778
+ columnAmount: columnAmount$,
779
+ rowAmount: rowAmount$,
780
+ layout: observer.layout$,
781
+ rootMousemove: rootMousemove$,
782
+ // gridGroupPositionFn: gridGroupPositionFn$,
783
+ gridGroupPosition: gridGroupPosition$,
784
+ computedData: observer.computedData$,
785
+ groupScale: groupScale$,
786
+ gridAxesSize: observer.gridAxesSize$,
787
+ fullParams: observer.fullParams$,
788
+ fullDataFormatter: observer.fullDataFormatter$,
789
+ fullChartParams: observer.fullChartParams$,
790
+ highlightTarget: highlightTarget$,
791
+ // gridAxesReverseTransform: observer.gridAxesReverseTransform$,
792
+ textReverseTransformWithRotate: textReverseTransformWithRotate$,
793
+ GroupDataMap: observer.GroupDataMap$,
794
+ textSizePx: observer.textSizePx$
795
+ }).pipe(
796
+ takeUntil(destroy$),
797
+ switchMap(async d => d),
798
+ ).subscribe(data => {
799
+ // // 由於event座標是基於底層的,但是container會有多欄,所以要重新計算
800
+ // const eventData = {
801
+ // offsetX: data.rootMousemove.offsetX * data.columnAmount % data.layout.rootWidth,
802
+ // offsetY: data.rootMousemove.offsetY * data.rowAmount % data.layout.rootHeight
803
+ // }
804
+ // 依event的座標取得group資料
805
+ const { groupIndex, groupLabel } = data.gridGroupPosition
806
+ // console.log('gridGroupPosition', groupIndex, groupLabel)
807
+ const axisX = data.groupScale(groupIndex) ?? 0
808
+ // console.log('axisX', axisX)
809
+ const lineData = createLineData({
810
+ groupLabel: groupLabel,
811
+ axisX,
812
+ axisHeight: data.gridAxesSize.height,
813
+ fullParams: data.fullParams,
814
+ })
815
+ // console.log('lineData', lineData)
816
+ renderLine({
817
+ // selection: axisSelection,
818
+ selection: data.axesSelection,
819
+ pluginName: name,
820
+ lineData,
821
+ fullParams: data.fullParams,
822
+ fullChartParams: data.fullChartParams
823
+ })
824
+ const labelData = createLabelData({
825
+ groupLabel: groupLabel,
826
+ axisX,
827
+ fullParams: data.fullParams,
828
+ textSizePx: data.textSizePx,
829
+ rowAmount: data.rowAmount
830
+ })
831
+ const labelSelection = renderLabel({
832
+ // selection: axisSelection,
833
+ selection: data.axesSelection,
834
+ labelData,
835
+ fullParams: data.fullParams,
836
+ fullDataFormatter: data.fullDataFormatter,
837
+ fullChartParams: data.fullChartParams,
838
+ // gridAxesReverseTransformValue: data.gridAxesReverseTransform.value,
839
+ textReverseTransformWithRotate: data.textReverseTransformWithRotate,
840
+ textSizePx: data.textSizePx,
841
+ })
842
+
843
+ // label的事件
844
+ labelSelection
845
+ .on('mouseover', (event, datum) => {
846
+ event.stopPropagation()
847
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
848
+
849
+ isLabelMouseover = true
850
+
851
+ subject.event$.next({
852
+ type: 'grid',
853
+ pluginName: name,
854
+ eventName: 'mouseover',
855
+ highlightTarget: data.highlightTarget,
856
+ datum: null,
857
+ gridIndex: 0,
858
+ series: [],
859
+ seriesIndex: -1,
860
+ seriesLabel: '',
861
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
862
+ groupIndex,
863
+ groupLabel,
864
+ event,
865
+ data: data.computedData
866
+ })
867
+ })
868
+ .on('mousemove', (event, datum) => {
869
+ event.stopPropagation()
870
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
871
+
872
+ subject.event$.next({
873
+ type: 'grid',
874
+ pluginName: name,
875
+ eventName: 'mousemove',
876
+ highlightTarget: data.highlightTarget,
877
+ datum: null,
878
+ gridIndex: 0,
879
+ series: [],
880
+ seriesIndex: -1,
881
+ seriesLabel: '',
882
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
883
+ groupIndex,
884
+ groupLabel,
885
+ event,
886
+ data: data.computedData
887
+ })
888
+ })
889
+ .on('mouseout', (event, datum) => {
890
+ event.stopPropagation()
891
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
892
+
893
+ isLabelMouseover = false
894
+
895
+ subject.event$.next({
896
+ type: 'grid',
897
+ pluginName: name,
898
+ eventName: 'mouseout',
899
+ highlightTarget: data.highlightTarget,
900
+ datum: null,
901
+ gridIndex: 0,
902
+ series: [],
903
+ seriesIndex: -1,
904
+ seriesLabel: '',
905
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
906
+ groupIndex,
907
+ groupLabel,
908
+ event,
909
+ data: data.computedData
910
+ })
911
+ })
912
+ .on('click', (event, datum) => {
913
+ event.stopPropagation()
914
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
915
+
916
+ subject.event$.next({
917
+ type: 'grid',
918
+ pluginName: name,
919
+ eventName: 'click',
920
+ highlightTarget: data.highlightTarget,
921
+ datum: null,
922
+ gridIndex: 0,
923
+ series: [],
924
+ seriesIndex: -1,
925
+ seriesLabel: '',
926
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
927
+ groupIndex,
928
+ groupLabel,
929
+ event,
930
+ data: data.computedData
931
+ })
932
+ })
933
+
934
+ })
935
+
936
+ // // -- highlight(無論highlightTarget設定為何,一律依從groupLabel來顯示) --
937
+ // combineLatest({
938
+ // event: subject.event$.pipe(
939
+ // filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove')
940
+ // ),
941
+ // computedData: observer.computedData$,
942
+ // groupScale: groupScale$,
943
+ // gridAxesSize: observer.gridAxesSize$,
944
+ // fullParams: observer.fullParams$,
945
+ // fullChartParams: observer.fullChartParams$,
946
+ // highlightTarget: highlightTarget$,
947
+ // gridAxesReverseTransform: observer.gridAxesReverseTransform$,
948
+ // GroupDataMap: observer.GroupDataMap$,
949
+ // gridGroupPositionFn: gridGroupPositionFn$,
950
+ // textSizePx: observer.textSizePx$
951
+ // }).pipe(
952
+ // takeUntil(destroy$),
953
+ // switchMap(async d => d)
954
+ // ).subscribe(data => {
955
+ // // const groups = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
956
+ // // ? data.event.groups
957
+ // // : []
958
+
959
+ // // const groupLabel = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
960
+ // // ? data.event.groupLabel
961
+ // // : ''
962
+ // const axisX = data.groupScale(data.event.groupLabel) ?? 0
963
+
964
+ // const lineData = createLineData({
965
+ // groupLabel: data.event.groupLabel,
966
+ // axisX,
967
+ // axisHeight: data.gridAxesSize.height,
968
+ // fullParams: data.fullParams,
969
+ // })
970
+ // renderLine({
971
+ // selection: axisSelection,
972
+ // pluginName: name,
973
+ // lineData,
974
+ // fullParams: data.fullParams,
975
+ // fullChartParams: data.fullChartParams
976
+ // })
977
+ // const labelData = createLabelData({
978
+ // groupLabel: data.event.groupLabel,
979
+ // axisX,
980
+ // fullParams: data.fullParams
981
+ // })
982
+ // const labelSelection = renderLabel({
983
+ // selection: axisSelection,
984
+ // labelData,
985
+ // fullParams: data.fullParams,
986
+ // fullChartParams: data.fullChartParams,
987
+ // gridAxesReverseTransformValue: data.gridAxesReverseTransform.value,
988
+ // textSizePx: data.textSizePx
989
+ // })
990
+
991
+ // // label的事件
992
+ // labelSelection
993
+ // .on('mouseover', (event, datum) => {
994
+
995
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
996
+
997
+ // subject.event$.next({
998
+ // type: 'grid',
999
+ // pluginName: name,
1000
+ // eventName: 'mouseover',
1001
+ // highlightTarget: data.highlightTarget,
1002
+ // datum: null,
1003
+ // gridIndex: 0,
1004
+ // series: [],
1005
+ // seriesIndex: -1,
1006
+ // seriesLabel: '',
1007
+ // groups: data.event.groups,
1008
+ // groupIndex,
1009
+ // groupLabel,
1010
+ // event,
1011
+ // data: data.computedData
1012
+ // })
1013
+ // })
1014
+ // .on('mousemove', (event, datum) => {
1015
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
1016
+
1017
+ // subject.event$.next({
1018
+ // type: 'grid',
1019
+ // pluginName: name,
1020
+ // eventName: 'mousemove',
1021
+ // highlightTarget: data.highlightTarget,
1022
+ // datum: null,
1023
+ // gridIndex: 0,
1024
+ // series: [],
1025
+ // seriesIndex: -1,
1026
+ // seriesLabel: '',
1027
+ // groups: data.event.groups,
1028
+ // groupIndex,
1029
+ // groupLabel,
1030
+ // event,
1031
+ // data: data.computedData
1032
+ // })
1033
+ // })
1034
+ // .on('mouseout', (event, datum) => {
1035
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
1036
+
1037
+ // subject.event$.next({
1038
+ // type: 'grid',
1039
+ // pluginName: name,
1040
+ // eventName: 'mouseout',
1041
+ // highlightTarget: data.highlightTarget,
1042
+ // datum: null,
1043
+ // gridIndex: 0,
1044
+ // series: [],
1045
+ // seriesIndex: -1,
1046
+ // seriesLabel: '',
1047
+ // groups: data.event.groups,
1048
+ // groupIndex,
1049
+ // groupLabel,
1050
+ // event,
1051
+ // data: data.computedData
1052
+ // })
1053
+ // })
1054
+ // .on('click', (event, datum) => {
1055
+ // const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
1056
+
1057
+ // subject.event$.next({
1058
+ // type: 'grid',
1059
+ // pluginName: name,
1060
+ // eventName: 'click',
1061
+ // highlightTarget: data.highlightTarget,
1062
+ // datum: null,
1063
+ // gridIndex: 0,
1064
+ // series: [],
1065
+ // seriesIndex: -1,
1066
+ // seriesLabel: '',
1067
+ // groups: data.event.groups,
1068
+ // groupIndex,
1069
+ // groupLabel,
1070
+ // event,
1071
+ // data: data.computedData
1072
+ // })
1073
+ // })
1074
+ // })
1075
+
1076
+
1077
+
1078
+ const rootRectMouseout$ = d3EventObservable(rootRectSelection, 'mouseout').pipe(
1079
+ takeUntil(destroy$),
1080
+ )
1081
+
1082
+ combineLatest({
1083
+ rootRectMouseout: rootRectMouseout$,
1084
+ axesSelection: axesSelection$,
1085
+ }).pipe(
1086
+ takeUntil(destroy$),
1087
+ switchMap(async d => d)
1088
+ ).subscribe(data => {
1089
+ setTimeout(() => {
1090
+ // @Q@ workaround - 不知為何和 label 會有衝突,當滑鼠移動到 label 上時,會觸發 mouseout 事件
1091
+ if (isLabelMouseover == true) {
1092
+ return
1093
+ }
1094
+
1095
+ removeLine(data.axesSelection)
1096
+ removeLabel(data.axesSelection)
1097
+ })
1098
+ })
1099
+
1100
+ return () => {
1101
+ destroy$.next(undefined)
1102
+ rootRectSelection.remove()
1103
+ }
1099
1104
  })