@orbcharts/plugins-basic 3.0.0-alpha.58 → 3.0.0-alpha.59

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. package/LICENSE +200 -200
  2. package/package.json +43 -43
  3. package/src/base/BaseBarStack.ts +778 -778
  4. package/src/base/BaseBars.ts +764 -764
  5. package/src/base/BaseBarsTriangle.ts +672 -672
  6. package/src/base/BaseDots.ts +513 -513
  7. package/src/base/BaseGroupAxis.ts +558 -558
  8. package/src/base/BaseLegend.ts +641 -641
  9. package/src/base/BaseLineAreas.ts +628 -628
  10. package/src/base/BaseLines.ts +704 -704
  11. package/src/base/BaseValueAxis.ts +478 -478
  12. package/src/base/types.ts +2 -2
  13. package/src/grid/defaults.ts +128 -128
  14. package/src/grid/gridObservables.ts +541 -541
  15. package/src/grid/index.ts +15 -15
  16. package/src/grid/plugins/BarStack.ts +43 -43
  17. package/src/grid/plugins/Bars.ts +44 -44
  18. package/src/grid/plugins/BarsPN.ts +41 -41
  19. package/src/grid/plugins/BarsTriangle.ts +42 -42
  20. package/src/grid/plugins/Dots.ts +37 -37
  21. package/src/grid/plugins/GridLegend.ts +59 -59
  22. package/src/grid/plugins/GroupAux.ts +976 -976
  23. package/src/grid/plugins/GroupAxis.ts +35 -35
  24. package/src/grid/plugins/LineAreas.ts +40 -40
  25. package/src/grid/plugins/Lines.ts +40 -40
  26. package/src/grid/plugins/ScalingArea.ts +173 -173
  27. package/src/grid/plugins/ValueAxis.ts +36 -36
  28. package/src/grid/plugins/ValueStackAxis.ts +38 -38
  29. package/src/grid/types.ts +123 -123
  30. package/src/index.ts +9 -9
  31. package/src/multiGrid/defaults.ts +158 -158
  32. package/src/multiGrid/index.ts +13 -13
  33. package/src/multiGrid/multiGridObservables.ts +49 -49
  34. package/src/multiGrid/plugins/MultiBarStack.ts +78 -78
  35. package/src/multiGrid/plugins/MultiBars.ts +77 -77
  36. package/src/multiGrid/plugins/MultiBarsTriangle.ts +77 -77
  37. package/src/multiGrid/plugins/MultiDots.ts +65 -65
  38. package/src/multiGrid/plugins/MultiGridLegend.ts +89 -89
  39. package/src/multiGrid/plugins/MultiGroupAxis.ts +69 -69
  40. package/src/multiGrid/plugins/MultiLineAreas.ts +77 -77
  41. package/src/multiGrid/plugins/MultiLines.ts +77 -77
  42. package/src/multiGrid/plugins/MultiValueAxis.ts +69 -69
  43. package/src/multiGrid/plugins/MultiValueStackAxis.ts +69 -69
  44. package/src/multiGrid/plugins/OverlappingValueAxes.ts +167 -167
  45. package/src/multiGrid/plugins/OverlappingValueStackAxes.ts +168 -168
  46. package/src/multiGrid/types.ts +72 -72
  47. package/src/noneData/defaults.ts +102 -102
  48. package/src/noneData/index.ts +3 -3
  49. package/src/noneData/plugins/Container.ts +10 -10
  50. package/src/noneData/plugins/Tooltip.ts +310 -310
  51. package/src/noneData/types.ts +26 -26
  52. package/src/series/defaults.ts +144 -144
  53. package/src/series/index.ts +9 -9
  54. package/src/series/plugins/Bubbles.ts +545 -545
  55. package/src/series/plugins/Pie.ts +576 -576
  56. package/src/series/plugins/PieEventTexts.ts +262 -262
  57. package/src/series/plugins/PieLabels.ts +304 -304
  58. package/src/series/plugins/Rose.ts +472 -472
  59. package/src/series/plugins/RoseLabels.ts +362 -362
  60. package/src/series/plugins/SeriesLegend.ts +59 -59
  61. package/src/series/seriesObservables.ts +145 -145
  62. package/src/series/seriesUtils.ts +51 -51
  63. package/src/series/types.ts +83 -83
  64. package/src/tree/defaults.ts +23 -23
  65. package/src/tree/index.ts +3 -3
  66. package/src/tree/plugins/TreeLegend.ts +59 -59
  67. package/src/tree/plugins/TreeMap.ts +305 -305
  68. package/src/tree/types.ts +23 -23
  69. package/src/utils/commonUtils.ts +21 -21
  70. package/src/utils/d3Graphics.ts +124 -124
  71. package/src/utils/d3Utils.ts +73 -73
  72. package/src/utils/observables.ts +14 -14
  73. package/src/utils/orbchartsUtils.ts +100 -100
  74. package/tsconfig.base.json +13 -13
  75. package/{tsconfig.json.bak.vite-plugin-tsconfig → tsconfig.json} +7 -7
  76. package/tsconfig.prod.json +2 -2
  77. package/vite.config.mjs +40 -40
