@orbcharts/plugins-basic 3.0.0-alpha.44 → 3.0.0-alpha.45

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 (155) hide show
  1. package/LICENSE +200 -200
  2. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseBarStack.d.ts +6 -4
  3. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseBars.d.ts +6 -4
  4. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseBarsTriangle.d.ts +7 -4
  5. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseDots.d.ts +5 -3
  6. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseGroupAxis.d.ts +3 -3
  7. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseLineAreas.d.ts +6 -3
  8. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseLines.d.ts +6 -3
  9. package/dist/{src → orbcharts-plugins-basic/src}/base/BaseValueAxis.d.ts +3 -3
  10. package/dist/{src → orbcharts-plugins-basic/src}/grid/gridObservables.d.ts +4 -4
  11. package/dist/orbcharts-plugins-basic/src/index.d.ts +5 -0
  12. package/dist/orbcharts-plugins-basic/src/multiGrid/multiGridObservables.d.ts +8 -0
  13. package/dist/orbcharts-plugins-basic/src/series/plugins/PieEventTexts.d.ts +3 -0
  14. package/dist/orbcharts-plugins-basic/src/series/seriesObservables.d.ts +21 -0
  15. package/dist/{src → orbcharts-plugins-basic/src}/series/seriesUtils.d.ts +3 -3
  16. package/dist/orbcharts-plugins-basic.es.js +7696 -7529
  17. package/dist/orbcharts-plugins-basic.umd.js +8 -8
  18. package/dist/src/index.d.ts +1 -5
  19. package/package.json +42 -42
  20. package/src/base/BaseBarStack.ts +778 -881
  21. package/src/base/BaseBars.ts +764 -750
  22. package/src/base/BaseBarsTriangle.ts +672 -659
  23. package/src/base/BaseDots.ts +502 -639
  24. package/src/base/BaseGroupAxis.ts +496 -496
  25. package/src/base/BaseLegend.ts +641 -641
  26. package/src/base/BaseLineAreas.ts +625 -621
  27. package/src/base/BaseLines.ts +699 -692
  28. package/src/base/BaseValueAxis.ts +478 -479
  29. package/src/base/types.ts +2 -2
  30. package/src/grid/defaults.ts +121 -121
  31. package/src/grid/gridObservables.ts +247 -263
  32. package/src/grid/index.ts +15 -15
  33. package/src/grid/plugins/BarStack.ts +50 -37
  34. package/src/grid/plugins/Bars.ts +51 -37
  35. package/src/grid/plugins/BarsDiverging.ts +41 -39
  36. package/src/grid/plugins/BarsTriangle.ts +50 -34
  37. package/src/grid/plugins/Dots.ts +37 -35
  38. package/src/grid/plugins/GridLegend.ts +59 -59
  39. package/src/grid/plugins/GroupAux.ts +645 -646
  40. package/src/grid/plugins/GroupAxis.ts +42 -30
  41. package/src/grid/plugins/LineAreas.ts +39 -36
  42. package/src/grid/plugins/Lines.ts +38 -35
  43. package/src/grid/plugins/ScalingArea.ts +173 -174
  44. package/src/grid/plugins/ValueAxis.ts +43 -31
  45. package/src/grid/plugins/ValueStackAxis.ts +79 -70
  46. package/src/grid/types.ts +120 -120
  47. package/src/index.ts +9 -9
  48. package/src/multiGrid/defaults.ts +147 -147
  49. package/src/multiGrid/index.ts +11 -11
  50. package/src/multiGrid/multiGridObservables.ts +42 -289
  51. package/src/multiGrid/plugins/MultiBarStack.ts +74 -60
  52. package/src/multiGrid/plugins/MultiBars.ts +73 -59
  53. package/src/multiGrid/plugins/MultiBarsTriangle.ts +73 -58
  54. package/src/multiGrid/plugins/MultiDots.ts +60 -58
  55. package/src/multiGrid/plugins/MultiGridLegend.ts +89 -89
  56. package/src/multiGrid/plugins/MultiGroupAxis.ts +65 -53
  57. package/src/multiGrid/plugins/MultiLineAreas.ts +62 -59
  58. package/src/multiGrid/plugins/MultiLines.ts +61 -58
  59. package/src/multiGrid/plugins/MultiValueAxis.ts +65 -53
  60. package/src/multiGrid/plugins/OverlappingValueAxes.ts +169 -164
  61. package/src/multiGrid/types.ts +67 -67
  62. package/src/noneData/defaults.ts +64 -61
  63. package/src/noneData/index.ts +3 -3
  64. package/src/noneData/plugins/Container.ts +10 -10
  65. package/src/noneData/plugins/Tooltip.ts +310 -310
  66. package/src/noneData/types.ts +26 -26
  67. package/src/series/defaults.ts +109 -99
  68. package/src/series/index.ts +6 -6
  69. package/src/series/plugins/Bubbles.ts +571 -551
  70. package/src/series/plugins/Pie.ts +548 -600
  71. package/src/series/plugins/PieEventTexts.ts +258 -194
  72. package/src/series/plugins/PieLabels.ts +335 -288
  73. package/src/series/plugins/SeriesLegend.ts +59 -59
  74. package/src/series/seriesObservables.ts +145 -0
  75. package/src/series/seriesUtils.ts +50 -50
  76. package/src/series/types.ts +67 -67
  77. package/src/tree/defaults.ts +22 -22
  78. package/src/tree/index.ts +3 -3
  79. package/src/tree/plugins/TreeLegend.ts +59 -59
  80. package/src/tree/plugins/TreeMap.ts +305 -305
  81. package/src/tree/types.ts +23 -23
  82. package/src/utils/commonUtils.ts +21 -21
  83. package/src/utils/d3Graphics.ts +124 -124
  84. package/src/utils/d3Utils.ts +73 -73
  85. package/src/utils/observables.ts +14 -14
  86. package/src/utils/orbchartsUtils.ts +100 -100
  87. package/tsconfig.dev.json +16 -16
  88. package/tsconfig.json +16 -13
  89. package/tsconfig.prod.json +13 -13
  90. package/vite.config.js +49 -49
  91. package/dist/src/multiGrid/multiGridObservables.d.ts +0 -12
  92. package/dist/src/series/plugins/PieEventTexts.d.ts +0 -1
  93. /package/dist/{src → orbcharts-plugins-basic/src}/base/BaseGroupArea.d.ts +0 -0
  94. /package/dist/{src → orbcharts-plugins-basic/src}/base/BaseLegend.d.ts +0 -0
  95. /package/dist/{src → orbcharts-plugins-basic/src}/base/types.d.ts +0 -0
  96. /package/dist/{src → orbcharts-plugins-basic/src}/grid/defaults.d.ts +0 -0
  97. /package/dist/{src → orbcharts-plugins-basic/src}/grid/index.d.ts +0 -0
  98. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/BarStack.d.ts +0 -0
  99. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/Bars.d.ts +0 -0
  100. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/BarsDiverging.d.ts +0 -0
  101. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/BarsTriangle.d.ts +0 -0
  102. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/Dots.d.ts +0 -0
  103. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GridLegend.d.ts +0 -0
  104. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GroupAux.d.ts +0 -0
  105. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/GroupAxis.d.ts +0 -0
  106. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/LineAreas.d.ts +0 -0
  107. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/Lines.d.ts +0 -0
  108. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/Ranking.d.ts +0 -0
  109. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/RankingAxis.d.ts +0 -0
  110. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/ScalingArea.d.ts +0 -0
  111. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/ValueAxis.d.ts +0 -0
  112. /package/dist/{src → orbcharts-plugins-basic/src}/grid/plugins/ValueStackAxis.d.ts +0 -0
  113. /package/dist/{src → orbcharts-plugins-basic/src}/grid/types.d.ts +0 -0
  114. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/defaults.d.ts +0 -0
  115. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/index.d.ts +0 -0
  116. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiBarStack.d.ts +0 -0
  117. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiBars.d.ts +0 -0
  118. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiBarsTriangle.d.ts +0 -0
  119. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiDots.d.ts +0 -0
  120. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiGridLegend.d.ts +0 -0
  121. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiGroupAxis.d.ts +0 -0
  122. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiLineAreas.d.ts +0 -0
  123. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiLines.d.ts +0 -0
  124. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/MultiValueAxis.d.ts +0 -0
  125. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/plugins/OverlappingValueAxes.d.ts +0 -0
  126. /package/dist/{src → orbcharts-plugins-basic/src}/multiGrid/types.d.ts +0 -0
  127. /package/dist/{src → orbcharts-plugins-basic/src}/multiValue/index.d.ts +0 -0
  128. /package/dist/{src → orbcharts-plugins-basic/src}/multiValue/plugins/Scatter.d.ts +0 -0
  129. /package/dist/{src → orbcharts-plugins-basic/src}/multiValue/plugins/ScatterAxes.d.ts +0 -0
  130. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/defaults.d.ts +0 -0
  131. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/index.d.ts +0 -0
  132. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/plugins/Container.d.ts +0 -0
  133. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/plugins/Tooltip.d.ts +0 -0
  134. /package/dist/{src → orbcharts-plugins-basic/src}/noneData/types.d.ts +0 -0
  135. /package/dist/{src → orbcharts-plugins-basic/src}/relationship/index.d.ts +0 -0
  136. /package/dist/{src → orbcharts-plugins-basic/src}/relationship/plugins/Relationship.d.ts +0 -0
  137. /package/dist/{src → orbcharts-plugins-basic/src}/series/defaults.d.ts +0 -0
  138. /package/dist/{src → orbcharts-plugins-basic/src}/series/index.d.ts +0 -0
  139. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/Bubbles.d.ts +0 -0
  140. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/Pie.d.ts +0 -0
  141. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/PieLabels.d.ts +0 -0
  142. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/SeriesLegend.d.ts +0 -0
  143. /package/dist/{src → orbcharts-plugins-basic/src}/series/plugins/Waffle.d.ts +0 -0
  144. /package/dist/{src → orbcharts-plugins-basic/src}/series/types.d.ts +0 -0
  145. /package/dist/{src → orbcharts-plugins-basic/src}/tree/defaults.d.ts +0 -0
  146. /package/dist/{src → orbcharts-plugins-basic/src}/tree/index.d.ts +0 -0
  147. /package/dist/{src → orbcharts-plugins-basic/src}/tree/plugins/TreeLegend.d.ts +0 -0
  148. /package/dist/{src → orbcharts-plugins-basic/src}/tree/plugins/TreeMap.d.ts +0 -0
  149. /package/dist/{src → orbcharts-plugins-basic/src}/tree/types.d.ts +0 -0
  150. /package/dist/{src → orbcharts-plugins-basic/src}/utils/commonUtils.d.ts +0 -0
  151. /package/dist/{src → orbcharts-plugins-basic/src}/utils/d3Graphics.d.ts +0 -0
  152. /package/dist/{src → orbcharts-plugins-basic/src}/utils/d3Utils.d.ts +0 -0
  153. /package/dist/{src → orbcharts-plugins-basic/src}/utils/observables.d.ts +0 -0
  154. /package/dist/{src → orbcharts-plugins-basic/src}/utils/orbchartsUtils.d.ts +0 -0
  155. /package/dist/{vite.config.d.ts → orbcharts-plugins-basic/vite.config.d.ts} +0 -0
