@orbcharts/plugin-basic 4.0.0-pre-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/LICENSE +201 -0
  2. package/dist/orbcharts-plugin-basic.es.js +25335 -0
  3. package/dist/orbcharts-plugin-basic.umd.js +341 -0
  4. package/dist/plugin-basic/src/baseLayers/BaseBars.d.ts +38 -0
  5. package/dist/plugin-basic/src/baseLayers/BaseBarsTriangle.d.ts +37 -0
  6. package/dist/plugin-basic/src/baseLayers/BaseCategoryAxis.d.ts +42 -0
  7. package/dist/plugin-basic/src/baseLayers/BaseDots.d.ts +38 -0
  8. package/dist/plugin-basic/src/baseLayers/BaseLegend.d.ts +31 -0
  9. package/dist/plugin-basic/src/baseLayers/BaseLineAreas.d.ts +36 -0
  10. package/dist/plugin-basic/src/baseLayers/BaseLines.d.ts +36 -0
  11. package/dist/plugin-basic/src/baseLayers/BaseStackedBars.d.ts +41 -0
  12. package/dist/plugin-basic/src/baseLayers/BaseTooltip.d.ts +47 -0
  13. package/dist/plugin-basic/src/baseLayers/BaseValueAxis.d.ts +38 -0
  14. package/dist/plugin-basic/src/baseLayers/BaseXAxis.d.ts +25 -0
  15. package/dist/plugin-basic/src/baseLayers/BaseXZoom.d.ts +22 -0
  16. package/dist/plugin-basic/src/baseLayers/BaseYAxis.d.ts +23 -0
  17. package/dist/plugin-basic/src/baseLayers/types.d.ts +171 -0
  18. package/dist/plugin-basic/src/const/layerIndex.d.ts +10 -0
  19. package/dist/plugin-basic/src/const/sharedPluginParams.d.ts +6 -0
  20. package/dist/plugin-basic/src/index.d.ts +2 -0
  21. package/dist/plugin-basic/src/plugins/CompositionPlot/CompositionPlot.d.ts +22 -0
  22. package/dist/plugin-basic/src/plugins/CompositionPlot/contextObservables.d.ts +40 -0
  23. package/dist/plugin-basic/src/plugins/CompositionPlot/defaults.d.ts +10 -0
  24. package/dist/plugin-basic/src/plugins/CompositionPlot/index.d.ts +3 -0
  25. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Bubbles.d.ts +16 -0
  26. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Indicator.d.ts +0 -0
  27. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Pie.d.ts +16 -0
  28. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/PieEventTexts.d.ts +16 -0
  29. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/PieLabels.d.ts +16 -0
  30. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Rose.d.ts +16 -0
  31. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/RoseLabels.d.ts +16 -0
  32. package/dist/plugin-basic/src/plugins/CompositionPlot/layers/Waffle.d.ts +0 -0
  33. package/dist/plugin-basic/src/plugins/CompositionPlot/types.d.ts +110 -0
  34. package/dist/plugin-basic/src/plugins/CompositionPlot/utils.d.ts +19 -0
  35. package/dist/plugin-basic/src/plugins/HierarchyPlot/HierarchyPlot.d.ts +22 -0
  36. package/dist/plugin-basic/src/plugins/HierarchyPlot/contextObservables.d.ts +16 -0
  37. package/dist/plugin-basic/src/plugins/HierarchyPlot/defaults.d.ts +4 -0
  38. package/dist/plugin-basic/src/plugins/HierarchyPlot/index.d.ts +3 -0
  39. package/dist/plugin-basic/src/plugins/HierarchyPlot/layers/TreeMap.d.ts +16 -0
  40. package/dist/plugin-basic/src/plugins/HierarchyPlot/types.d.ts +29 -0
  41. package/dist/plugin-basic/src/plugins/Legend/Legend.d.ts +22 -0
  42. package/dist/plugin-basic/src/plugins/Legend/contextObservables.d.ts +9 -0
  43. package/dist/plugin-basic/src/plugins/Legend/defaults.d.ts +4 -0
  44. package/dist/plugin-basic/src/plugins/Legend/index.d.ts +3 -0
  45. package/dist/plugin-basic/src/plugins/Legend/layers/Legend.d.ts +16 -0
  46. package/dist/plugin-basic/src/plugins/Legend/types.d.ts +31 -0
  47. package/dist/plugin-basic/src/plugins/Legend/utils.d.ts +19 -0
  48. package/dist/plugin-basic/src/plugins/NetworkPlot/NetworkPlot.d.ts +22 -0
  49. package/dist/plugin-basic/src/plugins/NetworkPlot/contextObservables.d.ts +19 -0
  50. package/dist/plugin-basic/src/plugins/NetworkPlot/defaults.d.ts +5 -0
  51. package/dist/plugin-basic/src/plugins/NetworkPlot/index.d.ts +3 -0
  52. package/dist/plugin-basic/src/plugins/NetworkPlot/layers/ForceDirected.d.ts +16 -0
  53. package/dist/plugin-basic/src/plugins/NetworkPlot/layers/ForceDirectedBubbles.d.ts +16 -0
  54. package/dist/plugin-basic/src/plugins/NetworkPlot/types.d.ts +117 -0
  55. package/dist/plugin-basic/src/plugins/ScatterPlot/ScatterPlot.d.ts +22 -0
  56. package/dist/plugin-basic/src/plugins/ScatterPlot/contextObservables.d.ts +140 -0
  57. package/dist/plugin-basic/src/plugins/ScatterPlot/defaults.d.ts +8 -0
  58. package/dist/plugin-basic/src/plugins/ScatterPlot/index.d.ts +3 -0
  59. package/dist/plugin-basic/src/plugins/ScatterPlot/layers/Scatter.d.ts +16 -0
  60. package/dist/plugin-basic/src/plugins/ScatterPlot/layers/ScatterBubbles.d.ts +16 -0
  61. package/dist/plugin-basic/src/plugins/ScatterPlot/layers/XYAux.d.ts +16 -0
  62. package/dist/plugin-basic/src/plugins/ScatterPlot/layers/XYAxes.d.ts +16 -0
  63. package/dist/plugin-basic/src/plugins/ScatterPlot/layers/XZoom.d.ts +16 -0
  64. package/dist/plugin-basic/src/plugins/ScatterPlot/types.d.ts +146 -0
  65. package/dist/plugin-basic/src/plugins/SeriesPlot/SeriesPlot.d.ts +22 -0
  66. package/dist/plugin-basic/src/plugins/SeriesPlot/contextObservables.d.ts +77 -0
  67. package/dist/plugin-basic/src/plugins/SeriesPlot/defaults.d.ts +15 -0
  68. package/dist/plugin-basic/src/plugins/SeriesPlot/index.d.ts +3 -0
  69. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/Bars.d.ts +16 -0
  70. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/BarsPN.d.ts +16 -0
  71. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/BarsTriangle.d.ts +16 -0
  72. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/CategoryAux.d.ts +16 -0
  73. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/CategoryAxis.d.ts +16 -0
  74. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/CategoryZoom.d.ts +16 -0
  75. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/Dots.d.ts +16 -0
  76. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/LineAreas.d.ts +16 -0
  77. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/Lines.d.ts +16 -0
  78. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/StackedBars.d.ts +16 -0
  79. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/StackedValueAxis.d.ts +16 -0
  80. package/dist/plugin-basic/src/plugins/SeriesPlot/layers/ValueAxis.d.ts +16 -0
  81. package/dist/plugin-basic/src/plugins/SeriesPlot/types.d.ts +140 -0
  82. package/dist/plugin-basic/src/plugins/Tooltip/Tooltip.d.ts +22 -0
  83. package/dist/plugin-basic/src/plugins/Tooltip/contextObservables.d.ts +9 -0
  84. package/dist/plugin-basic/src/plugins/Tooltip/defaults.d.ts +4 -0
  85. package/dist/plugin-basic/src/plugins/Tooltip/index.d.ts +3 -0
  86. package/dist/plugin-basic/src/plugins/Tooltip/layers/Tooltip.d.ts +16 -0
  87. package/dist/plugin-basic/src/plugins/Tooltip/types.d.ts +35 -0
  88. package/dist/plugin-basic/src/plugins/Tooltip/utils.d.ts +19 -0
  89. package/dist/plugin-basic/src/plugins/index.d.ts +7 -0
  90. package/dist/plugin-basic/src/types/BaseLayer.d.ts +3 -0
  91. package/dist/plugin-basic/src/types/Common.d.ts +14 -0
  92. package/dist/plugin-basic/src/types/ComputedData.d.ts +27 -0
  93. package/dist/plugin-basic/src/types/PluginParams.d.ts +66 -0
  94. package/dist/plugin-basic/src/types/index.d.ts +3 -0
  95. package/dist/plugin-basic/src/utils/commonUtils.d.ts +3 -0
  96. package/dist/plugin-basic/src/utils/d3Graphics.d.ts +24 -0
  97. package/dist/plugin-basic/src/utils/d3Scale.d.ts +28 -0
  98. package/dist/plugin-basic/src/utils/d3Utils.d.ts +14 -0
  99. package/dist/plugin-basic/src/utils/graphObservables.d.ts +0 -0
  100. package/dist/plugin-basic/src/utils/gridObservables.d.ts +51 -0
  101. package/dist/plugin-basic/src/utils/multivariateObservables.d.ts +74 -0
  102. package/dist/plugin-basic/src/utils/observables.d.ts +34 -0
  103. package/dist/plugin-basic/src/utils/orbchartsUtils.d.ts +26 -0
  104. package/dist/plugin-basic/src/utils/seriesObservables.d.ts +22 -0
  105. package/dist/plugin-basic/vite.config.d.ts +2 -0
  106. package/dist/src/index.d.ts +1 -0
  107. package/package.json +62 -0
  108. package/src/baseLayers/BaseBars.ts +783 -0
  109. package/src/baseLayers/BaseBarsTriangle.ts +692 -0
  110. package/src/baseLayers/BaseCategoryAxis.ts +708 -0
  111. package/src/baseLayers/BaseDots.ts +495 -0
  112. package/src/baseLayers/BaseLegend.ts +684 -0
  113. package/src/baseLayers/BaseLineAreas.ts +644 -0
  114. package/src/baseLayers/BaseLines.ts +721 -0
  115. package/src/baseLayers/BaseStackedBars.ts +818 -0
  116. package/src/baseLayers/BaseTooltip.ts +435 -0
  117. package/src/baseLayers/BaseValueAxis.ts +612 -0
  118. package/src/baseLayers/BaseXAxis.ts +412 -0
  119. package/src/baseLayers/BaseXZoom.ts +250 -0
  120. package/src/baseLayers/BaseYAxis.ts +371 -0
  121. package/src/baseLayers/types.ts +174 -0
  122. package/src/const/layerIndex.ts +36 -0
  123. package/src/const/sharedPluginParams.ts +29 -0
  124. package/src/index.ts +3 -0
  125. package/src/plugins/CompositionPlot/CompositionPlot.ts +308 -0
  126. package/src/plugins/CompositionPlot/contextObservables.ts +251 -0
  127. package/src/plugins/CompositionPlot/defaults.ts +162 -0
  128. package/src/plugins/CompositionPlot/index.ts +3 -0
  129. package/src/plugins/CompositionPlot/layers/Bubbles.ts +808 -0
  130. package/src/plugins/CompositionPlot/layers/Indicator.ts +0 -0
  131. package/src/plugins/CompositionPlot/layers/Pie.ts +776 -0
  132. package/src/plugins/CompositionPlot/layers/PieEventTexts.ts +326 -0
  133. package/src/plugins/CompositionPlot/layers/PieLabels.ts +651 -0
  134. package/src/plugins/CompositionPlot/layers/Rose.ts +546 -0
  135. package/src/plugins/CompositionPlot/layers/RoseLabels.ts +616 -0
  136. package/src/plugins/CompositionPlot/layers/Waffle.ts +0 -0
  137. package/src/plugins/CompositionPlot/types.ts +129 -0
  138. package/src/plugins/CompositionPlot/utils.ts +53 -0
  139. package/src/plugins/HierarchyPlot/HierarchyPlot.ts +190 -0
  140. package/src/plugins/HierarchyPlot/contextObservables.ts +136 -0
  141. package/src/plugins/HierarchyPlot/defaults.ts +31 -0
  142. package/src/plugins/HierarchyPlot/index.ts +3 -0
  143. package/src/plugins/HierarchyPlot/layers/TreeMap.ts +371 -0
  144. package/src/plugins/HierarchyPlot/types.ts +36 -0
  145. package/src/plugins/Legend/Legend.ts +151 -0
  146. package/src/plugins/Legend/contextObservables.ts +55 -0
  147. package/src/plugins/Legend/defaults.ts +37 -0
  148. package/src/plugins/Legend/index.ts +3 -0
  149. package/src/plugins/Legend/layers/Legend.ts +114 -0
  150. package/src/plugins/Legend/types.ts +45 -0
  151. package/src/plugins/Legend/utils.ts +53 -0
  152. package/src/plugins/NetworkPlot/NetworkPlot.ts +228 -0
  153. package/src/plugins/NetworkPlot/contextObservables.ts +123 -0
  154. package/src/plugins/NetworkPlot/defaults.ts +147 -0
  155. package/src/plugins/NetworkPlot/index.ts +3 -0
  156. package/src/plugins/NetworkPlot/layers/ForceDirected.ts +1048 -0
  157. package/src/plugins/NetworkPlot/layers/ForceDirectedBubbles.ts +1318 -0
  158. package/src/plugins/NetworkPlot/types.ts +146 -0
  159. package/src/plugins/ScatterPlot/ScatterPlot.ts +569 -0
  160. package/src/plugins/ScatterPlot/contextObservables.ts +901 -0
  161. package/src/plugins/ScatterPlot/defaults.ts +212 -0
  162. package/src/plugins/ScatterPlot/index.ts +3 -0
  163. package/src/plugins/ScatterPlot/layers/Scatter.ts +518 -0
  164. package/src/plugins/ScatterPlot/layers/ScatterBubbles.ts +670 -0
  165. package/src/plugins/ScatterPlot/layers/XYAux.ts +686 -0
  166. package/src/plugins/ScatterPlot/layers/XYAxes.ts +205 -0
  167. package/src/plugins/ScatterPlot/layers/XZoom.ts +48 -0
  168. package/src/plugins/ScatterPlot/types.ts +179 -0
  169. package/src/plugins/SeriesPlot/SeriesPlot.ts +494 -0
  170. package/src/plugins/SeriesPlot/contextObservables.ts +726 -0
  171. package/src/plugins/SeriesPlot/defaults.ts +142 -0
  172. package/src/plugins/SeriesPlot/index.ts +3 -0
  173. package/src/plugins/SeriesPlot/layers/Bars.ts +84 -0
  174. package/src/plugins/SeriesPlot/layers/BarsPN.ts +85 -0
  175. package/src/plugins/SeriesPlot/layers/BarsTriangle.ts +89 -0
  176. package/src/plugins/SeriesPlot/layers/CategoryAux.ts +1131 -0
  177. package/src/plugins/SeriesPlot/layers/CategoryAxis.ts +92 -0
  178. package/src/plugins/SeriesPlot/layers/CategoryZoom.ts +233 -0
  179. package/src/plugins/SeriesPlot/layers/Dots.ts +91 -0
  180. package/src/plugins/SeriesPlot/layers/LineAreas.ts +82 -0
  181. package/src/plugins/SeriesPlot/layers/Lines.ts +75 -0
  182. package/src/plugins/SeriesPlot/layers/StackedBars.ts +85 -0
  183. package/src/plugins/SeriesPlot/layers/StackedValueAxis.ts +111 -0
  184. package/src/plugins/SeriesPlot/layers/ValueAxis.ts +111 -0
  185. package/src/plugins/SeriesPlot/types.ts +201 -0
  186. package/src/plugins/Tooltip/Tooltip.ts +159 -0
  187. package/src/plugins/Tooltip/contextObservables.ts +55 -0
  188. package/src/plugins/Tooltip/defaults.ts +458 -0
  189. package/src/plugins/Tooltip/index.ts +3 -0
  190. package/src/plugins/Tooltip/layers/Tooltip.ts +90 -0
  191. package/src/plugins/Tooltip/types.ts +55 -0
  192. package/src/plugins/Tooltip/utils.ts +53 -0
  193. package/src/plugins/index.ts +8 -0
  194. package/src/types/BaseLayer.ts +3 -0
  195. package/src/types/Common.ts +20 -0
  196. package/src/types/ComputedData.ts +55 -0
  197. package/src/types/PluginParams.ts +81 -0
  198. package/src/types/index.ts +3 -0
  199. package/src/utils/commonUtils.ts +31 -0
  200. package/src/utils/d3Graphics.ts +177 -0
  201. package/src/utils/d3Scale.ts +198 -0
  202. package/src/utils/d3Utils.ts +92 -0
  203. package/src/utils/graphObservables.ts +0 -0
  204. package/src/utils/gridObservables.ts +637 -0
  205. package/src/utils/multivariateObservables.ts +790 -0
  206. package/src/utils/observables.ts +357 -0
  207. package/src/utils/orbchartsUtils.ts +335 -0
  208. package/src/utils/seriesObservables.ts +172 -0