@@ -1,304 +1,304 @@
1
- import * as d3 from 'd3'
2
- import {
3
- combineLatest,
4
- switchMap,
5
- first,
6
- map,
7
- takeUntil,
8
- Observable,
9
- distinctUntilChanged,
10
- Subject,
11
- BehaviorSubject } from 'rxjs'
12
- import {
13
- defineSeriesPlugin } from '@orbcharts/core'
14
- import type {
15
- ComputedDatumSeries,
16
- SeriesContainerPosition,
17
- EventSeries,
18
- ChartParams } from '@orbcharts/core'
19
- import type { PieLabelsParams } from '../types'
20
- import type { PieDatum } from '../seriesUtils'
21
- import { DEFAULT_PIE_LABELS_PARAMS } from '../defaults'
22
- import { makePieData } from '../seriesUtils'
23
- import { makeD3Arc } from '../../utils/d3Utils'
24
- import { getDatumColor, getClassName } from '../../utils/orbchartsUtils'
25
- import { seriesCenterSelectionObservable } from '../seriesObservables'
26
-
27
- interface RenderDatum {
28
- pieDatum: PieDatum
29
- arcIndex: number
30
- arcLabel: string
31
- x: number
32
- y: number
33
- mouseoverX: number
34
- mouseoverY: number
35
- }
36
-
37
- const pluginName = 'PieLabels'
38
- const textClassName = getClassName(pluginName, 'text')
39
-
40
- function makeRenderData (pieData: PieDatum[], arc: d3.Arc<any, d3.DefaultArcObject>, mouseoverArc: d3.Arc<any, d3.DefaultArcObject>, centroid: number): RenderDatum[] {
41
- return pieData
42
- .map((d, i) => {
43
- const [_x, _y] = arc!.centroid(d as any)
44
- const [_mouseoverX, _mouseoverY] = mouseoverArc!.centroid(d as any)
45
- return {
46
- pieDatum: d,
47
- arcIndex: i,
48
- arcLabel: d.data.label,
49
- x: _x * centroid!,
50
- y: _y * centroid!,
51
- mouseoverX: _mouseoverX * centroid!,
52
- mouseoverY: _mouseoverY * centroid!
53
- }
54
- })
55
- .filter(d => d.pieDatum.data.visible)
56
- }
57
-
58
- // 繪製圓餅圖
59
- function renderLabel (selection: d3.Selection<SVGGElement, undefined, any, any>, data: RenderDatum[], pluginParams: PieLabelsParams, fullChartParams: ChartParams) {
60
- // console.log(data)
61
- // let update = this.gSelection.selectAll('g').data(pieData)
62
- let update: d3.Selection<SVGPathElement, RenderDatum, any, any> = selection
63
- .selectAll<SVGPathElement, RenderDatum>('text')
64
- .data(data, d => d.pieDatum.id)
65
- let enter = update.enter()
66
- .append<SVGPathElement>('text')
67
- .classed(textClassName, true)
68
- let exit = update.exit()
69
-
70
- enter
71
- .append('text')
72
-
73
- const labelSelection = update.merge(enter)
74
- labelSelection
75
- .attr('font-weight', 'bold')
76
- .attr('text-anchor', 'middle')
77
- .style('dominant-baseline', 'middle')
78
- // .style('pointer-events', 'none')
79
- .style('cursor', d => fullChartParams.highlightTarget && fullChartParams.highlightTarget != 'none'
80
- ? 'pointer'
81
- : 'none')
82
- // .text((d, i) => d.arcLabel)
83
- .text(d => pluginParams.labelFn(d.pieDatum.data))
84
- .attr('font-size', fullChartParams.styles.textSize)
85
- .attr('fill', (d, i) => getDatumColor({ datum: d.pieDatum.data, colorType: pluginParams.labelColorType, fullChartParams }))
86
- .transition()
87
- .attr('transform', (d) => {
88
- // console.log('transform', d)
89
- return 'translate(' + d.x + ',' + d.y + ')'
90
- })
91
- // .on('end', () => initHighlight({ labelSelection, data, fullChartParams }))
92
- exit.remove()
93
-
94
- // 如無新增資料則不用等動畫
95
- // if (enter.size() == 0) {
96
- // this.initHighlight()
97
- // }
98
-
99
- return labelSelection
100
- }
101
-
102
- // function initHighlight ({ labelSelection, data, fullChartParams }: {
103
- // labelSelection: (d3.Selection<SVGPathElement, RenderDatum, any, any>)
104
- // data: RenderDatum[]
105
- // fullChartParams: ChartParams
106
- // }) {
107
- // removeHighlight({ labelSelection })
108
- // // if (fullParams.highlightSeriesId || fullParams.highlightDatumId) {
109
- // highlight({
110
- // labelSelection,
111
- // data,
112
- // id: fullChartParams.highlightDefault,
113
- // label: fullChartParams.highlightDefault,
114
- // fullChartParams
115
- // })
116
- // // }
117
- // }
118
-
119
- function highlight ({ labelSelection, ids, fullChartParams }: {
120
- labelSelection: (d3.Selection<SVGPathElement, RenderDatum, any, any>)
121
- ids: string[]
122
- fullChartParams: ChartParams
123
- }) {
124
- labelSelection.interrupt('highlight')
125
-
126
- if (!ids.length) {
127
- labelSelection
128
- .transition()
129
- .duration(200)
130
- .attr('transform', (d) => {
131
- return 'translate(' + d.x + ',' + d.y + ')'
132
- })
133
- .style('opacity', 1)
134
- return
135
- }
136
-
137
- labelSelection.each((d, i, n) => {
138
- const segment = d3.select<SVGPathElement, RenderDatum>(n[i])
139
-
140
- if (ids.includes(d.pieDatum.id)) {
141
- segment
142
- .style('opacity', 1)
143
- .transition()
144
- .duration(200)
145
- .attr('transform', (d) => {
146
- return 'translate(' + d.mouseoverX + ',' + d.mouseoverY + ')'
147
- })
148
- } else {
149
- segment
150
- .style('opacity', fullChartParams.styles.unhighlightedOpacity)
151
- .transition()
152
- .duration(200)
153
- .attr('transform', (d) => {
154
- return 'translate(' + d.x + ',' + d.y + ')'
155
- })
156
- }
157
- })
158
- }
159
-
160
-
161
- function createEachPieLabel (pluginName: string, context: {
162
- containerSelection: d3.Selection<SVGGElement, any, any, unknown>
163
- // computedData$: Observable<ComputedDatumSeries[][]>
164
- containerVisibleComputedLayoutData$: Observable<ComputedDatumSeries[]>
165
- // SeriesDataMap$: Observable<Map<string, ComputedDatumSeries[]>>
166
- fullParams$: Observable<PieLabelsParams>
167
- fullChartParams$: Observable<ChartParams>
168
- seriesHighlight$: Observable<ComputedDatumSeries[]>
169
- seriesContainerPosition$: Observable<SeriesContainerPosition>
170
- event$: Subject<EventSeries>
171
- }) {
172
- const destroy$ = new Subject()
173
-
174
- // const graphicSelection: d3.Selection<SVGGElement, any, any, any> = selection.append('g')
175
- let labelSelection$: Subject<d3.Selection<SVGPathElement, RenderDatum, any, any>> = new Subject()
176
- let renderData: RenderDatum[] = []
177
-
178
- const shorterSideWith$ = context.seriesContainerPosition$.pipe(
179
- takeUntil(destroy$),
180
- map(d => d.width < d.height ? d.width : d.height),
181
- distinctUntilChanged()
182
- )
183
-
184
- combineLatest({
185
- shorterSideWith: shorterSideWith$,
186
- containerVisibleComputedLayoutData: context.containerVisibleComputedLayoutData$,
187
- fullParams: context.fullParams$,
188
- fullChartParams: context.fullChartParams$
189
- }).pipe(
190
- takeUntil(destroy$),
191
- switchMap(async (d) => d),
192
- ).subscribe(data => {
193
-
194
- // const shorterSideWith = data.layout.width < data.layout.height ? data.layout.width : data.layout.height
195
-
196
- // 弧產生器 (d3.arc())
197
- const arc = makeD3Arc({
198
- axisWidth: data.shorterSideWith,
199
- innerRadius: 0,
200
- outerRadius: data.fullParams.outerRadius,
201
- padAngle: 0,
202
- cornerRadius: 0
203
- })
204
-
205
- const arcMouseover = makeD3Arc({
206
- axisWidth: data.shorterSideWith,
207
- innerRadius: 0,
208
- outerRadius: data.fullParams.outerRadiusWhileHighlight, // 外半徑變化
209
- padAngle: 0,
210
- cornerRadius: 0
211
- })
212
-
213
- const pieData = makePieData({
214
- data: data.containerVisibleComputedLayoutData,
215
- startAngle: data.fullParams.startAngle,
216
- endAngle: data.fullParams.endAngle
217
- })
218
-
219
- renderData = makeRenderData(pieData, arc, arcMouseover, data.fullParams.labelCentroid)
220
-
221
- const labelSelection = renderLabel(context.containerSelection, renderData, data.fullParams, data.fullChartParams)
222
-
223
- labelSelection$.next(labelSelection)
224
-
225
- })
226
-
227
- combineLatest({
228
- labelSelection: labelSelection$,
229
- highlight: context.seriesHighlight$.pipe(
230
- map(data => data.map(d => d.id))
231
- ),
232
- fullChartParams: context.fullChartParams$,
233
- }).pipe(
234
- takeUntil(destroy$),
235
- switchMap(async d => d)
236
- ).subscribe(data => {
237
- highlight({
238
- labelSelection: data.labelSelection,
239
- ids: data.highlight,
240
- fullChartParams: data.fullChartParams,
241
- })
242
- })
243
-
244
- return () => {
245
- destroy$.next(undefined)
246
- }
247
- }
248
-
249
-
250
- export const PieLabels = defineSeriesPlugin(pluginName, DEFAULT_PIE_LABELS_PARAMS)(({ selection, observer, subject }) => {
251
-
252
- const destroy$ = new Subject()
253
-
254
- const { seriesCenterSelection$ } = seriesCenterSelectionObservable({
255
- selection: selection,
256
- pluginName,
257
- separateSeries$: observer.separateSeries$,
258
- seriesLabels$: observer.seriesLabels$,
259
- seriesContainerPosition$: observer.seriesContainerPosition$
260
- })
261
-
262
- const unsubscribeFnArr: (() => void)[] = []
263
-
264
- seriesCenterSelection$
265
- .pipe(
266
- takeUntil(destroy$)
267
- )
268
- .subscribe(seriesCenterSelection => {
269
- // 每次重新計算時,清除之前的訂閱
270
- unsubscribeFnArr.forEach(fn => fn())
271
-
272
- seriesCenterSelection.each((d, containerIndex, g) => {
273
-
274
- const containerSelection = d3.select(g[containerIndex])
275
-
276
- const containerVisibleComputedLayoutData$ = observer.visibleComputedLayoutData$.pipe(
277
- takeUntil(destroy$),
278
- map(data => data[containerIndex] ?? data[0])
279
- )
280
-
281
- const containerPosition$ = observer.seriesContainerPosition$.pipe(
282
- takeUntil(destroy$),
283
- map(data => data[containerIndex] ?? data[0])
284
- )
285
-
286
- unsubscribeFnArr[containerIndex] = createEachPieLabel(pluginName, {
287
- containerSelection: containerSelection,
288
- // computedData$: observer.computedData$,
289
- containerVisibleComputedLayoutData$: containerVisibleComputedLayoutData$,
290
- // SeriesDataMap$: observer.SeriesDataMap$,
291
- fullParams$: observer.fullParams$,
292
- fullChartParams$: observer.fullChartParams$,
293
- seriesHighlight$: observer.seriesHighlight$,
294
- seriesContainerPosition$: containerPosition$,
295
- event$: subject.event$,
296
- })
297
-
298
- })
299
- })
300
-
301
- return () => {
302
- destroy$.next(undefined)
303
- }
304
- })
1
+ import * as d3 from 'd3'
2
+ import {
3
+ combineLatest,
4
+ switchMap,
5
+ first,
6
+ map,
7
+ takeUntil,
8
+ Observable,
9
+ distinctUntilChanged,
10
+ Subject,
11
+ BehaviorSubject } from 'rxjs'
12
+ import {
13
+ defineSeriesPlugin } from '@orbcharts/core'
14
+ import type {
15
+ ComputedDatumSeries,
16
+ SeriesContainerPosition,
17
+ EventSeries,
18
+ ChartParams } from '@orbcharts/core'
19
+ import type { PieLabelsParams } from '../types'
20
+ import type { PieDatum } from '../seriesUtils'
21
+ import { DEFAULT_PIE_LABELS_PARAMS } from '../defaults'
22
+ import { makePieData } from '../seriesUtils'
23
+ import { makeD3Arc } from '../../utils/d3Utils'
24
+ import { getDatumColor, getClassName } from '../../utils/orbchartsUtils'
25
+ import { seriesCenterSelectionObservable } from '../seriesObservables'
26
+
27
+ interface RenderDatum {
28
+ pieDatum: PieDatum
29
+ arcIndex: number
30
+ arcLabel: string
31
+ x: number
32
+ y: number
33
+ mouseoverX: number
34
+ mouseoverY: number
35
+ }
36
+
37
+ const pluginName = 'PieLabels'
38
+ const textClassName = getClassName(pluginName, 'text')
39
+
40
+ function makeRenderData (pieData: PieDatum[], arc: d3.Arc<any, d3.DefaultArcObject>, mouseoverArc: d3.Arc<any, d3.DefaultArcObject>, centroid: number): RenderDatum[] {
41
+ return pieData
42
+ .map((d, i) => {
43
+ const [_x, _y] = arc!.centroid(d as any)
44
+ const [_mouseoverX, _mouseoverY] = mouseoverArc!.centroid(d as any)
45
+ return {
46
+ pieDatum: d,
47
+ arcIndex: i,
48
+ arcLabel: d.data.label,
49
+ x: _x * centroid!,
50
+ y: _y * centroid!,
51
+ mouseoverX: _mouseoverX * centroid!,
52
+ mouseoverY: _mouseoverY * centroid!
53
+ }
54
+ })
55
+ .filter(d => d.pieDatum.data.visible)
56
+ }
57
+
58
+ // 繪製圓餅圖
59
+ function renderLabel (selection: d3.Selection<SVGGElement, undefined, any, any>, data: RenderDatum[], pluginParams: PieLabelsParams, fullChartParams: ChartParams) {
60
+ // console.log(data)
61
+ // let update = this.gSelection.selectAll('g').data(pieData)
62
+ let update: d3.Selection<SVGPathElement, RenderDatum, any, any> = selection
63
+ .selectAll<SVGPathElement, RenderDatum>('text')
64
+ .data(data, d => d.pieDatum.id)
65
+ let enter = update.enter()
66
+ .append<SVGPathElement>('text')
67
+ .classed(textClassName, true)
68
+ let exit = update.exit()
69
+
70
+ enter
71
+ .append('text')
72
+
73
+ const labelSelection = update.merge(enter)
74
+ labelSelection
75
+ .attr('font-weight', 'bold')
76
+ .attr('text-anchor', 'middle')
77
+ .style('dominant-baseline', 'middle')
78
+ // .style('pointer-events', 'none')
79
+ .style('cursor', d => fullChartParams.highlightTarget && fullChartParams.highlightTarget != 'none'
80
+ ? 'pointer'
81
+ : 'none')
82
+ // .text((d, i) => d.arcLabel)
83
+ .text(d => pluginParams.labelFn(d.pieDatum.data))
84
+ .attr('font-size', fullChartParams.styles.textSize)
85
+ .attr('fill', (d, i) => getDatumColor({ datum: d.pieDatum.data, colorType: pluginParams.labelColorType, fullChartParams }))
86
+ .transition()
87
+ .attr('transform', (d) => {
88
+ // console.log('transform', d)
89
+ return 'translate(' + d.x + ',' + d.y + ')'
90
+ })
91
+ // .on('end', () => initHighlight({ labelSelection, data, fullChartParams }))
92
+ exit.remove()
93
+
94
+ // 如無新增資料則不用等動畫
95
+ // if (enter.size() == 0) {
96
+ // this.initHighlight()
97
+ // }
98
+
99
+ return labelSelection
100
+ }
101
+
102
+ // function initHighlight ({ labelSelection, data, fullChartParams }: {
103
+ // labelSelection: (d3.Selection<SVGPathElement, RenderDatum, any, any>)
104
+ // data: RenderDatum[]
105
+ // fullChartParams: ChartParams
106
+ // }) {
107
+ // removeHighlight({ labelSelection })
108
+ // // if (fullParams.highlightSeriesId || fullParams.highlightDatumId) {
109
+ // highlight({
110
+ // labelSelection,
111
+ // data,
112
+ // id: fullChartParams.highlightDefault,
113
+ // label: fullChartParams.highlightDefault,
114
+ // fullChartParams
115
+ // })
116
+ // // }
117
+ // }
118
+
119
+ function highlight ({ labelSelection, ids, fullChartParams }: {
120
+ labelSelection: (d3.Selection<SVGPathElement, RenderDatum, any, any>)
121
+ ids: string[]
122
+ fullChartParams: ChartParams
123
+ }) {
124
+ labelSelection.interrupt('highlight')
125
+
126
+ if (!ids.length) {
127
+ labelSelection
128
+ .transition()
129
+ .duration(200)
130
+ .attr('transform', (d) => {
131
+ return 'translate(' + d.x + ',' + d.y + ')'
132
+ })
133
+ .style('opacity', 1)
134
+ return
135
+ }
136
+
137
+ labelSelection.each((d, i, n) => {
138
+ const segment = d3.select<SVGPathElement, RenderDatum>(n[i])
139
+
140
+ if (ids.includes(d.pieDatum.id)) {
141
+ segment
142
+ .style('opacity', 1)
143
+ .transition()
144
+ .duration(200)
145
+ .attr('transform', (d) => {
146
+ return 'translate(' + d.mouseoverX + ',' + d.mouseoverY + ')'
147
+ })
148
+ } else {
149
+ segment
150
+ .style('opacity', fullChartParams.styles.unhighlightedOpacity)
151
+ .transition()
152
+ .duration(200)
153
+ .attr('transform', (d) => {
154
+ return 'translate(' + d.x + ',' + d.y + ')'
155
+ })
156
+ }
157
+ })
158
+ }
159
+
160
+
161
+ function createEachPieLabel (pluginName: string, context: {
162
+ containerSelection: d3.Selection<SVGGElement, any, any, unknown>
163
+ // computedData$: Observable<ComputedDatumSeries[][]>
164
+ containerVisibleComputedLayoutData$: Observable<ComputedDatumSeries[]>
165
+ // SeriesDataMap$: Observable<Map<string, ComputedDatumSeries[]>>
166
+ fullParams$: Observable<PieLabelsParams>
167
+ fullChartParams$: Observable<ChartParams>
168
+ seriesHighlight$: Observable<ComputedDatumSeries[]>
169
+ seriesContainerPosition$: Observable<SeriesContainerPosition>
170
+ event$: Subject<EventSeries>
171
+ }) {
172
+ const destroy$ = new Subject()
173
+
174
+ // const graphicSelection: d3.Selection<SVGGElement, any, any, any> = selection.append('g')
175
+ let labelSelection$: Subject<d3.Selection<SVGPathElement, RenderDatum, any, any>> = new Subject()
176
+ let renderData: RenderDatum[] = []
177
+
178
+ const shorterSideWith$ = context.seriesContainerPosition$.pipe(
179
+ takeUntil(destroy$),
180
+ map(d => d.width < d.height ? d.width : d.height),
181
+ distinctUntilChanged()
182
+ )
183
+
184
+ combineLatest({
185
+ shorterSideWith: shorterSideWith$,
186
+ containerVisibleComputedLayoutData: context.containerVisibleComputedLayoutData$,
187
+ fullParams: context.fullParams$,
188
+ fullChartParams: context.fullChartParams$
189
+ }).pipe(
190
+ takeUntil(destroy$),
191
+ switchMap(async (d) => d),
192
+ ).subscribe(data => {
193
+
194
+ // const shorterSideWith = data.layout.width < data.layout.height ? data.layout.width : data.layout.height
195
+
196
+ // 弧產生器 (d3.arc())
197
+ const arc = makeD3Arc({
198
+ axisWidth: data.shorterSideWith,
199
+ innerRadius: 0,
200
+ outerRadius: data.fullParams.outerRadius,
201
+ padAngle: 0,
202
+ cornerRadius: 0
203
+ })
204
+
205
+ const arcMouseover = makeD3Arc({
206
+ axisWidth: data.shorterSideWith,
207
+ innerRadius: 0,
208
+ outerRadius: data.fullParams.outerRadiusWhileHighlight, // 外半徑變化
209
+ padAngle: 0,
210
+ cornerRadius: 0
211
+ })
212
+
213
+ const pieData = makePieData({
214
+ data: data.containerVisibleComputedLayoutData,
215
+ startAngle: data.fullParams.startAngle,
216
+ endAngle: data.fullParams.endAngle
217
+ })
218
+
219
+ renderData = makeRenderData(pieData, arc, arcMouseover, data.fullParams.labelCentroid)
220
+
221
+ const labelSelection = renderLabel(context.containerSelection, renderData, data.fullParams, data.fullChartParams)
222
+
223
+ labelSelection$.next(labelSelection)
224
+
225
+ })
226
+
227
+ combineLatest({
228
+ labelSelection: labelSelection$,
229
+ highlight: context.seriesHighlight$.pipe(
230
+ map(data => data.map(d => d.id))
231
+ ),
232
+ fullChartParams: context.fullChartParams$,
233
+ }).pipe(
234
+ takeUntil(destroy$),
235
+ switchMap(async d => d)
236
+ ).subscribe(data => {
237
+ highlight({
238
+ labelSelection: data.labelSelection,
239
+ ids: data.highlight,
240
+ fullChartParams: data.fullChartParams,
241
+ })
242
+ })
243
+
244
+ return () => {
245
+ destroy$.next(undefined)
246
+ }
247
+ }
248
+
249
+
250
+ export const PieLabels = defineSeriesPlugin(pluginName, DEFAULT_PIE_LABELS_PARAMS)(({ selection, observer, subject }) => {
251
+
252
+ const destroy$ = new Subject()
253
+
254
+ const { seriesCenterSelection$ } = seriesCenterSelectionObservable({
255
+ selection: selection,
256
+ pluginName,
257
+ separateSeries$: observer.separateSeries$,
258
+ seriesLabels$: observer.seriesLabels$,
259
+ seriesContainerPosition$: observer.seriesContainerPosition$
260
+ })
261
+
262
+ const unsubscribeFnArr: (() => void)[] = []
263
+
264
+ seriesCenterSelection$
265
+ .pipe(
266
+ takeUntil(destroy$)
267
+ )
268
+ .subscribe(seriesCenterSelection => {
269
+ // 每次重新計算時,清除之前的訂閱
270
+ unsubscribeFnArr.forEach(fn => fn())
271
+
272
+ seriesCenterSelection.each((d, containerIndex, g) => {
273
+
274
+ const containerSelection = d3.select(g[containerIndex])
275
+
276
+ const containerVisibleComputedLayoutData$ = observer.visibleComputedLayoutData$.pipe(
277
+ takeUntil(destroy$),
278
+ map(data => data[containerIndex] ?? data[0])
279
+ )
280
+
281
+ const containerPosition$ = observer.seriesContainerPosition$.pipe(
282
+ takeUntil(destroy$),
283
+ map(data => data[containerIndex] ?? data[0])
284
+ )
285
+
286
+ unsubscribeFnArr[containerIndex] = createEachPieLabel(pluginName, {
287
+ containerSelection: containerSelection,
288
+ // computedData$: observer.computedData$,
289
+ containerVisibleComputedLayoutData$: containerVisibleComputedLayoutData$,
290
+ // SeriesDataMap$: observer.SeriesDataMap$,
291
+ fullParams$: observer.fullParams$,
292
+ fullChartParams$: observer.fullChartParams$,
293
+ seriesHighlight$: observer.seriesHighlight$,
294
+ seriesContainerPosition$: containerPosition$,
295
+ event$: subject.event$,
296
+ })
297
+
298
+ })
299
+ })
300
+
301
+ return () => {
302
+ destroy$.next(undefined)
303
+ }
304
+ })