@@ -1,647 +1,646 @@
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
- Subject,
14
- Observable } from 'rxjs'
15
- import {
16
- defineGridPlugin } from '@orbcharts/core'
17
- import type {
18
- TransformData,
19
- ChartParams } from '@orbcharts/core'
20
- import { DEFAULT_GROUP_AREA_PARAMS } from '../defaults'
21
- import { parseTickFormatValue } from '../../utils/d3Utils'
22
- import { measureTextWidth } from '../../utils/commonUtils'
23
- import { getColor, getClassName, getUniID } from '../../utils/orbchartsUtils'
24
- import { d3EventObservable } from '../../utils/observables'
25
- import { gridGroupPositionFnObservable } from '../gridObservables'
26
- import { createAxisPointScale } from '@orbcharts/core'
27
- import type { GroupAuxParams } from '../types'
28
-
29
- interface LineDatum {
30
- id: string
31
- x1: number
32
- x2: number
33
- y1: number
34
- y2: number
35
- }
36
-
37
- interface LabelDatum {
38
- id: string
39
- text: string
40
- x: number
41
- y: number
42
- }
43
-
44
- const pluginName = 'GroupAux'
45
- const labelClassName = getClassName(pluginName, 'label-box')
46
-
47
- function createLineData ({ groupLabel, axisX, axisHeight, fullParams }: {
48
- groupLabel: string
49
- axisX: number
50
- axisHeight: number
51
- fullParams: GroupAuxParams
52
- }): LineDatum[] {
53
- return fullParams.showLine && groupLabel
54
- ? [{
55
- id: groupLabel,
56
- x1: axisX,
57
- x2: axisX,
58
- y1: 0,
59
- y2: axisHeight
60
- }]
61
- : []
62
- }
63
-
64
- function renderLine ({ selection, pluginName, lineData, fullParams, fullChartParams }: {
65
- selection: d3.Selection<any, unknown, any, unknown>
66
- pluginName: string
67
- lineData: LineDatum[]
68
- fullParams: GroupAuxParams
69
- fullChartParams: ChartParams
70
- }) {
71
- const gClassName = getClassName(pluginName, 'auxline')
72
- const update = selection
73
- .selectAll<SVGLineElement, LineDatum>(`line.${gClassName}`)
74
- .data(lineData)
75
- const enter = update
76
- .enter()
77
- .append('line')
78
- .classed(gClassName, true)
79
- // .style('stroke', '#E4E7ED')
80
- .style('stroke', d => getColor(fullParams.lineColorType, fullChartParams))
81
- .style('stroke-width', 1)
82
- .style('stroke-dasharray', fullParams.lineDashArray ?? 'none')
83
- .style('pointer-events', 'none')
84
- // .attr('opacity', 0)
85
- const auxLineSelection = update.merge(enter)
86
- // .attr('opacity', (d) => {
87
- // return d.active == true ? 1 : 0
88
- // })
89
- update.exit().remove()
90
- enter
91
- .attr('x1', d => d.x1)
92
- .attr('y1', d => d.y1)
93
- .attr('x2', d => d.x2)
94
- .attr('y2', d => d.y2)
95
- update
96
- .transition()
97
- .duration(50)
98
- .attr('x1', d => d.x1)
99
- .attr('y1', d => d.y1)
100
- .attr('x2', d => d.x2)
101
- .attr('y2', d => d.y2)
102
-
103
- return auxLineSelection
104
- }
105
-
106
- function removeLine (selection: d3.Selection<any, unknown, any, unknown>) {
107
- const update = selection
108
- .selectAll<SVGLineElement, LineDatum>('line')
109
- .data([])
110
-
111
- update.exit().remove()
112
- }
113
-
114
- function createLabelData ({ groupLabel, axisX, fullParams }: {
115
- groupLabel: string
116
- axisX: number
117
- fullParams: GroupAuxParams
118
- }) {
119
- return fullParams.showLabel && groupLabel
120
- ? [{
121
- id: groupLabel,
122
- x: axisX,
123
- y: - fullParams.labelPadding,
124
- text: parseTickFormatValue(groupLabel, fullParams.labelTextFormat)
125
- }]
126
- : []
127
- }
128
-
129
- function renderLabel ({ selection, labelData, fullParams, fullChartParams, gridAxesReverseTransformValue, textSizePx }: {
130
- selection: d3.Selection<any, unknown, any, unknown>
131
- labelData: LabelDatum[]
132
- fullParams: GroupAuxParams
133
- fullChartParams: ChartParams
134
- gridAxesReverseTransformValue: string
135
- textSizePx: number
136
- }) {
137
- const rectHeight = textSizePx + 4
138
-
139
- const gUpdate = selection
140
- .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
141
- .data(labelData)
142
- const gEnter = gUpdate
143
- .enter()
144
- .append('g')
145
- .classed(labelClassName, true)
146
- .style('cursor', 'pointer')
147
- const axisLabelSelection = gEnter.merge(gUpdate)
148
- gEnter
149
- .attr("transform", (d, i) => {
150
- return `translate(${d.x}, ${d.y})`
151
- })
152
- gUpdate
153
- .transition()
154
- .duration(50)
155
- .attr("transform", (d, i) => {
156
- return `translate(${d.x}, ${d.y})`
157
- })
158
- gUpdate.exit().remove()
159
-
160
- axisLabelSelection.each((datum, i, n) => {
161
- const rectWidth = measureTextWidth(datum.text, textSizePx) + 12
162
- const rectX = - rectWidth / 2
163
-
164
- const rectUpdate = d3.select(n[i])
165
- .selectAll<SVGRectElement, LabelDatum>('rect')
166
- .data([datum])
167
- const rectEnter = rectUpdate
168
- .enter()
169
- .append('rect')
170
- .attr('height', `${rectHeight}px`)
171
- .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
172
- .attr('x', rectX)
173
- .attr('y', -2)
174
- .attr('rx', 5)
175
- .attr('ry', 5)
176
- .style('cursor', 'pointer')
177
- // .style('pointer-events', 'none')
178
- const rect = rectUpdate.merge(rectEnter)
179
- .attr('width', d => `${rectWidth}px`)
180
- .style('transform', gridAxesReverseTransformValue)
181
- rectUpdate.exit().remove()
182
-
183
- const textUpdate = d3.select(n[i])
184
- .selectAll<SVGTextElement, LabelDatum>('text')
185
- .data([datum])
186
- const textEnter = textUpdate
187
- .enter()
188
- .append('text')
189
- .style('dominant-baseline', 'hanging')
190
- .style('cursor', 'pointer')
191
- // .style('pointer-events', 'none')
192
- const text = textUpdate.merge(textEnter)
193
- .text(d => d.text)
194
- .style('transform', gridAxesReverseTransformValue)
195
- .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
196
- .attr('font-size', fullChartParams.styles.textSize)
197
- .attr('x', rectX + 6)
198
- textUpdate.exit().remove()
199
- })
200
-
201
- return axisLabelSelection
202
- }
203
-
204
- function removeLabel (selection: d3.Selection<any, unknown, any, unknown>) {
205
- const gUpdate = selection
206
- .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
207
- .data([])
208
-
209
- gUpdate.exit().remove()
210
- }
211
-
212
- export const GroupAux = defineGridPlugin(pluginName, DEFAULT_GROUP_AREA_PARAMS)(({ selection, rootSelection, name, subject, observer }) => {
213
- const destroy$ = new Subject()
214
-
215
- const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
216
- .insert('rect', 'g')
217
- .classed(getClassName(pluginName, 'rect'), true)
218
- .attr('opacity', 0)
219
-
220
- const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
221
- .append('g')
222
-
223
- observer.layout$.pipe(
224
- takeUntil(destroy$),
225
- ).subscribe(d => {
226
- rootRectSelection
227
- .attr('width', d.rootWidth)
228
- .attr('height', d.rootHeight)
229
- })
230
-
231
- observer.gridAxesTransform$
232
- .pipe(
233
- takeUntil(destroy$),
234
- map(d => d.value),
235
- distinctUntilChanged()
236
- ).subscribe(d => {
237
- axisSelection
238
- .style('transform', d)
239
- })
240
-
241
- // const visibleComputedData$ = observer.computedData$.pipe(
242
- // takeUntil(destroy$),
243
- // map(data => {
244
- // const visibleComputedData = data
245
- // .map(d => {
246
- // return d.filter(_d => {
247
- // return _d.visible == true
248
- // })
249
- // })
250
- // .filter(d => d.length)
251
- // // console.log('visibleComputedData', visibleComputedData)
252
- // return visibleComputedData
253
- // })
254
- // )
255
-
256
- // const SeriesDataMap$ = visibleComputedData$.pipe(
257
- // map(d => makeGridSeriesDataMap(d))
258
- // )
259
-
260
- // const GroupDataMap$ = visibleComputedData$.pipe(
261
- // map(d => makeGridGroupDataMap(d))
262
- // )
263
-
264
- // const contentTransform$: Observable<string> = new Observable(subscriber => {
265
- // combineLatest({
266
- // fullParams: observer.fullParams$,
267
- // gridAxesTransform: observer.gridAxesTransform$
268
- // }).pipe(
269
- // takeUntil(destroy$),
270
- // // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
271
- // switchMap(async (d) => d),
272
- // ).subscribe(data => {
273
-
274
- // const transformData = Object.assign({}, data.gridAxesTransform)
275
-
276
- // // const value = getAxesTransformValue({
277
- // // translate: [0, 0],
278
- // // scale: [transformData.scale[0] * -1, transformData.scale[1] * -1],
279
- // // rotate: transformData.rotate * -1,
280
- // // rotateX: transformData.rotateX * -1,
281
- // // rotateY: transformData.rotateY * -1
282
- // // })
283
-
284
- // subscriber.next(transformData.value)
285
- // })
286
- // })
287
- // const reverseTransform$: Observable<TransformData> = observer.gridAxesTransform$.pipe(
288
- // takeUntil(destroy$),
289
- // map(d => {
290
- // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
291
- // const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
292
- // const rotate = d.rotate * -1
293
- // const rotateX = d.rotateX * -1
294
- // const rotateY = d.rotateY * -1
295
- // return {
296
- // translate,
297
- // scale,
298
- // rotate,
299
- // rotateX,
300
- // rotateY,
301
- // value: ''
302
- // }
303
- // }),
304
- // )
305
- // const contentTransform$ = combineLatest({
306
- // fullParams: observer.fullParams$,
307
- // reverseTransform: reverseTransform$
308
- // }).pipe(
309
- // takeUntil(destroy$),
310
- // switchMap(async data => {
311
- // const translate = [0, 0]
312
- // return `translate(${translate[0]}px, ${translate[1]}px) rotate(${data.reverseTransform.rotate}deg) rotateX(${data.reverseTransform.rotateX}deg) rotateY(${data.reverseTransform.rotateY}deg)`
313
- // }),
314
- // distinctUntilChanged()
315
- // )
316
-
317
- const groupScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
318
- combineLatest({
319
- fullDataFormatter: observer.fullDataFormatter$,
320
- gridAxesSize: observer.gridAxesSize$,
321
- computedData: observer.computedData$
322
- }).pipe(
323
- takeUntil(destroy$),
324
- switchMap(async (d) => d),
325
- ).subscribe(data => {
326
- const groupMin = 0
327
- const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
328
- const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
329
- ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
330
- : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
331
- const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
332
- ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
333
- : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
334
-
335
- const groupingLength = data.computedData[0]
336
- ? data.computedData[0].length
337
- : 0
338
-
339
- let _labels = data.fullDataFormatter.grid.gridData.seriesDirection === 'row'
340
- // ? data.fullDataFormatter.grid.columnLabels
341
- // : data.fullDataFormatter.grid.rowLabels
342
- ? (data.computedData[0] ?? []).map(d => d.groupLabel)
343
- : data.computedData.map(d => d[0].groupLabel)
344
-
345
- const axisLabels = new Array(groupingLength).fill(0)
346
- .map((d, i) => {
347
- return _labels[i] != null
348
- ? _labels[i]
349
- : String(i) // 沒有label則用序列號填充
350
- })
351
- .filter((d, i) => {
352
- return i >= groupScaleDomainMin && i <= groupScaleDomainMax
353
- })
354
-
355
-
356
- const padding = data.fullDataFormatter.grid.groupAxis.scalePadding
357
-
358
- const groupScale = createAxisPointScale({
359
- axisLabels,
360
- axisWidth: data.gridAxesSize.width,
361
- padding
362
- })
363
-
364
- subscriber.next(groupScale)
365
- })
366
- })
367
-
368
- // 取得事件座標的group資料
369
- const gridGroupPositionFn$ = gridGroupPositionFnObservable({
370
- fullDataFormatter$: observer.fullDataFormatter$,
371
- gridAxesSize$: observer.gridAxesSize$,
372
- computedData$: observer.computedData$,
373
- fullChartParams$: observer.fullChartParams$,
374
- })
375
-
376
- const highlightTarget$ = observer.fullChartParams$.pipe(
377
- takeUntil(destroy$),
378
- map(d => d.highlightTarget),
379
- distinctUntilChanged()
380
- )
381
-
382
- combineLatest({
383
- computedData: observer.computedData$,
384
- gridAxesSize: observer.gridAxesSize$,
385
- fullParams: observer.fullParams$,
386
- fullChartParams: observer.fullChartParams$,
387
- highlightTarget: highlightTarget$,
388
- SeriesDataMap: observer.SeriesDataMap$,
389
- GroupDataMap: observer.GroupDataMap$,
390
- gridGroupPositionFn: gridGroupPositionFn$,
391
- groupScale: groupScale$,
392
- }).pipe(
393
- takeUntil(destroy$),
394
- // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
395
- switchMap(async (d) => d),
396
- ).subscribe(data => {
397
-
398
- // store.selection
399
- rootSelection
400
- .on('mouseover', (event, datum) => {
401
- // event.stopPropagation()
402
-
403
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
404
-
405
- subject.event$.next({
406
- type: 'grid',
407
- pluginName: name,
408
- eventName: 'mouseover',
409
- highlightTarget: data.highlightTarget,
410
- datum: null,
411
- gridIndex: 0, // @Q@ 暫不處理
412
- series: [],
413
- seriesIndex: -1,
414
- seriesLabel: '',
415
- groups: data.GroupDataMap.get(groupLabel) ?? [],
416
- groupIndex,
417
- groupLabel,
418
- event,
419
- data: data.computedData
420
- })
421
- })
422
- .on('mousemove', (event, datum) => {
423
- // event.stopPropagation()
424
-
425
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
426
-
427
- subject.event$.next({
428
- type: 'grid',
429
- pluginName: name,
430
- eventName: 'mousemove',
431
- highlightTarget: data.highlightTarget,
432
- datum: null,
433
- gridIndex: 0, // @Q@ 暫不處理
434
- series: [],
435
- seriesIndex: -1,
436
- seriesLabel: '',
437
- groups: data.GroupDataMap.get(groupLabel) ?? [],
438
- groupIndex,
439
- groupLabel,
440
- event,
441
- data: data.computedData
442
- })
443
- })
444
- .on('mouseout', (event, datum) => {
445
- // event.stopPropagation()
446
-
447
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
448
-
449
- subject.event$.next({
450
- type: 'grid',
451
- pluginName: name,
452
- eventName: 'mouseout',
453
- highlightTarget: data.highlightTarget,
454
- datum: null,
455
- gridIndex: 0, // @Q@ 暫不處理
456
- series: [],
457
- seriesIndex: -1,
458
- seriesLabel: '',
459
- groups: data.GroupDataMap.get(groupLabel) ?? [],
460
- groupIndex,
461
- groupLabel,
462
- event,
463
- data: data.computedData
464
- })
465
- })
466
- .on('click', (event, datum) => {
467
- event.stopPropagation()
468
-
469
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
470
-
471
- subject.event$.next({
472
- type: 'grid',
473
- pluginName: name,
474
- eventName: 'click',
475
- highlightTarget: data.highlightTarget,
476
- datum: null,
477
- gridIndex: 0, // @Q@ 暫不處理
478
- series: [],
479
- seriesIndex: -1,
480
- seriesLabel: '',
481
- groups: data.GroupDataMap.get(groupLabel) ?? [],
482
- groupIndex,
483
- groupLabel,
484
- event,
485
- data: data.computedData
486
- })
487
- })
488
-
489
- // barSelection$.next(barSelection!)
490
- })
491
-
492
- // -- highlight(無論highlightTarget設定為何,一律依從groupLabel來顯示) --
493
- combineLatest({
494
- // highlight: highlight$,
495
- event: subject.event$.pipe(
496
- filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove')
497
- ),
498
- computedData: observer.computedData$,
499
- groupScale: groupScale$,
500
- gridAxesSize: observer.gridAxesSize$,
501
- fullParams: observer.fullParams$,
502
- fullChartParams: observer.fullChartParams$,
503
- highlightTarget: highlightTarget$,
504
- gridAxesReverseTransform: observer.gridAxesReverseTransform$,
505
- GroupDataMap: observer.GroupDataMap$,
506
- gridGroupPositionFn: gridGroupPositionFn$,
507
- textSizePx: observer.textSizePx$
508
- }).pipe(
509
- takeUntil(destroy$),
510
- switchMap(async d => d)
511
- ).subscribe(data => {
512
- // const groups = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
513
- // ? data.event.groups
514
- // : []
515
-
516
- // const groupLabel = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
517
- // ? data.event.groupLabel
518
- // : ''
519
- const axisX = data.groupScale(data.event.groupLabel) ?? 0
520
-
521
- const lineData = createLineData({
522
- groupLabel: data.event.groupLabel,
523
- axisX,
524
- axisHeight: data.gridAxesSize.height,
525
- fullParams: data.fullParams,
526
- })
527
- renderLine({
528
- selection: axisSelection,
529
- pluginName: name,
530
- lineData,
531
- fullParams: data.fullParams,
532
- fullChartParams: data.fullChartParams
533
- })
534
- const labelData = createLabelData({
535
- groupLabel: data.event.groupLabel,
536
- axisX,
537
- fullParams: data.fullParams
538
- })
539
- const labelSelection = renderLabel({
540
- selection: axisSelection,
541
- labelData,
542
- fullParams: data.fullParams,
543
- fullChartParams: data.fullChartParams,
544
- gridAxesReverseTransformValue: data.gridAxesReverseTransform.value,
545
- textSizePx: data.textSizePx
546
- })
547
-
548
- // label的事件
549
- labelSelection
550
- .on('mouseover', (event, datum) => {
551
-
552
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
553
-
554
- subject.event$.next({
555
- type: 'grid',
556
- pluginName: name,
557
- eventName: 'mouseover',
558
- highlightTarget: data.highlightTarget,
559
- datum: null,
560
- gridIndex: 0, // @Q@ 暫不處理
561
- series: [],
562
- seriesIndex: -1,
563
- seriesLabel: '',
564
- groups: data.event.groups,
565
- groupIndex,
566
- groupLabel,
567
- event,
568
- data: data.computedData
569
- })
570
- })
571
- .on('mousemove', (event, datum) => {
572
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
573
-
574
- subject.event$.next({
575
- type: 'grid',
576
- pluginName: name,
577
- eventName: 'mousemove',
578
- highlightTarget: data.highlightTarget,
579
- datum: null,
580
- gridIndex: 0, // @Q@ 暫不處理
581
- series: [],
582
- seriesIndex: -1,
583
- seriesLabel: '',
584
- groups: data.event.groups,
585
- groupIndex,
586
- groupLabel,
587
- event,
588
- data: data.computedData
589
- })
590
- })
591
- .on('mouseout', (event, datum) => {
592
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
593
-
594
- subject.event$.next({
595
- type: 'grid',
596
- pluginName: name,
597
- eventName: 'mouseout',
598
- highlightTarget: data.highlightTarget,
599
- datum: null,
600
- gridIndex: 0, // @Q@ 暫不處理
601
- series: [],
602
- seriesIndex: -1,
603
- seriesLabel: '',
604
- groups: data.event.groups,
605
- groupIndex,
606
- groupLabel,
607
- event,
608
- data: data.computedData
609
- })
610
- })
611
- .on('click', (event, datum) => {
612
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
613
-
614
- subject.event$.next({
615
- type: 'grid',
616
- pluginName: name,
617
- eventName: 'click',
618
- highlightTarget: data.highlightTarget,
619
- datum: null,
620
- gridIndex: 0, // @Q@ 暫不處理
621
- series: [],
622
- seriesIndex: -1,
623
- seriesLabel: '',
624
- groups: data.event.groups,
625
- groupIndex,
626
- groupLabel,
627
- event,
628
- data: data.computedData
629
- })
630
- })
631
- })
632
-
633
- const rootMouseout$ = d3EventObservable(rootRectSelection, 'mouseout').pipe(
634
- takeUntil(destroy$),
635
- )
636
-
637
- rootMouseout$.subscribe(event => {
638
- console.log('rootMouseout')
639
- removeLine(axisSelection)
640
- removeLabel(axisSelection)
641
- })
642
-
643
- return () => {
644
- destroy$.next(undefined)
645
- rootRectSelection.remove()
646
- }
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
+ Subject,
14
+ Observable } from 'rxjs'
15
+ import {
16
+ defineGridPlugin } from '@orbcharts/core'
17
+ import type {
18
+ TransformData,
19
+ ChartParams } from '@orbcharts/core'
20
+ import { DEFAULT_GROUP_AREA_PARAMS } from '../defaults'
21
+ import { parseTickFormatValue } from '../../utils/d3Utils'
22
+ import { measureTextWidth } from '../../utils/commonUtils'
23
+ import { getColor, getClassName, getUniID } from '../../utils/orbchartsUtils'
24
+ import { d3EventObservable } from '../../utils/observables'
25
+ import { gridGroupPositionFnObservable } from '../gridObservables'
26
+ import { createAxisPointScale } from '@orbcharts/core'
27
+ import type { GroupAuxParams } from '../types'
28
+
29
+ interface LineDatum {
30
+ id: string
31
+ x1: number
32
+ x2: number
33
+ y1: number
34
+ y2: number
35
+ }
36
+
37
+ interface LabelDatum {
38
+ id: string
39
+ text: string
40
+ x: number
41
+ y: number
42
+ }
43
+
44
+ const pluginName = 'GroupAux'
45
+ const labelClassName = getClassName(pluginName, 'label-box')
46
+
47
+ function createLineData ({ groupLabel, axisX, axisHeight, fullParams }: {
48
+ groupLabel: string
49
+ axisX: number
50
+ axisHeight: number
51
+ fullParams: GroupAuxParams
52
+ }): LineDatum[] {
53
+ return fullParams.showLine && groupLabel
54
+ ? [{
55
+ id: groupLabel,
56
+ x1: axisX,
57
+ x2: axisX,
58
+ y1: 0,
59
+ y2: axisHeight
60
+ }]
61
+ : []
62
+ }
63
+
64
+ function renderLine ({ selection, pluginName, lineData, fullParams, fullChartParams }: {
65
+ selection: d3.Selection<any, unknown, any, unknown>
66
+ pluginName: string
67
+ lineData: LineDatum[]
68
+ fullParams: GroupAuxParams
69
+ fullChartParams: ChartParams
70
+ }) {
71
+ const gClassName = getClassName(pluginName, 'auxline')
72
+ const update = selection
73
+ .selectAll<SVGLineElement, LineDatum>(`line.${gClassName}`)
74
+ .data(lineData)
75
+ const enter = update
76
+ .enter()
77
+ .append('line')
78
+ .classed(gClassName, true)
79
+ // .style('stroke', '#E4E7ED')
80
+ .style('stroke', d => getColor(fullParams.lineColorType, fullChartParams))
81
+ .style('stroke-width', 1)
82
+ .style('stroke-dasharray', fullParams.lineDashArray ?? 'none')
83
+ .style('pointer-events', 'none')
84
+ // .attr('opacity', 0)
85
+ const auxLineSelection = update.merge(enter)
86
+ // .attr('opacity', (d) => {
87
+ // return d.active == true ? 1 : 0
88
+ // })
89
+ update.exit().remove()
90
+ enter
91
+ .attr('x1', d => d.x1)
92
+ .attr('y1', d => d.y1)
93
+ .attr('x2', d => d.x2)
94
+ .attr('y2', d => d.y2)
95
+ update
96
+ .transition()
97
+ .duration(50)
98
+ .attr('x1', d => d.x1)
99
+ .attr('y1', d => d.y1)
100
+ .attr('x2', d => d.x2)
101
+ .attr('y2', d => d.y2)
102
+
103
+ return auxLineSelection
104
+ }
105
+
106
+ function removeLine (selection: d3.Selection<any, unknown, any, unknown>) {
107
+ const update = selection
108
+ .selectAll<SVGLineElement, LineDatum>('line')
109
+ .data([])
110
+
111
+ update.exit().remove()
112
+ }
113
+
114
+ function createLabelData ({ groupLabel, axisX, fullParams }: {
115
+ groupLabel: string
116
+ axisX: number
117
+ fullParams: GroupAuxParams
118
+ }) {
119
+ return fullParams.showLabel && groupLabel
120
+ ? [{
121
+ id: groupLabel,
122
+ x: axisX,
123
+ y: - fullParams.labelPadding,
124
+ text: parseTickFormatValue(groupLabel, fullParams.labelTextFormat)
125
+ }]
126
+ : []
127
+ }
128
+
129
+ function renderLabel ({ selection, labelData, fullParams, fullChartParams, gridAxesReverseTransformValue, textSizePx }: {
130
+ selection: d3.Selection<any, unknown, any, unknown>
131
+ labelData: LabelDatum[]
132
+ fullParams: GroupAuxParams
133
+ fullChartParams: ChartParams
134
+ gridAxesReverseTransformValue: string
135
+ textSizePx: number
136
+ }) {
137
+ const rectHeight = textSizePx + 4
138
+
139
+ const gUpdate = selection
140
+ .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
141
+ .data(labelData)
142
+ const gEnter = gUpdate
143
+ .enter()
144
+ .append('g')
145
+ .classed(labelClassName, true)
146
+ .style('cursor', 'pointer')
147
+ const axisLabelSelection = gEnter.merge(gUpdate)
148
+ gEnter
149
+ .attr("transform", (d, i) => {
150
+ return `translate(${d.x}, ${d.y})`
151
+ })
152
+ gUpdate
153
+ .transition()
154
+ .duration(50)
155
+ .attr("transform", (d, i) => {
156
+ return `translate(${d.x}, ${d.y})`
157
+ })
158
+ gUpdate.exit().remove()
159
+
160
+ axisLabelSelection.each((datum, i, n) => {
161
+ const rectWidth = measureTextWidth(datum.text, textSizePx) + 12
162
+ const rectX = - rectWidth / 2
163
+
164
+ const rectUpdate = d3.select(n[i])
165
+ .selectAll<SVGRectElement, LabelDatum>('rect')
166
+ .data([datum])
167
+ const rectEnter = rectUpdate
168
+ .enter()
169
+ .append('rect')
170
+ .attr('height', `${rectHeight}px`)
171
+ .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
172
+ .attr('x', rectX)
173
+ .attr('y', -2)
174
+ .attr('rx', 5)
175
+ .attr('ry', 5)
176
+ .style('cursor', 'pointer')
177
+ // .style('pointer-events', 'none')
178
+ const rect = rectUpdate.merge(rectEnter)
179
+ .attr('width', d => `${rectWidth}px`)
180
+ .style('transform', gridAxesReverseTransformValue)
181
+ rectUpdate.exit().remove()
182
+
183
+ const textUpdate = d3.select(n[i])
184
+ .selectAll<SVGTextElement, LabelDatum>('text')
185
+ .data([datum])
186
+ const textEnter = textUpdate
187
+ .enter()
188
+ .append('text')
189
+ .style('dominant-baseline', 'hanging')
190
+ .style('cursor', 'pointer')
191
+ // .style('pointer-events', 'none')
192
+ const text = textUpdate.merge(textEnter)
193
+ .text(d => d.text)
194
+ .style('transform', gridAxesReverseTransformValue)
195
+ .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
196
+ .attr('font-size', fullChartParams.styles.textSize)
197
+ .attr('x', rectX + 6)
198
+ textUpdate.exit().remove()
199
+ })
200
+
201
+ return axisLabelSelection
202
+ }
203
+
204
+ function removeLabel (selection: d3.Selection<any, unknown, any, unknown>) {
205
+ const gUpdate = selection
206
+ .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
207
+ .data([])
208
+
209
+ gUpdate.exit().remove()
210
+ }
211
+
212
+ export const GroupAux = defineGridPlugin(pluginName, DEFAULT_GROUP_AREA_PARAMS)(({ selection, rootSelection, name, subject, observer }) => {
213
+ const destroy$ = new Subject()
214
+
215
+ const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
216
+ .insert('rect', 'g')
217
+ .classed(getClassName(pluginName, 'rect'), true)
218
+ .attr('opacity', 0)
219
+
220
+ const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
221
+ .append('g')
222
+
223
+ observer.layout$.pipe(
224
+ takeUntil(destroy$),
225
+ ).subscribe(d => {
226
+ rootRectSelection
227
+ .attr('width', d.rootWidth)
228
+ .attr('height', d.rootHeight)
229
+ })
230
+
231
+ observer.gridAxesTransform$
232
+ .pipe(
233
+ takeUntil(destroy$),
234
+ map(d => d.value),
235
+ distinctUntilChanged()
236
+ ).subscribe(d => {
237
+ axisSelection
238
+ .style('transform', d)
239
+ })
240
+
241
+ // const visibleComputedData$ = observer.computedData$.pipe(
242
+ // takeUntil(destroy$),
243
+ // map(data => {
244
+ // const visibleComputedData = data
245
+ // .map(d => {
246
+ // return d.filter(_d => {
247
+ // return _d.visible == true
248
+ // })
249
+ // })
250
+ // .filter(d => d.length)
251
+ // // console.log('visibleComputedData', visibleComputedData)
252
+ // return visibleComputedData
253
+ // })
254
+ // )
255
+
256
+ // const SeriesDataMap$ = visibleComputedData$.pipe(
257
+ // map(d => makeGridSeriesDataMap(d))
258
+ // )
259
+
260
+ // const GroupDataMap$ = visibleComputedData$.pipe(
261
+ // map(d => makeGridGroupDataMap(d))
262
+ // )
263
+
264
+ // const contentTransform$: Observable<string> = new Observable(subscriber => {
265
+ // combineLatest({
266
+ // fullParams: observer.fullParams$,
267
+ // gridAxesTransform: observer.gridAxesTransform$
268
+ // }).pipe(
269
+ // takeUntil(destroy$),
270
+ // // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
271
+ // switchMap(async (d) => d),
272
+ // ).subscribe(data => {
273
+
274
+ // const transformData = Object.assign({}, data.gridAxesTransform)
275
+
276
+ // // const value = getAxesTransformValue({
277
+ // // translate: [0, 0],
278
+ // // scale: [transformData.scale[0] * -1, transformData.scale[1] * -1],
279
+ // // rotate: transformData.rotate * -1,
280
+ // // rotateX: transformData.rotateX * -1,
281
+ // // rotateY: transformData.rotateY * -1
282
+ // // })
283
+
284
+ // subscriber.next(transformData.value)
285
+ // })
286
+ // })
287
+ // const reverseTransform$: Observable<TransformData> = observer.gridAxesTransform$.pipe(
288
+ // takeUntil(destroy$),
289
+ // map(d => {
290
+ // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
291
+ // const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
292
+ // const rotate = d.rotate * -1
293
+ // const rotateX = d.rotateX * -1
294
+ // const rotateY = d.rotateY * -1
295
+ // return {
296
+ // translate,
297
+ // scale,
298
+ // rotate,
299
+ // rotateX,
300
+ // rotateY,
301
+ // value: ''
302
+ // }
303
+ // }),
304
+ // )
305
+ // const contentTransform$ = combineLatest({
306
+ // fullParams: observer.fullParams$,
307
+ // reverseTransform: reverseTransform$
308
+ // }).pipe(
309
+ // takeUntil(destroy$),
310
+ // switchMap(async data => {
311
+ // const translate = [0, 0]
312
+ // return `translate(${translate[0]}px, ${translate[1]}px) rotate(${data.reverseTransform.rotate}deg) rotateX(${data.reverseTransform.rotateX}deg) rotateY(${data.reverseTransform.rotateY}deg)`
313
+ // }),
314
+ // distinctUntilChanged()
315
+ // )
316
+
317
+ const groupScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
318
+ combineLatest({
319
+ fullDataFormatter: observer.fullDataFormatter$,
320
+ gridAxesSize: observer.gridAxesSize$,
321
+ computedData: observer.computedData$
322
+ }).pipe(
323
+ takeUntil(destroy$),
324
+ switchMap(async (d) => d),
325
+ ).subscribe(data => {
326
+ const groupMin = 0
327
+ const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
328
+ const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
329
+ ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
330
+ : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
331
+ const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
332
+ ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
333
+ : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
334
+
335
+ const groupingLength = data.computedData[0]
336
+ ? data.computedData[0].length
337
+ : 0
338
+
339
+ let _labels = data.fullDataFormatter.grid.seriesDirection === 'row'
340
+ // ? data.fullDataFormatter.grid.columnLabels
341
+ // : data.fullDataFormatter.grid.rowLabels
342
+ ? (data.computedData[0] ?? []).map(d => d.groupLabel)
343
+ : data.computedData.map(d => d[0].groupLabel)
344
+
345
+ const axisLabels = new Array(groupingLength).fill(0)
346
+ .map((d, i) => {
347
+ return _labels[i] != null
348
+ ? _labels[i]
349
+ : String(i) // 沒有label則用序列號填充
350
+ })
351
+ .filter((d, i) => {
352
+ return i >= groupScaleDomainMin && i <= groupScaleDomainMax
353
+ })
354
+
355
+
356
+ const padding = data.fullDataFormatter.grid.groupAxis.scalePadding
357
+
358
+ const groupScale = createAxisPointScale({
359
+ axisLabels,
360
+ axisWidth: data.gridAxesSize.width,
361
+ padding
362
+ })
363
+
364
+ subscriber.next(groupScale)
365
+ })
366
+ })
367
+
368
+ // 取得事件座標的group資料
369
+ const gridGroupPositionFn$ = gridGroupPositionFnObservable({
370
+ fullDataFormatter$: observer.fullDataFormatter$,
371
+ gridAxesSize$: observer.gridAxesSize$,
372
+ computedData$: observer.computedData$,
373
+ fullChartParams$: observer.fullChartParams$,
374
+ })
375
+
376
+ const highlightTarget$ = observer.fullChartParams$.pipe(
377
+ takeUntil(destroy$),
378
+ map(d => d.highlightTarget),
379
+ distinctUntilChanged()
380
+ )
381
+
382
+ combineLatest({
383
+ computedData: observer.computedData$,
384
+ gridAxesSize: observer.gridAxesSize$,
385
+ fullParams: observer.fullParams$,
386
+ fullChartParams: observer.fullChartParams$,
387
+ highlightTarget: highlightTarget$,
388
+ SeriesDataMap: observer.SeriesDataMap$,
389
+ GroupDataMap: observer.GroupDataMap$,
390
+ gridGroupPositionFn: gridGroupPositionFn$,
391
+ groupScale: groupScale$,
392
+ }).pipe(
393
+ takeUntil(destroy$),
394
+ switchMap(async (d) => d),
395
+ ).subscribe(data => {
396
+
397
+ // store.selection
398
+ rootSelection
399
+ .on('mouseover', (event, datum) => {
400
+ // event.stopPropagation()
401
+
402
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
403
+
404
+ subject.event$.next({
405
+ type: 'grid',
406
+ pluginName: name,
407
+ eventName: 'mouseover',
408
+ highlightTarget: data.highlightTarget,
409
+ datum: null,
410
+ gridIndex: 0, // @Q@ 暫不處理
411
+ series: [],
412
+ seriesIndex: -1,
413
+ seriesLabel: '',
414
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
415
+ groupIndex,
416
+ groupLabel,
417
+ event,
418
+ data: data.computedData
419
+ })
420
+ })
421
+ .on('mousemove', (event, datum) => {
422
+ // event.stopPropagation()
423
+
424
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
425
+
426
+ subject.event$.next({
427
+ type: 'grid',
428
+ pluginName: name,
429
+ eventName: 'mousemove',
430
+ highlightTarget: data.highlightTarget,
431
+ datum: null,
432
+ gridIndex: 0, // @Q@ 暫不處理
433
+ series: [],
434
+ seriesIndex: -1,
435
+ seriesLabel: '',
436
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
437
+ groupIndex,
438
+ groupLabel,
439
+ event,
440
+ data: data.computedData
441
+ })
442
+ })
443
+ .on('mouseout', (event, datum) => {
444
+ // event.stopPropagation()
445
+
446
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
447
+
448
+ subject.event$.next({
449
+ type: 'grid',
450
+ pluginName: name,
451
+ eventName: 'mouseout',
452
+ highlightTarget: data.highlightTarget,
453
+ datum: null,
454
+ gridIndex: 0, // @Q@ 暫不處理
455
+ series: [],
456
+ seriesIndex: -1,
457
+ seriesLabel: '',
458
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
459
+ groupIndex,
460
+ groupLabel,
461
+ event,
462
+ data: data.computedData
463
+ })
464
+ })
465
+ .on('click', (event, datum) => {
466
+ event.stopPropagation()
467
+
468
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
469
+
470
+ subject.event$.next({
471
+ type: 'grid',
472
+ pluginName: name,
473
+ eventName: 'click',
474
+ highlightTarget: data.highlightTarget,
475
+ datum: null,
476
+ gridIndex: 0, // @Q@ 暫不處理
477
+ series: [],
478
+ seriesIndex: -1,
479
+ seriesLabel: '',
480
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
481
+ groupIndex,
482
+ groupLabel,
483
+ event,
484
+ data: data.computedData
485
+ })
486
+ })
487
+
488
+ // barSelection$.next(barSelection!)
489
+ })
490
+
491
+ // -- highlight(無論highlightTarget設定為何,一律依從groupLabel來顯示) --
492
+ combineLatest({
493
+ // highlight: highlight$,
494
+ event: subject.event$.pipe(
495
+ filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove')
496
+ ),
497
+ computedData: observer.computedData$,
498
+ groupScale: groupScale$,
499
+ gridAxesSize: observer.gridAxesSize$,
500
+ fullParams: observer.fullParams$,
501
+ fullChartParams: observer.fullChartParams$,
502
+ highlightTarget: highlightTarget$,
503
+ gridAxesReverseTransform: observer.gridAxesReverseTransform$,
504
+ GroupDataMap: observer.GroupDataMap$,
505
+ gridGroupPositionFn: gridGroupPositionFn$,
506
+ textSizePx: observer.textSizePx$
507
+ }).pipe(
508
+ takeUntil(destroy$),
509
+ switchMap(async d => d)
510
+ ).subscribe(data => {
511
+ // const groups = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
512
+ // ? data.event.groups
513
+ // : []
514
+
515
+ // const groupLabel = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
516
+ // ? data.event.groupLabel
517
+ // : ''
518
+ const axisX = data.groupScale(data.event.groupLabel) ?? 0
519
+
520
+ const lineData = createLineData({
521
+ groupLabel: data.event.groupLabel,
522
+ axisX,
523
+ axisHeight: data.gridAxesSize.height,
524
+ fullParams: data.fullParams,
525
+ })
526
+ renderLine({
527
+ selection: axisSelection,
528
+ pluginName: name,
529
+ lineData,
530
+ fullParams: data.fullParams,
531
+ fullChartParams: data.fullChartParams
532
+ })
533
+ const labelData = createLabelData({
534
+ groupLabel: data.event.groupLabel,
535
+ axisX,
536
+ fullParams: data.fullParams
537
+ })
538
+ const labelSelection = renderLabel({
539
+ selection: axisSelection,
540
+ labelData,
541
+ fullParams: data.fullParams,
542
+ fullChartParams: data.fullChartParams,
543
+ gridAxesReverseTransformValue: data.gridAxesReverseTransform.value,
544
+ textSizePx: data.textSizePx
545
+ })
546
+
547
+ // label的事件
548
+ labelSelection
549
+ .on('mouseover', (event, datum) => {
550
+
551
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
552
+
553
+ subject.event$.next({
554
+ type: 'grid',
555
+ pluginName: name,
556
+ eventName: 'mouseover',
557
+ highlightTarget: data.highlightTarget,
558
+ datum: null,
559
+ gridIndex: 0, // @Q@ 暫不處理
560
+ series: [],
561
+ seriesIndex: -1,
562
+ seriesLabel: '',
563
+ groups: data.event.groups,
564
+ groupIndex,
565
+ groupLabel,
566
+ event,
567
+ data: data.computedData
568
+ })
569
+ })
570
+ .on('mousemove', (event, datum) => {
571
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
572
+
573
+ subject.event$.next({
574
+ type: 'grid',
575
+ pluginName: name,
576
+ eventName: 'mousemove',
577
+ highlightTarget: data.highlightTarget,
578
+ datum: null,
579
+ gridIndex: 0, // @Q@ 暫不處理
580
+ series: [],
581
+ seriesIndex: -1,
582
+ seriesLabel: '',
583
+ groups: data.event.groups,
584
+ groupIndex,
585
+ groupLabel,
586
+ event,
587
+ data: data.computedData
588
+ })
589
+ })
590
+ .on('mouseout', (event, datum) => {
591
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
592
+
593
+ subject.event$.next({
594
+ type: 'grid',
595
+ pluginName: name,
596
+ eventName: 'mouseout',
597
+ highlightTarget: data.highlightTarget,
598
+ datum: null,
599
+ gridIndex: 0, // @Q@ 暫不處理
600
+ series: [],
601
+ seriesIndex: -1,
602
+ seriesLabel: '',
603
+ groups: data.event.groups,
604
+ groupIndex,
605
+ groupLabel,
606
+ event,
607
+ data: data.computedData
608
+ })
609
+ })
610
+ .on('click', (event, datum) => {
611
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
612
+
613
+ subject.event$.next({
614
+ type: 'grid',
615
+ pluginName: name,
616
+ eventName: 'click',
617
+ highlightTarget: data.highlightTarget,
618
+ datum: null,
619
+ gridIndex: 0, // @Q@ 暫不處理
620
+ series: [],
621
+ seriesIndex: -1,
622
+ seriesLabel: '',
623
+ groups: data.event.groups,
624
+ groupIndex,
625
+ groupLabel,
626
+ event,
627
+ data: data.computedData
628
+ })
629
+ })
630
+ })
631
+
632
+ const rootMouseout$ = d3EventObservable(rootRectSelection, 'mouseout').pipe(
633
+ takeUntil(destroy$),
634
+ )
635
+
636
+ rootMouseout$.subscribe(event => {
637
+ console.log('rootMouseout')
638
+ removeLine(axisSelection)
639
+ removeLabel(axisSelection)
640
+ })
641
+
642
+ return () => {
643
+ destroy$.next(undefined)
644
+ rootRectSelection.remove()
645
+ }
647
646
  })