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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-plugins-basic.es.js +5611 -5571
  3. package/dist/orbcharts-plugins-basic.umd.js +7 -7
  4. package/dist/src/base/BaseLegend.d.ts +1 -0
  5. package/package.json +42 -42
  6. package/src/base/BaseBarStack.ts +881 -881
  7. package/src/base/BaseBars.ts +750 -750
  8. package/src/base/BaseBarsTriangle.ts +659 -659
  9. package/src/base/BaseDots.ts +639 -639
  10. package/src/base/BaseGroupAxis.ts +496 -496
  11. package/src/base/BaseLegend.ts +641 -636
  12. package/src/base/BaseLineAreas.ts +621 -621
  13. package/src/base/BaseLines.ts +692 -692
  14. package/src/base/BaseValueAxis.ts +479 -479
  15. package/src/base/types.ts +2 -2
  16. package/src/grid/defaults.ts +121 -121
  17. package/src/grid/gridObservables.ts +263 -263
  18. package/src/grid/index.ts +15 -15
  19. package/src/grid/plugins/BarStack.ts +37 -37
  20. package/src/grid/plugins/Bars.ts +37 -37
  21. package/src/grid/plugins/BarsDiverging.ts +39 -39
  22. package/src/grid/plugins/BarsTriangle.ts +34 -34
  23. package/src/grid/plugins/Dots.ts +35 -35
  24. package/src/grid/plugins/GridLegend.ts +59 -58
  25. package/src/grid/plugins/GroupAux.ts +646 -643
  26. package/src/grid/plugins/GroupAxis.ts +30 -30
  27. package/src/grid/plugins/LineAreas.ts +36 -36
  28. package/src/grid/plugins/Lines.ts +35 -35
  29. package/src/grid/plugins/ScalingArea.ts +174 -174
  30. package/src/grid/plugins/ValueAxis.ts +31 -31
  31. package/src/grid/plugins/ValueStackAxis.ts +70 -70
  32. package/src/grid/types.ts +120 -120
  33. package/src/index.ts +9 -9
  34. package/src/multiGrid/defaults.ts +147 -147
  35. package/src/multiGrid/index.ts +11 -11
  36. package/src/multiGrid/multiGridObservables.ts +289 -289
  37. package/src/multiGrid/plugins/MultiBarStack.ts +60 -60
  38. package/src/multiGrid/plugins/MultiBars.ts +59 -59
  39. package/src/multiGrid/plugins/MultiBarsTriangle.ts +58 -58
  40. package/src/multiGrid/plugins/MultiDots.ts +58 -58
  41. package/src/multiGrid/plugins/MultiGridLegend.ts +89 -88
  42. package/src/multiGrid/plugins/MultiGroupAxis.ts +53 -53
  43. package/src/multiGrid/plugins/MultiLineAreas.ts +59 -59
  44. package/src/multiGrid/plugins/MultiLines.ts +58 -58
  45. package/src/multiGrid/plugins/MultiValueAxis.ts +53 -53
  46. package/src/multiGrid/plugins/OverlappingValueAxes.ts +164 -164
  47. package/src/multiGrid/types.ts +67 -67
  48. package/src/noneData/defaults.ts +61 -61
  49. package/src/noneData/index.ts +3 -3
  50. package/src/noneData/plugins/Container.ts +10 -10
  51. package/src/noneData/plugins/Tooltip.ts +310 -304
  52. package/src/noneData/types.ts +26 -26
  53. package/src/series/defaults.ts +99 -99
  54. package/src/series/index.ts +6 -6
  55. package/src/series/plugins/Bubbles.ts +551 -551
  56. package/src/series/plugins/Pie.ts +600 -600
  57. package/src/series/plugins/PieEventTexts.ts +194 -194
  58. package/src/series/plugins/PieLabels.ts +288 -288
  59. package/src/series/plugins/SeriesLegend.ts +59 -58
  60. package/src/series/seriesUtils.ts +50 -50
  61. package/src/series/types.ts +67 -67
  62. package/src/tree/defaults.ts +22 -22
  63. package/src/tree/index.ts +3 -3
  64. package/src/tree/plugins/TreeLegend.ts +59 -58
  65. package/src/tree/plugins/TreeMap.ts +305 -302
  66. package/src/tree/types.ts +23 -23
  67. package/src/utils/commonUtils.ts +21 -21
  68. package/src/utils/d3Graphics.ts +124 -124
  69. package/src/utils/d3Utils.ts +73 -73
  70. package/src/utils/observables.ts +14 -14
  71. package/src/utils/orbchartsUtils.ts +100 -100
  72. package/tsconfig.dev.json +16 -16
  73. package/tsconfig.json +13 -13
  74. package/tsconfig.prod.json +13 -13
  75. package/vite.config.js +49 -49