@@ -0,0 +1,546 @@
1
+ import * as d3 from 'd3'
2
+ import {
3
+ combineLatest,
4
+ map,
5
+ filter,
6
+ switchMap,
7
+ takeUntil,
8
+ distinctUntilChanged,
9
+ shareReplay,
10
+ debounceTime,
11
+ Observable,
12
+ Subject,
13
+ BehaviorSubject} from 'rxjs'
14
+ import type { Theme, EventData } from '@orbcharts/core'
15
+ import type { CompositionPlotExtendContext, CompositionPlotPluginParams, RoseParams } from "../types"
16
+ import type { PieDatum } from '../utils'
17
+ import { defineSVGLayer } from '@orbcharts/core'
18
+ import { validateObject } from '@orbcharts/core'
19
+ import { DEFAULT_ROSE_PARAMS } from "../defaults"
20
+ import { seriesCenterSelectionObservable } from "../../../utils/seriesObservables"
21
+ import { getDatumColor } from '../../../utils/orbchartsUtils'
22
+ import { createClassName } from '../../../utils/orbchartsUtils'
23
+ import { makeD3Arc } from '../../../utils/d3Utils'
24
+ import { makePieData } from '../utils'
25
+ import type { ComputedDatumSeries } from '../../../types/ComputedData'
26
+ import type { ContainerPosition } from '../../../types/PluginParams'
27
+ import { LAYER_INDEX_OF_GRAPHIC } from '../../../const/layerIndex'
28
+
29
+ interface RoseDatum extends PieDatum {
30
+ prevValue: number // 補間動畫用的(前次資料的value)
31
+ }
32
+
33
+ const pluginName = 'CompositionPlot'
34
+ const layerName = 'Rose'
35
+
36
+ const roseInnerRadius = 0
37
+ const roseStartAngle = 0
38
+ const roseEndAngle = Math.PI * 2
39
+
40
+
41
+ function makeTweenArcFn ({ cornerRadius, outerRadius, axisWidth, maxValue, arcScaleType, layerParams }: {
42
+ // interpolateRadius: (t: number) => number
43
+ outerRadius: number
44
+ cornerRadius: number
45
+ axisWidth: number
46
+ maxValue: number
47
+ arcScaleType: 'radius' | 'area'
48
+ layerParams: RoseParams
49
+ }): (d: RoseDatum) => (t: number) => string {
50
+
51
+ const outerRadiusWidth = (axisWidth / 2) * outerRadius
52
+
53
+ // const arcScale = d3.scaleLinear()
54
+ // .domain([0, maxValue])
55
+ // .range([0, outerRadiusWidth])
56
+
57
+ const exponent = arcScaleType === 'area'
58
+ ? 0.5 // 比例映射面積(0.5為取平方根)
59
+ : 1 // 比例映射半徑
60
+
61
+ const arcScale = d3.scalePow()
62
+ .domain([0, maxValue])
63
+ .range([0, outerRadiusWidth])
64
+ .exponent(exponent)
65
+
66
+ return (d: RoseDatum) => {
67
+ const prevEachOuterRadius = arcScale(d.prevValue)!
68
+ const eachOuterRadius = arcScale(d.value)!
69
+
70
+ const interpolateRadius = d3.interpolate(prevEachOuterRadius, eachOuterRadius)
71
+
72
+ return (t: number) => {
73
+
74
+ const outerRadius = interpolateRadius(t)
75
+
76
+ const arc = d3.arc()
77
+ .innerRadius(0)
78
+ .outerRadius(outerRadius)
79
+ .padAngle(layerParams.padAngle)
80
+ .padRadius(outerRadius)
81
+ .cornerRadius(cornerRadius)
82
+
83
+ return arc(d as any)
84
+ }
85
+ }
86
+ }
87
+
88
+ // function renderPie ({ selection, data, tweenArc, transitionDuration, pathClassName }: {
89
+ // selection: d3.Selection<SVGGElement, unknown, any, unknown>
90
+ // data: RoseDatum[]
91
+ // // arc: d3.Arc<any, d3.DefaultArcObject>
92
+ // tweenArc: (d: RoseDatum) => (t: number) => string
93
+ // transitionDuration: number
94
+ // pathClassName: string
95
+ // }): d3.Selection<SVGPathElement, RoseDatum, any, any> {
96
+ // // console.log('data', data)
97
+ // const pathSelection: d3.Selection<SVGPathElement, RoseDatum, any, any> = selection
98
+ // .selectAll<SVGPathElement, RoseDatum>('path')
99
+ // .data(data, d => d.id)
100
+ // .join('path')
101
+ // .classed(pathClassName, true)
102
+ // .style('cursor', 'pointer')
103
+ // .attr('fill', (d, i) => d.data.color)
104
+ // pathSelection
105
+ // .transition('graphicMove')
106
+ // .duration(transitionDuration)
107
+ // .attrTween('d', tweenArc)
108
+
109
+ // return pathSelection
110
+ // }
111
+
112
+ function highlight ({ pathSelection, ids, layerParams, pluginParams, tweenArc }: {
113
+ pathSelection: d3.Selection<SVGPathElement, RoseDatum, any, any>
114
+ ids: string[]
115
+ layerParams: RoseParams
116
+ pluginParams: CompositionPlotPluginParams
117
+ // arc: d3.Arc<any, d3.DefaultArcObject>
118
+ tweenArc: (d: RoseDatum) => (t: number) => string
119
+ }) {
120
+ pathSelection.interrupt('highlight')
121
+
122
+ if (!ids.length) {
123
+ // 取消放大
124
+ pathSelection
125
+ .transition('highlight')
126
+ .style('opacity', 1)
127
+ .attr('d', (d: RoseDatum) => {
128
+ return tweenArc(d)(1)
129
+ })
130
+ return
131
+ }
132
+
133
+ pathSelection.each((d, i, n) => {
134
+ const segment = d3.select(n[i])
135
+
136
+ if (ids.includes(d.data.id)) {
137
+ segment
138
+ .style('opacity', 1)
139
+ .transition('highlight')
140
+ .ease(d3.easeElastic)
141
+ .duration(500)
142
+ // .attr('d', (d: any) => {
143
+ // return arc!({
144
+ // ...d,
145
+ // startAngle: d.startAngle - 0.5,
146
+ // endAngle: d.endAngle + 0.5
147
+ // })
148
+ // })
149
+ .attr('d', (d: RoseDatum) => {
150
+ return tweenArc({
151
+ ...d,
152
+ startAngle: d.startAngle - layerParams.angleIncreaseWhileHighlight,
153
+ endAngle: d.endAngle + layerParams.angleIncreaseWhileHighlight
154
+ })(1)
155
+ })
156
+ // .on('interrupt', () => {
157
+ // // this.pathSelection!.select('path').attr('d', (d) => {
158
+ // // return this.arc!(d as any)
159
+ // // })
160
+ // this.initHighlight()
161
+ // })
162
+ } else {
163
+ // 取消放大
164
+ segment
165
+ .style('opacity', pluginParams.styles.unhighlightedOpacity)
166
+ .transition('highlight')
167
+ .attr('d', (d: RoseDatum) => {
168
+ return tweenArc(d)(1)
169
+ })
170
+ }
171
+ })
172
+ }
173
+
174
+ // 各別的pie
175
+ function createEachRose (pluginName: string, context: {
176
+ containerSelection: d3.Selection<SVGGElement, any, any, unknown>
177
+ computedData$: Observable<ComputedDatumSeries[][]>
178
+ // visibleComputedData$: Observable<ComputedDatumSeries[][]>
179
+ visibleComputedSortedData$: Observable<ComputedDatumSeries[][]>
180
+ containerVisibleComputedSortedData$: Observable<ComputedDatumSeries[]>
181
+ SeriesDataMap$: Observable<Map<string, ComputedDatumSeries[]>>
182
+ layerParams$: Observable<RoseParams>
183
+ pluginParams$: Observable<CompositionPlotPluginParams>
184
+ theme$: Observable<Theme>
185
+ seriesHighlight$: Observable<ComputedDatumSeries[]>
186
+ seriesContainerPosition$: Observable<ContainerPosition>
187
+ eventTrigger$: Subject<EventData>
188
+ }) {
189
+ const destroy$ = new Subject()
190
+
191
+ const pathClassName = createClassName(pluginName, layerName, 'path')
192
+
193
+ let lastPieData: RoseDatum[] = [] // 紀錄補間動畫前次的資料
194
+
195
+ const shorterSideWith$ = context.seriesContainerPosition$.pipe(
196
+ takeUntil(destroy$),
197
+ map(d => d.width < d.height ? d.width : d.height),
198
+ distinctUntilChanged()
199
+ )
200
+
201
+ const roseData$: Observable<RoseDatum[]> = combineLatest({
202
+ containerVisibleComputedSortedData: context.containerVisibleComputedSortedData$,
203
+ layerParams: context.layerParams$,
204
+ }).pipe(
205
+ takeUntil(destroy$),
206
+ switchMap(async (d) => d),
207
+ map(data => {
208
+ const eachAngle = roseEndAngle / data.containerVisibleComputedSortedData.length
209
+ return data.containerVisibleComputedSortedData.map((d, i) => {
210
+ return {
211
+ id: d.id,
212
+ data: d,
213
+ index: i,
214
+ value: d.value,
215
+ startAngle: eachAngle * i,
216
+ endAngle: eachAngle * (i + 1),
217
+ padAngle: data.layerParams.padAngle,
218
+ prevValue: (lastPieData[i] && lastPieData[i].id === d.id) ? lastPieData[i].value : 0
219
+ }
220
+ })
221
+ })
222
+ )
223
+
224
+ const highlightTarget$ = context.pluginParams$.pipe(
225
+ takeUntil(destroy$),
226
+ map(d => d.styles.highlightTarget),
227
+ distinctUntilChanged()
228
+ )
229
+
230
+ const maxValue$ = context.visibleComputedSortedData$.pipe(
231
+ map(data => Math.max(...data.flat().map(d => d.value))),
232
+ distinctUntilChanged()
233
+ )
234
+
235
+ // context.visibleComputedSortedData$.subscribe(data => {
236
+ // console.log('visibleComputedSortedData$', data)
237
+ // })
238
+
239
+ const tweenArc$ = combineLatest({
240
+ layerParams: context.layerParams$,
241
+ axisWidth: shorterSideWith$,
242
+ maxValue: maxValue$
243
+ }).pipe(
244
+ takeUntil(destroy$),
245
+ debounceTime(0),
246
+ map((data) => {
247
+ return makeTweenArcFn({
248
+ cornerRadius: data.layerParams.cornerRadius,
249
+ outerRadius: data.layerParams.outerRadius,
250
+ axisWidth: data.axisWidth,
251
+ maxValue: data.maxValue,
252
+ arcScaleType: data.layerParams.arcScaleType,
253
+ layerParams: data.layerParams
254
+ })
255
+ })
256
+ )
257
+
258
+ const transitionDuration$ = context.pluginParams$.pipe(
259
+ takeUntil(destroy$),
260
+ map(d => d.styles.transitionDuration),
261
+ distinctUntilChanged()
262
+ )
263
+
264
+ // 是否在transition中
265
+ const isTransitionMoving$ = new BehaviorSubject<boolean>(false)
266
+
267
+ const pathSelection$ = new Observable<d3.Selection<SVGPathElement, RoseDatum, any, any>>(subscriber => {
268
+ combineLatest({
269
+ roseData: roseData$,
270
+ tweenArc: tweenArc$,
271
+ transitionDuration: transitionDuration$,
272
+ layerParams: context.layerParams$,
273
+ pluginParams: context.pluginParams$,
274
+ theme: context.theme$
275
+ }).pipe(
276
+ takeUntil(destroy$),
277
+ debounceTime(0)
278
+ ).subscribe(data => {
279
+ const roseData = data.roseData.map((d, i) => {
280
+ d.prevValue = (lastPieData[i] && lastPieData[i].id === d.id) ? lastPieData[i].value : 0
281
+ return d
282
+ })
283
+
284
+ isTransitionMoving$.next(true)
285
+
286
+ const pathSelection: d3.Selection<SVGPathElement, RoseDatum, any, any> = context.containerSelection
287
+ .selectAll<SVGPathElement, RoseDatum>('path')
288
+ .data(roseData, d => d.id)
289
+ .join('path')
290
+ .classed(pathClassName, true)
291
+ .style('cursor', 'pointer')
292
+ .attr('fill', (d, i) => d.data.color)
293
+ .attr('stroke', (d, i) => getDatumColor({
294
+ datum: d.data,
295
+ colorType: data.layerParams.strokeColorType,
296
+ theme: data.theme
297
+ }))
298
+ .attr('stroke-width', data.layerParams.strokeWidth)
299
+ pathSelection.interrupt('graphicMove')
300
+ pathSelection
301
+ .transition('graphicMove')
302
+ .duration(data.transitionDuration)
303
+ .attrTween('d', data.tweenArc)
304
+ .on('end', () => {
305
+ subscriber.next(pathSelection)
306
+
307
+ isTransitionMoving$.next(false)
308
+ // lastPieData = Object.assign([], data.roseData)
309
+ // console.log('lastPieData', lastPieData)
310
+ })
311
+ lastPieData = Object.assign([], roseData)
312
+
313
+ })
314
+ }).pipe(
315
+ shareReplay(1)
316
+ )
317
+
318
+ combineLatest({
319
+ pathSelection: pathSelection$,
320
+ SeriesDataMap: context.SeriesDataMap$,
321
+ computedData: context.computedData$,
322
+ highlightTarget: highlightTarget$
323
+ }).pipe(
324
+ takeUntil(destroy$),
325
+ debounceTime(0)
326
+ ).subscribe(data => {
327
+ data.pathSelection
328
+ .on('mouseover', (event, pieDatum) => {
329
+ event.stopPropagation()
330
+
331
+ context.eventTrigger$.next({
332
+ // type: 'series',
333
+ // eventName: 'mouseover',
334
+ // pluginName,
335
+ // highlightTarget: data.highlightTarget,
336
+ // datum: pieDatum.data,
337
+ // series: data.SeriesDataMap.get(pieDatum.data.seriesLabel)!,
338
+ // seriesIndex: pieDatum.data.seriesIndex,
339
+ // seriesLabel: pieDatum.data.seriesLabel,
340
+ // event,
341
+ // data: data.computedData
342
+ eventName: 'mouseover',
343
+ pluginName,
344
+ layerName,
345
+ target: pieDatum.data,
346
+ event
347
+ })
348
+ })
349
+ .on('mousemove', (event, pieDatum) => {
350
+ event.stopPropagation()
351
+
352
+ context.eventTrigger$.next({
353
+ // type: 'series',
354
+ // eventName: 'mousemove',
355
+ // pluginName,
356
+ // highlightTarget: data.highlightTarget,
357
+ // datum: pieDatum.data,
358
+ // series: data.SeriesDataMap.get(pieDatum.data.seriesLabel)!,
359
+ // seriesIndex: pieDatum.data.seriesIndex,
360
+ // seriesLabel: pieDatum.data.seriesLabel,
361
+ // event,
362
+ // data: data.computedData,
363
+ eventName: 'mousemove',
364
+ pluginName,
365
+ layerName,
366
+ target: pieDatum.data,
367
+ event
368
+ })
369
+ })
370
+ .on('mouseout', (event, pieDatum) => {
371
+ event.stopPropagation()
372
+
373
+ context.eventTrigger$.next({
374
+ // type: 'series',
375
+ // eventName: 'mouseout',
376
+ // pluginName,
377
+ // highlightTarget: data.highlightTarget,
378
+ // datum: pieDatum.data,
379
+ // series: data.SeriesDataMap.get(pieDatum.data.seriesLabel)!,
380
+ // seriesIndex: pieDatum.data.seriesIndex,
381
+ // seriesLabel: pieDatum.data.seriesLabel,
382
+ // event,
383
+ // data: data.computedData,
384
+ eventName: 'mouseout',
385
+ pluginName,
386
+ layerName,
387
+ target: pieDatum.data,
388
+ event
389
+ })
390
+ })
391
+ .on('click', (event, pieDatum) => {
392
+ event.stopPropagation()
393
+
394
+ context.eventTrigger$.next({
395
+ // type: 'series',
396
+ // eventName: 'click',
397
+ // pluginName,
398
+ // highlightTarget: data.highlightTarget,
399
+ // datum: pieDatum.data,
400
+ // series: data.SeriesDataMap.get(pieDatum.data.seriesLabel)!,
401
+ // seriesIndex: pieDatum.data.seriesIndex,
402
+ // seriesLabel: pieDatum.data.seriesLabel,
403
+ // event,
404
+ // data: data.computedData,
405
+ eventName: 'click',
406
+ pluginName,
407
+ layerName,
408
+ target: pieDatum.data,
409
+ event
410
+ })
411
+ })
412
+ })
413
+
414
+ combineLatest({
415
+ pathSelection: pathSelection$,
416
+ highlight: context.seriesHighlight$.pipe(
417
+ map(data => data.map(d => d.id))
418
+ ),
419
+ layerParams: context.layerParams$,
420
+ pluginParams: context.pluginParams$,
421
+ // arc: arc$,
422
+ tweenArc: tweenArc$,
423
+ isTransitionMoving: isTransitionMoving$
424
+ }).pipe(
425
+ takeUntil(destroy$),
426
+ debounceTime(0),
427
+ filter(d => !d.isTransitionMoving) // 避免資料變更時的動畫和highlight的動畫重覆執行
428
+ ).subscribe(data => {
429
+ highlight({
430
+ pathSelection: data.pathSelection,
431
+ ids: data.highlight,
432
+ layerParams: data.layerParams,
433
+ pluginParams: data.pluginParams,
434
+ tweenArc: data.tweenArc,
435
+ // arcMouseover: data.arcMouseover
436
+ })
437
+ })
438
+
439
+
440
+
441
+
442
+ return () => {
443
+ destroy$.next(undefined)
444
+ }
445
+ }
446
+
447
+ export const Rose = defineSVGLayer<CompositionPlotExtendContext, CompositionPlotPluginParams, RoseParams>({
448
+ name: layerName,
449
+ defaultParams: DEFAULT_ROSE_PARAMS,
450
+ layerIndex: LAYER_INDEX_OF_GRAPHIC,
451
+ initShow: false,
452
+ validator: (params) => {
453
+ const result = validateObject(params, {
454
+ outerRadius: {
455
+ toBeTypes: ['number'],
456
+ },
457
+ padAngle: {
458
+ toBeTypes: ['number'],
459
+ },
460
+ strokeColorType: {
461
+ toBeOption: 'ColorType'
462
+ },
463
+ strokeWidth: {
464
+ toBeTypes: ['number']
465
+ },
466
+ cornerRadius: {
467
+ toBeTypes: ['number']
468
+ },
469
+ arcScaleType: {
470
+ toBe: '"area" | "radius"',
471
+ test: (value: any) => value === 'area' || value === 'radius'
472
+ },
473
+ angleIncreaseWhileHighlight: {
474
+ toBeTypes: ['number']
475
+ }
476
+ })
477
+ return result
478
+ },
479
+ setup: ({ svgG, pluginParams$, layerParams$, context }) => {
480
+
481
+ const destroy$ = new Subject()
482
+
483
+ context.layout$
484
+ .pipe(
485
+ takeUntil(destroy$)
486
+ )
487
+ .subscribe(layout => {
488
+ d3.select(svgG)
489
+ .attr('transform', `translate(${layout.left}, ${layout.top})`)
490
+ })
491
+
492
+ const { seriesCenterSelection$ } = seriesCenterSelectionObservable({
493
+ selection: d3.select(svgG),
494
+ pluginName,
495
+ layerName,
496
+ visibleComputedSortedData$: context.visibleComputedSortedData$,
497
+ seriesContainerPosition$: context.seriesContainerPosition$
498
+ })
499
+
500
+ const unsubscribeFnArr: (() => void)[] = []
501
+
502
+ seriesCenterSelection$
503
+ .pipe(
504
+ takeUntil(destroy$)
505
+ )
506
+ .subscribe(seriesCenterSelection => {
507
+ // 每次重新計算時,清除之前的訂閱
508
+ unsubscribeFnArr.forEach(fn => fn())
509
+
510
+ seriesCenterSelection.each((d, containerIndex, g) => {
511
+ const containerSelection = d3.select(g[containerIndex])
512
+
513
+ const containerVisibleComputedSortedData$ = context.visibleComputedSortedData$.pipe(
514
+ takeUntil(destroy$),
515
+ map(data => JSON.parse(JSON.stringify(data[containerIndex] ?? data[0])))
516
+ )
517
+
518
+ const containerPosition$ = context.seriesContainerPosition$.pipe(
519
+ takeUntil(destroy$),
520
+ map(data => JSON.parse(JSON.stringify(data[containerIndex] ?? data[0])))
521
+ )
522
+
523
+ unsubscribeFnArr[containerIndex] = createEachRose(pluginName, {
524
+ containerSelection: containerSelection,
525
+ computedData$: context.computedData$,
526
+ // visibleComputedData$: context.visibleComputedData$,
527
+ visibleComputedSortedData$: context.visibleComputedSortedData$,
528
+ containerVisibleComputedSortedData$: containerVisibleComputedSortedData$,
529
+ SeriesDataMap$: context.SeriesDataMap$,
530
+ layerParams$: layerParams$,
531
+ pluginParams$: pluginParams$,
532
+ theme$: context.theme$,
533
+ seriesHighlight$: context.seriesHighlight$,
534
+ seriesContainerPosition$: containerPosition$,
535
+ eventTrigger$: context.eventTrigger$,
536
+ })
537
+
538
+ })
539
+ })
540
+
541
+ return () => {
542
+ destroy$.next(undefined)
543
+ unsubscribeFnArr.forEach(fn => fn())
544
+ }
545
+ }
546
+ })