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

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