@@ -1,644 +1,647 @@
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 }: {
130
- selection: d3.Selection<any, unknown, any, unknown>
131
- labelData: LabelDatum[]
132
- fullParams: GroupAuxParams
133
- fullChartParams: ChartParams
134
- gridAxesReverseTransformValue: string
135
- }) {
136
- const rectHeight = fullChartParams.styles.textSize + 4
137
-
138
- const gUpdate = selection
139
- .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
140
- .data(labelData)
141
- const gEnter = gUpdate
142
- .enter()
143
- .append('g')
144
- .classed(labelClassName, true)
145
- .style('cursor', 'pointer')
146
- const axisLabelSelection = gEnter.merge(gUpdate)
147
- gEnter
148
- .attr("transform", (d, i) => {
149
- return `translate(${d.x}, ${d.y})`
150
- })
151
- gUpdate
152
- .transition()
153
- .duration(50)
154
- .attr("transform", (d, i) => {
155
- return `translate(${d.x}, ${d.y})`
156
- })
157
- gUpdate.exit().remove()
158
-
159
- axisLabelSelection.each((datum, i, n) => {
160
- const rectWidth = measureTextWidth(datum.text, fullChartParams.styles.textSize) + 12
161
- const rectX = - rectWidth / 2
162
-
163
- const rectUpdate = d3.select(n[i])
164
- .selectAll<SVGRectElement, LabelDatum>('rect')
165
- .data([datum])
166
- const rectEnter = rectUpdate
167
- .enter()
168
- .append('rect')
169
- .attr('height', `${rectHeight}px`)
170
- .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
171
- .attr('x', rectX)
172
- .attr('y', -2)
173
- .attr('rx', 5)
174
- .attr('ry', 5)
175
- .style('cursor', 'pointer')
176
- // .style('pointer-events', 'none')
177
- const rect = rectUpdate.merge(rectEnter)
178
- .attr('width', d => `${rectWidth}px`)
179
- .style('transform', gridAxesReverseTransformValue)
180
- rectUpdate.exit().remove()
181
-
182
- const textUpdate = d3.select(n[i])
183
- .selectAll<SVGTextElement, LabelDatum>('text')
184
- .data([datum])
185
- const textEnter = textUpdate
186
- .enter()
187
- .append('text')
188
- .style('dominant-baseline', 'hanging')
189
- .style('cursor', 'pointer')
190
- // .style('pointer-events', 'none')
191
- const text = textUpdate.merge(textEnter)
192
- .text(d => d.text)
193
- .style('transform', gridAxesReverseTransformValue)
194
- .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
195
- .attr('font-size', fullChartParams.styles.textSize)
196
- .attr('x', rectX + 6)
197
- textUpdate.exit().remove()
198
- })
199
-
200
- return axisLabelSelection
201
- }
202
-
203
- function removeLabel (selection: d3.Selection<any, unknown, any, unknown>) {
204
- const gUpdate = selection
205
- .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
206
- .data([])
207
-
208
- gUpdate.exit().remove()
209
- }
210
-
211
- export const GroupAux = defineGridPlugin(pluginName, DEFAULT_GROUP_AREA_PARAMS)(({ selection, rootSelection, name, subject, observer }) => {
212
- const destroy$ = new Subject()
213
-
214
- const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
215
- .insert('rect', 'g')
216
- .classed(getClassName(pluginName, 'rect'), true)
217
- .attr('opacity', 0)
218
-
219
- const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
220
- .append('g')
221
-
222
- observer.layout$.pipe(
223
- takeUntil(destroy$),
224
- ).subscribe(d => {
225
- rootRectSelection
226
- .attr('width', d.rootWidth)
227
- .attr('height', d.rootHeight)
228
- })
229
-
230
- observer.gridAxesTransform$
231
- .pipe(
232
- takeUntil(destroy$),
233
- map(d => d.value),
234
- distinctUntilChanged()
235
- ).subscribe(d => {
236
- axisSelection
237
- .style('transform', d)
238
- })
239
-
240
- // const visibleComputedData$ = observer.computedData$.pipe(
241
- // takeUntil(destroy$),
242
- // map(data => {
243
- // const visibleComputedData = data
244
- // .map(d => {
245
- // return d.filter(_d => {
246
- // return _d.visible == true
247
- // })
248
- // })
249
- // .filter(d => d.length)
250
- // // console.log('visibleComputedData', visibleComputedData)
251
- // return visibleComputedData
252
- // })
253
- // )
254
-
255
- // const SeriesDataMap$ = visibleComputedData$.pipe(
256
- // map(d => makeGridSeriesDataMap(d))
257
- // )
258
-
259
- // const GroupDataMap$ = visibleComputedData$.pipe(
260
- // map(d => makeGridGroupDataMap(d))
261
- // )
262
-
263
- // const contentTransform$: Observable<string> = new Observable(subscriber => {
264
- // combineLatest({
265
- // fullParams: observer.fullParams$,
266
- // gridAxesTransform: observer.gridAxesTransform$
267
- // }).pipe(
268
- // takeUntil(destroy$),
269
- // // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
270
- // switchMap(async (d) => d),
271
- // ).subscribe(data => {
272
-
273
- // const transformData = Object.assign({}, data.gridAxesTransform)
274
-
275
- // // const value = getAxesTransformValue({
276
- // // translate: [0, 0],
277
- // // scale: [transformData.scale[0] * -1, transformData.scale[1] * -1],
278
- // // rotate: transformData.rotate * -1,
279
- // // rotateX: transformData.rotateX * -1,
280
- // // rotateY: transformData.rotateY * -1
281
- // // })
282
-
283
- // subscriber.next(transformData.value)
284
- // })
285
- // })
286
- // const reverseTransform$: Observable<TransformData> = observer.gridAxesTransform$.pipe(
287
- // takeUntil(destroy$),
288
- // map(d => {
289
- // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
290
- // const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
291
- // const rotate = d.rotate * -1
292
- // const rotateX = d.rotateX * -1
293
- // const rotateY = d.rotateY * -1
294
- // return {
295
- // translate,
296
- // scale,
297
- // rotate,
298
- // rotateX,
299
- // rotateY,
300
- // value: ''
301
- // }
302
- // }),
303
- // )
304
- // const contentTransform$ = combineLatest({
305
- // fullParams: observer.fullParams$,
306
- // reverseTransform: reverseTransform$
307
- // }).pipe(
308
- // takeUntil(destroy$),
309
- // switchMap(async data => {
310
- // const translate = [0, 0]
311
- // return `translate(${translate[0]}px, ${translate[1]}px) rotate(${data.reverseTransform.rotate}deg) rotateX(${data.reverseTransform.rotateX}deg) rotateY(${data.reverseTransform.rotateY}deg)`
312
- // }),
313
- // distinctUntilChanged()
314
- // )
315
-
316
- const groupScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
317
- combineLatest({
318
- fullDataFormatter: observer.fullDataFormatter$,
319
- gridAxesSize: observer.gridAxesSize$,
320
- computedData: observer.computedData$
321
- }).pipe(
322
- takeUntil(destroy$),
323
- switchMap(async (d) => d),
324
- ).subscribe(data => {
325
- const groupMin = 0
326
- const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
327
- const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
328
- ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
329
- : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
330
- const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
331
- ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
332
- : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
333
-
334
- const groupingLength = data.computedData[0]
335
- ? data.computedData[0].length
336
- : 0
337
-
338
- let _labels = data.fullDataFormatter.grid.gridData.seriesDirection === 'row'
339
- // ? data.fullDataFormatter.grid.columnLabels
340
- // : data.fullDataFormatter.grid.rowLabels
341
- ? (data.computedData[0] ?? []).map(d => d.groupLabel)
342
- : data.computedData.map(d => d[0].groupLabel)
343
-
344
- const axisLabels = new Array(groupingLength).fill(0)
345
- .map((d, i) => {
346
- return _labels[i] != null
347
- ? _labels[i]
348
- : String(i) // 沒有label則用序列號填充
349
- })
350
- .filter((d, i) => {
351
- return i >= groupScaleDomainMin && i <= groupScaleDomainMax
352
- })
353
-
354
-
355
- const padding = data.fullDataFormatter.grid.groupAxis.scalePadding
356
-
357
- const groupScale = createAxisPointScale({
358
- axisLabels,
359
- axisWidth: data.gridAxesSize.width,
360
- padding
361
- })
362
-
363
- subscriber.next(groupScale)
364
- })
365
- })
366
-
367
- // 取得事件座標的group資料
368
- const gridGroupPositionFn$ = gridGroupPositionFnObservable({
369
- fullDataFormatter$: observer.fullDataFormatter$,
370
- gridAxesSize$: observer.gridAxesSize$,
371
- computedData$: observer.computedData$,
372
- fullChartParams$: observer.fullChartParams$,
373
- })
374
-
375
- const highlightTarget$ = observer.fullChartParams$.pipe(
376
- takeUntil(destroy$),
377
- map(d => d.highlightTarget),
378
- distinctUntilChanged()
379
- )
380
-
381
- combineLatest({
382
- computedData: observer.computedData$,
383
- gridAxesSize: observer.gridAxesSize$,
384
- fullParams: observer.fullParams$,
385
- fullChartParams: observer.fullChartParams$,
386
- highlightTarget: highlightTarget$,
387
- SeriesDataMap: observer.SeriesDataMap$,
388
- GroupDataMap: observer.GroupDataMap$,
389
- gridGroupPositionFn: gridGroupPositionFn$,
390
- groupScale: groupScale$,
391
- }).pipe(
392
- takeUntil(destroy$),
393
- // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
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
- }).pipe(
507
- takeUntil(destroy$),
508
- switchMap(async d => d)
509
- ).subscribe(data => {
510
- // const groups = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
511
- // ? data.event.groups
512
- // : []
513
-
514
- // const groupLabel = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
515
- // ? data.event.groupLabel
516
- // : ''
517
- const axisX = data.groupScale(data.event.groupLabel) ?? 0
518
-
519
- const lineData = createLineData({
520
- groupLabel: data.event.groupLabel,
521
- axisX,
522
- axisHeight: data.gridAxesSize.height,
523
- fullParams: data.fullParams,
524
- })
525
- renderLine({
526
- selection: axisSelection,
527
- pluginName: name,
528
- lineData,
529
- fullParams: data.fullParams,
530
- fullChartParams: data.fullChartParams
531
- })
532
- const labelData = createLabelData({
533
- groupLabel: data.event.groupLabel,
534
- axisX,
535
- fullParams: data.fullParams
536
- })
537
- const labelSelection = renderLabel({
538
- selection: axisSelection,
539
- labelData,
540
- fullParams: data.fullParams,
541
- fullChartParams: data.fullChartParams,
542
- gridAxesReverseTransformValue: data.gridAxesReverseTransform.value
543
- })
544
-
545
- // label的事件
546
- labelSelection
547
- .on('mouseover', (event, datum) => {
548
-
549
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
550
-
551
- subject.event$.next({
552
- type: 'grid',
553
- pluginName: name,
554
- eventName: 'mouseover',
555
- highlightTarget: data.highlightTarget,
556
- datum: null,
557
- gridIndex: 0, // @Q@ 暫不處理
558
- series: [],
559
- seriesIndex: -1,
560
- seriesLabel: '',
561
- groups: data.event.groups,
562
- groupIndex,
563
- groupLabel,
564
- event,
565
- data: data.computedData
566
- })
567
- })
568
- .on('mousemove', (event, datum) => {
569
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
570
-
571
- subject.event$.next({
572
- type: 'grid',
573
- pluginName: name,
574
- eventName: 'mousemove',
575
- highlightTarget: data.highlightTarget,
576
- datum: null,
577
- gridIndex: 0, // @Q@ 暫不處理
578
- series: [],
579
- seriesIndex: -1,
580
- seriesLabel: '',
581
- groups: data.event.groups,
582
- groupIndex,
583
- groupLabel,
584
- event,
585
- data: data.computedData
586
- })
587
- })
588
- .on('mouseout', (event, datum) => {
589
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
590
-
591
- subject.event$.next({
592
- type: 'grid',
593
- pluginName: name,
594
- eventName: 'mouseout',
595
- highlightTarget: data.highlightTarget,
596
- datum: null,
597
- gridIndex: 0, // @Q@ 暫不處理
598
- series: [],
599
- seriesIndex: -1,
600
- seriesLabel: '',
601
- groups: data.event.groups,
602
- groupIndex,
603
- groupLabel,
604
- event,
605
- data: data.computedData
606
- })
607
- })
608
- .on('click', (event, datum) => {
609
- const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
610
-
611
- subject.event$.next({
612
- type: 'grid',
613
- pluginName: name,
614
- eventName: 'click',
615
- highlightTarget: data.highlightTarget,
616
- datum: null,
617
- gridIndex: 0, // @Q@ 暫不處理
618
- series: [],
619
- seriesIndex: -1,
620
- seriesLabel: '',
621
- groups: data.event.groups,
622
- groupIndex,
623
- groupLabel,
624
- event,
625
- data: data.computedData
626
- })
627
- })
628
- })
629
-
630
- const rootMouseout$ = d3EventObservable(rootRectSelection, 'mouseout').pipe(
631
- takeUntil(destroy$),
632
- )
633
-
634
- rootMouseout$.subscribe(event => {
635
- console.log('rootMouseout')
636
- removeLine(axisSelection)
637
- removeLabel(axisSelection)
638
- })
639
-
640
- return () => {
641
- destroy$.next(undefined)
642
- rootRectSelection.remove()
643
- }
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
+ }
644
647
  })