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

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 (84) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-plugins-basic.es.js +5477 -5426
  3. package/dist/orbcharts-plugins-basic.umd.js +8 -8
  4. package/dist/src/base/BaseBarStack.d.ts +1 -1
  5. package/dist/src/base/BaseBars.d.ts +1 -1
  6. package/dist/src/base/BaseBarsTriangle.d.ts +1 -1
  7. package/dist/src/base/BaseDots.d.ts +1 -1
  8. package/dist/src/base/BaseLineAreas.d.ts +1 -1
  9. package/dist/src/base/BaseLines.d.ts +1 -1
  10. package/dist/src/multiGrid/defaults.d.ts +2 -1
  11. package/dist/src/multiGrid/index.d.ts +1 -0
  12. package/dist/src/multiGrid/plugins/MultiLineAreas.d.ts +1 -0
  13. package/dist/src/multiGrid/types.d.ts +4 -4
  14. package/package.json +42 -42
  15. package/src/base/BaseBarStack.ts +881 -879
  16. package/src/base/BaseBars.ts +750 -748
  17. package/src/base/BaseBarsTriangle.ts +659 -657
  18. package/src/base/BaseDots.ts +639 -637
  19. package/src/base/BaseGroupAxis.ts +496 -496
  20. package/src/base/BaseLegend.ts +636 -636
  21. package/src/base/BaseLineAreas.ts +621 -624
  22. package/src/base/BaseLines.ts +692 -695
  23. package/src/base/BaseValueAxis.ts +479 -479
  24. package/src/base/types.ts +2 -2
  25. package/src/grid/defaults.ts +121 -121
  26. package/src/grid/gridObservables.ts +263 -263
  27. package/src/grid/index.ts +15 -15
  28. package/src/grid/plugins/BarStack.ts +37 -37
  29. package/src/grid/plugins/Bars.ts +37 -37
  30. package/src/grid/plugins/BarsDiverging.ts +39 -39
  31. package/src/grid/plugins/BarsTriangle.ts +34 -34
  32. package/src/grid/plugins/Dots.ts +35 -35
  33. package/src/grid/plugins/GridLegend.ts +58 -58
  34. package/src/grid/plugins/GroupAux.ts +643 -643
  35. package/src/grid/plugins/GroupAxis.ts +30 -30
  36. package/src/grid/plugins/LineAreas.ts +36 -36
  37. package/src/grid/plugins/Lines.ts +35 -35
  38. package/src/grid/plugins/ScalingArea.ts +174 -174
  39. package/src/grid/plugins/ValueAxis.ts +31 -31
  40. package/src/grid/plugins/ValueStackAxis.ts +70 -70
  41. package/src/grid/types.ts +120 -120
  42. package/src/index.ts +9 -9
  43. package/src/multiGrid/defaults.ts +147 -140
  44. package/src/multiGrid/index.ts +11 -10
  45. package/src/multiGrid/multiGridObservables.ts +289 -278
  46. package/src/multiGrid/plugins/MultiBarStack.ts +60 -60
  47. package/src/multiGrid/plugins/MultiBars.ts +59 -59
  48. package/src/multiGrid/plugins/MultiBarsTriangle.ts +58 -58
  49. package/src/multiGrid/plugins/MultiDots.ts +58 -58
  50. package/src/multiGrid/plugins/MultiGridLegend.ts +88 -88
  51. package/src/multiGrid/plugins/MultiGroupAxis.ts +53 -53
  52. package/src/multiGrid/plugins/MultiLineAreas.ts +59 -0
  53. package/src/multiGrid/plugins/MultiLines.ts +58 -58
  54. package/src/multiGrid/plugins/MultiValueAxis.ts +53 -53
  55. package/src/multiGrid/plugins/OverlappingValueAxes.ts +164 -165
  56. package/src/multiGrid/types.ts +67 -67
  57. package/src/noneData/defaults.ts +61 -61
  58. package/src/noneData/index.ts +3 -3
  59. package/src/noneData/plugins/Container.ts +10 -10
  60. package/src/noneData/plugins/Tooltip.ts +304 -304
  61. package/src/noneData/types.ts +26 -26
  62. package/src/series/defaults.ts +99 -99
  63. package/src/series/index.ts +6 -6
  64. package/src/series/plugins/Bubbles.ts +551 -549
  65. package/src/series/plugins/Pie.ts +600 -598
  66. package/src/series/plugins/PieEventTexts.ts +194 -194
  67. package/src/series/plugins/PieLabels.ts +288 -285
  68. package/src/series/plugins/SeriesLegend.ts +58 -58
  69. package/src/series/seriesUtils.ts +50 -50
  70. package/src/series/types.ts +67 -67
  71. package/src/tree/defaults.ts +22 -22
  72. package/src/tree/index.ts +3 -3
  73. package/src/tree/plugins/TreeLegend.ts +58 -58
  74. package/src/tree/plugins/TreeMap.ts +302 -300
  75. package/src/tree/types.ts +23 -23
  76. package/src/utils/commonUtils.ts +21 -21
  77. package/src/utils/d3Graphics.ts +124 -124
  78. package/src/utils/d3Utils.ts +73 -73
  79. package/src/utils/observables.ts +14 -14
  80. package/src/utils/orbchartsUtils.ts +100 -100
  81. package/tsconfig.dev.json +16 -16
  82. package/tsconfig.json +13 -13
  83. package/tsconfig.prod.json +13 -13
  84. package/vite.config.js +49 -49
@@ -1,644 +1,644 @@
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 }: {
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
+ }
644
644
  })