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

Sign up to get free protection for your applications and to get access to all the features.
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
  })