@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,692 @@
1
+ import * as d3 from 'd3'
2
+ import {
3
+ combineLatest,
4
+ map,
5
+ debounceTime,
6
+ switchMap,
7
+ takeUntil,
8
+ distinctUntilChanged,
9
+ shareReplay,
10
+ Observable,
11
+ Subject } from 'rxjs'
12
+ import type { EventData } from '@orbcharts/core'
13
+ import type { BaseLayerFn } from '../types/BaseLayer'
14
+ import type {
15
+ ComputedDatumGrid,
16
+ ComputedData,
17
+ ContainerPositionScaled,
18
+ Layout,
19
+ TransformData,
20
+ GraphicStyles
21
+ } from '../types'
22
+ import type { ComputedAxesDataGrid } from '../plugins/SeriesPlot/types'
23
+ import { getD3TransitionEase } from '../utils/d3Utils'
24
+ import { createClassName, createUniID } from '../utils/orbchartsUtils'
25
+ import { gridSelectionsObservable } from '../utils/gridObservables'
26
+
27
+ export interface BaseBarsTriangleParams {
28
+ barWidth: number;
29
+ barPadding: number;
30
+ barGroupPadding: number;
31
+ linearGradientOpacity: [number, number];
32
+ }
33
+
34
+ interface BaseBarsContext {
35
+ selection: d3.Selection<any, unknown, any, unknown>
36
+ pluginName: string
37
+ layerName: string
38
+ computedData$: Observable<ComputedData<'grid'>>
39
+ visibleComputedData$: Observable<ComputedDatumGrid[][]>
40
+ visibleComputedAxesData$: Observable<ComputedAxesDataGrid>
41
+ seriesLabels$: Observable<string[]>
42
+ SeriesDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
43
+ CategoryDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
44
+ baseBarsTriangleParams$: Observable<BaseBarsTriangleParams>
45
+ styles$: Observable<GraphicStyles>
46
+ gridAxesTransform$: Observable<TransformData>
47
+ gridGraphicTransform$: Observable<TransformData>
48
+ gridAxesSize$: Observable<{
49
+ width: number;
50
+ height: number;
51
+ }>
52
+ gridHighlight$: Observable<ComputedDatumGrid[]>
53
+ gridContainerPosition$: Observable<ContainerPositionScaled[]>
54
+ isSeriesSeprate$: Observable<boolean>
55
+ eventTrigger$: Subject<EventData<'grid'>>
56
+ }
57
+
58
+
59
+ interface RenderBarParams {
60
+ graphicGSelection: d3.Selection<SVGGElement, unknown, any, any>
61
+ pathGClassName: string
62
+ pathClassName: string
63
+ visibleComputedAxesData: ComputedAxesDataGrid
64
+ linearGradientIds: string[]
65
+ zeroYArr: number[]
66
+ barScale: d3.ScalePoint<string>
67
+ styles: GraphicStyles
68
+ barWidth: number
69
+ delayGroup: number
70
+ transitionItem: number
71
+ isSeriesSeprate: boolean
72
+ }
73
+
74
+ // interface BarDatumGrid extends ComputedDatumGrid {
75
+ // linearGradientId: string
76
+ // }
77
+
78
+ type ClipPathDatum = {
79
+ id: string;
80
+ // x: number;
81
+ // y: number;
82
+ width: number;
83
+ height: number;
84
+ }
85
+
86
+ // const pluginName = 'BaseBarsTriangle'
87
+ // const pathGClassName = createClassName(pluginName, 'pathG')
88
+ // const pathClassName = createClassName(pluginName, 'path')
89
+ // group的delay在動畫中的佔比(剩餘部份的時間為圖形本身的動畫時間,因為delay時間和最後一個group的動畫時間加總為1)
90
+ const groupDelayProportionOfDuration = 0.3
91
+
92
+ function calcBarWidth ({ axisWidth, groupAmount, barAmountOfGroup, barPadding = 0, barGroupPadding = 0 }: {
93
+ axisWidth: number
94
+ groupAmount: number
95
+ barAmountOfGroup: number
96
+ barPadding: number
97
+ barGroupPadding: number
98
+ }) {
99
+ const eachGroupWidth = groupAmount > 1 // 等於 1 時會算出 Infinity
100
+ ? axisWidth / (groupAmount - 1)
101
+ : axisWidth
102
+ const width = (eachGroupWidth - barGroupPadding) / barAmountOfGroup - barPadding
103
+ return width > 1 ? width : 1
104
+ }
105
+
106
+ function makeBarScale (barWidth: number, seriesLabels: string[], params: BaseBarsTriangleParams) {
107
+ const barHalfWidth = barWidth! / 2
108
+ const barGroupWidth = barWidth * seriesLabels.length + params.barPadding! * seriesLabels.length
109
+ return d3.scalePoint()
110
+ .domain(seriesLabels)
111
+ .range([-barGroupWidth / 2 + barHalfWidth, barGroupWidth / 2 - barHalfWidth])
112
+ }
113
+
114
+ function calcDelayGroup (barGroupAmount: number, totalDuration: number) {
115
+ if (barGroupAmount <= 1) {
116
+ // 一筆內計算會出錯所以不算
117
+ return 0
118
+ }
119
+ return totalDuration / (barGroupAmount - 1) * groupDelayProportionOfDuration // 依group數量計算
120
+ }
121
+
122
+ function calctransitionItem (barGroupAmount: number, totalDuration: number) {
123
+ if (barGroupAmount <= 1) {
124
+ // 一筆內不會有delay
125
+ return totalDuration
126
+ }
127
+ return totalDuration * (1 - groupDelayProportionOfDuration) // delay後剩餘的時間
128
+ }
129
+
130
+ function renderTriangleBars ({ graphicGSelection, pathGClassName, pathClassName, visibleComputedAxesData, linearGradientIds, zeroYArr, barScale, styles, barWidth, delayGroup, transitionItem, isSeriesSeprate }: RenderBarParams) {
131
+
132
+ const barHalfWidth = barWidth! / 2
133
+
134
+ graphicGSelection
135
+ .each((d, seriesIndex, g) => {
136
+ // g
137
+ const gSelection = d3.select(g[seriesIndex])
138
+ .selectAll<SVGGElement, ComputedDatumGrid>(`g.${pathGClassName}`)
139
+ .data(visibleComputedAxesData[seriesIndex] ?? [])
140
+ .join(
141
+ enter => {
142
+ const enterSelection = enter
143
+ .append('g')
144
+ .classed(pathGClassName, true)
145
+ .attr('cursor', 'pointer')
146
+ enterSelection
147
+ .append('path')
148
+ .classed(pathClassName, true)
149
+ .style('vector-effect', 'non-scaling-stroke')
150
+ .attr('d', (d) => {
151
+ const x = -barHalfWidth
152
+ const y1 = zeroYArr[seriesIndex]
153
+ const y2 = zeroYArr[seriesIndex]
154
+ return `M${x},${y1} L${x + (barWidth! / 2)},${y2} ${x + barWidth!},${y1}`
155
+ })
156
+ return enterSelection
157
+ },
158
+ update => update,
159
+ exit => exit.remove()
160
+ )
161
+ .attr('transform', d => `translate(${isSeriesSeprate ? 0 : barScale(d.series)!}, 0)`)
162
+
163
+ // path
164
+ gSelection.select(`path.${pathClassName}`)
165
+ .attr('height', d => Math.abs(d.axisYFromZero) || 1) // 無值還是給一個 1 的高度
166
+ .attr('y', d => d.axisY < zeroYArr[seriesIndex] ? d.axisY : zeroYArr[seriesIndex])
167
+ .attr('x', d => isSeriesSeprate ? 0 : barScale(d.series)!)
168
+ // .style('fill', d => `url(#${d.linearGradientId})`)
169
+ .style('fill', d => `url(#${linearGradientIds[d.seriesIndex]})`)
170
+ .attr('stroke', d => d.color)
171
+ .attr('transform', d => `translate(${(d ? d.axisX : 0)}, ${0})`)
172
+ .transition()
173
+ .duration(transitionItem)
174
+ .ease(getD3TransitionEase(styles.transitionEase))
175
+ .delay((d, i) => d.categoryIndex * delayGroup)
176
+ // .attr('transform', `translate(${-barHalfWidth}, 0)`)
177
+ // .attr('x', d => itemScale(d.itemLabel)!)
178
+ // .attr('y', d => -d.y)
179
+ .attr('d', (d) => {
180
+ const x = -barHalfWidth
181
+ const y1 = zeroYArr[seriesIndex]
182
+ const y2 = d.axisY
183
+ return `M${x},${y1} L${x + (barWidth! / 2)},${y2} ${x + barWidth!},${y1}`
184
+ })
185
+ })
186
+
187
+ const graphicBarSelection: d3.Selection<SVGPathElement, ComputedDatumGrid, any, any> = graphicGSelection.selectAll(`path.${pathClassName}`)
188
+
189
+ return graphicBarSelection
190
+ }
191
+
192
+ function renderLinearGradient ({ defsSelection, computedData, linearGradientIds, params }: {
193
+ defsSelection: d3.Selection<SVGDefsElement, any, any, any>
194
+ computedData: ComputedData<'grid'>
195
+ linearGradientIds: string[]
196
+ params: BaseBarsTriangleParams
197
+ }) {
198
+ defsSelection!
199
+ .selectAll<SVGLinearGradientElement, ComputedDatumGrid>('linearGradient')
200
+ .data(computedData ?? [])
201
+ .join(
202
+ enter => {
203
+ return enter
204
+ .append('linearGradient')
205
+ .attr('x1', '0%')
206
+ .attr('x2', '0%')
207
+ .attr('y1', '100%')
208
+ .attr('y2', '0%')
209
+ .attr('spreadMethod', 'pad')
210
+ },
211
+ update => update,
212
+ exit => exit.remove()
213
+ )
214
+ .attr('id', (d, i) => {
215
+ return d[0] ? linearGradientIds[d[0].seriesIndex] : ''
216
+ })
217
+ .html((d, i) => {
218
+ const color = d[0] ? d[0].color : ''
219
+ return `
220
+ <stop offset="0%" stop-color="${color}" stop-opacity="${params.linearGradientOpacity[0]}"/>
221
+ <stop offset="100%" stop-color="${color}" stop-opacity="${params.linearGradientOpacity[1]}"/>
222
+ `
223
+ })
224
+
225
+ }
226
+
227
+
228
+ function renderClipPath ({ defsSelection, clipPathData }: {
229
+ defsSelection: d3.Selection<SVGDefsElement, any, any, any>
230
+ clipPathData: ClipPathDatum[]
231
+ }) {
232
+ const clipPath = defsSelection
233
+ .selectAll<SVGClipPathElement, Layout>('clipPath')
234
+ .data(clipPathData)
235
+ .join(
236
+ enter => {
237
+ return enter
238
+ .append('clipPath')
239
+ },
240
+ update => update,
241
+ exit => exit.remove()
242
+ )
243
+ .attr('id', d => d.id)
244
+ .each((d, i, g) => {
245
+ const rect = d3.select(g[i])
246
+ .selectAll<SVGRectElement, typeof d>('rect')
247
+ .data([d])
248
+ .join(
249
+ enter => {
250
+ return enter
251
+ .append('rect')
252
+ },
253
+ update => update,
254
+ exit => exit.remove()
255
+ )
256
+ .attr('x', 0)
257
+ .attr('y', 0)
258
+ .attr('width', _d => _d.width)
259
+ .attr('height', _d => _d.height)
260
+ })
261
+ }
262
+
263
+ function highlight ({ selection, ids, styles }: {
264
+ selection: d3.Selection<SVGPathElement, ComputedDatumGrid, any, any>
265
+ ids: string[]
266
+ styles: GraphicStyles
267
+ }) {
268
+ selection.interrupt('highlight')
269
+
270
+ const removeHighlight = () => {
271
+ selection
272
+ .transition('highlight')
273
+ .duration(200)
274
+ .style('opacity', 1)
275
+ }
276
+
277
+ if (!ids.length) {
278
+ removeHighlight()
279
+ return
280
+ }
281
+
282
+ selection
283
+ .each((d, i, n) => {
284
+ if (ids.includes(d.id)) {
285
+ d3.select(n[i])
286
+ .style('opacity', 1)
287
+ } else {
288
+ d3.select(n[i])
289
+ .style('opacity', styles.unhighlightedOpacity)
290
+ }
291
+ })
292
+ }
293
+
294
+
295
+ export const createBaseBarsTriangle: BaseLayerFn<BaseBarsContext> = ({
296
+ selection,
297
+ pluginName,
298
+ layerName,
299
+ computedData$,
300
+ visibleComputedData$,
301
+ visibleComputedAxesData$,
302
+ seriesLabels$,
303
+ SeriesDataMap$,
304
+ CategoryDataMap$,
305
+ baseBarsTriangleParams$,
306
+ styles$,
307
+ gridAxesTransform$,
308
+ gridGraphicTransform$,
309
+ gridAxesSize$,
310
+ gridHighlight$,
311
+ gridContainerPosition$,
312
+ isSeriesSeprate$,
313
+ eventTrigger$
314
+ }) => {
315
+ const destroy$ = new Subject()
316
+
317
+ const clipPathID = createUniID(pluginName, layerName, 'clipPath-box')
318
+ const pathGClassName = createClassName(pluginName, layerName, 'pathG')
319
+ const pathClassName = createClassName(pluginName, layerName, 'path')
320
+
321
+ const {
322
+ seriesSelection$,
323
+ axesSelection$,
324
+ defsSelection$,
325
+ graphicGSelection$
326
+ } = gridSelectionsObservable({
327
+ selection,
328
+ pluginName,
329
+ layerName,
330
+ clipPathID,
331
+ seriesLabels$,
332
+ gridContainerPosition$,
333
+ gridAxesTransform$,
334
+ gridGraphicTransform$
335
+ })
336
+
337
+ // valueAxis 的起始座標
338
+ const valueAxisStart$: Observable<number> = gridGraphicTransform$.pipe(
339
+ takeUntil(destroy$),
340
+ map(data => {
341
+ // 抵消掉外層的變型
342
+ return - data.translate[1] / data.scale[1]
343
+ })
344
+ )
345
+
346
+ const zeroYArr$ = visibleComputedAxesData$.pipe(
347
+ // map(d => d[0] && d[0][0]
348
+ // ? d[0][0].axisY - d[0][0].axisYFromZero
349
+ // : 0),
350
+ map(data => {
351
+ return data.map(d => {
352
+ return d[0] ? d[0].axisY - d[0].axisYFromZero : 0
353
+ })
354
+ }),
355
+ distinctUntilChanged()
356
+ )
357
+
358
+ const barWidth$ = combineLatest({
359
+ computedData: computedData$,
360
+ visibleComputedData: visibleComputedData$,
361
+ params: baseBarsTriangleParams$,
362
+ gridAxesSize: gridAxesSize$,
363
+ isSeriesSeprate: isSeriesSeprate$
364
+ }).pipe(
365
+ takeUntil(destroy$),
366
+ debounceTime(0),
367
+ map(data => {
368
+ if (data.params.barWidth) {
369
+ return data.params.barWidth
370
+ } else if (data.isSeriesSeprate) {
371
+ return calcBarWidth({
372
+ axisWidth: data.gridAxesSize.width,
373
+ groupAmount: data.computedData[0] ? data.computedData[0].length : 0,
374
+ barAmountOfGroup: 1,
375
+ barPadding: data.params.barPadding,
376
+ barGroupPadding: data.params.barGroupPadding
377
+ })
378
+ } else {
379
+ return calcBarWidth({
380
+ axisWidth: data.gridAxesSize.width,
381
+ groupAmount: data.computedData[0] ? data.computedData[0].length : 0,
382
+ barAmountOfGroup: data.visibleComputedData.length,
383
+ barPadding: data.params.barPadding,
384
+ barGroupPadding: data.params.barGroupPadding
385
+ })
386
+ }
387
+ })
388
+ )
389
+
390
+ // const seriesLabels$ = visibleComputedData$.pipe(
391
+ // takeUntil(destroy$),
392
+ // map(data => {
393
+ // const SeriesLabelSet: Set<string> = new Set()
394
+ // data.forEach(d => {
395
+ // d.forEach(_d => {
396
+ // SeriesLabelSet.add(_d.seriesLabel)
397
+ // })
398
+ // })
399
+ // return Array.from(SeriesLabelSet)
400
+ // })
401
+ // )
402
+
403
+ const groupLabels$ = visibleComputedData$.pipe(
404
+ takeUntil(destroy$),
405
+ map(data => {
406
+ const GroupLabelSet: Set<string> = new Set()
407
+ data.forEach(d => {
408
+ d.forEach(_d => {
409
+ GroupLabelSet.add(_d.category)
410
+ })
411
+ })
412
+ return Array.from(GroupLabelSet)
413
+ })
414
+ )
415
+
416
+ const barScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
417
+ combineLatest({
418
+ seriesLabels: seriesLabels$,
419
+ barWidth: barWidth$,
420
+ params: baseBarsTriangleParams$,
421
+ }).pipe(
422
+ takeUntil(destroy$),
423
+ debounceTime(0)
424
+ ).subscribe(data => {
425
+ const barScale = makeBarScale(data.barWidth, data.seriesLabels, data.params)
426
+ subscriber.next(barScale)
427
+ })
428
+ })
429
+
430
+ const transitionDuration$ = styles$.pipe(
431
+ takeUntil(destroy$),
432
+ map(d => d.transitionDuration),
433
+ distinctUntilChanged()
434
+ )
435
+
436
+ const delayGroup$ = new Observable<number>(subscriber => {
437
+ combineLatest({
438
+ groupLabels: groupLabels$,
439
+ transitionDuration: transitionDuration$,
440
+ }).pipe(
441
+ debounceTime(0)
442
+ ).subscribe(data => {
443
+ const delay = calcDelayGroup(data.groupLabels.length, data.transitionDuration)
444
+ subscriber.next(delay)
445
+ })
446
+ }).pipe(
447
+ takeUntil(destroy$),
448
+ distinctUntilChanged()
449
+ )
450
+
451
+ const transitionItem$ = new Observable<number>(subscriber => {
452
+ combineLatest({
453
+ groupLabels: groupLabels$,
454
+ transitionDuration: transitionDuration$
455
+ }).pipe(
456
+ debounceTime(0)
457
+ ).subscribe(data => {
458
+ const transition = calctransitionItem(data.groupLabels.length, data.transitionDuration)
459
+ subscriber.next(transition)
460
+ })
461
+ }).pipe(
462
+ takeUntil(destroy$),
463
+ distinctUntilChanged()
464
+ )
465
+
466
+ //
467
+
468
+ combineLatest({
469
+ defsSelection: defsSelection$,
470
+ gridAxesSize: gridAxesSize$,
471
+ }).pipe(
472
+ takeUntil(destroy$),
473
+ debounceTime(0)
474
+ ).subscribe(data => {
475
+ const clipPathData = [{
476
+ id: clipPathID,
477
+ width: data.gridAxesSize.width,
478
+ height: data.gridAxesSize.height
479
+ }]
480
+ renderClipPath({
481
+ defsSelection: data.defsSelection,
482
+ clipPathData
483
+ })
484
+ })
485
+
486
+
487
+ const highlightTarget$ = styles$.pipe(
488
+ takeUntil(destroy$),
489
+ map(d => d.highlightTarget),
490
+ distinctUntilChanged()
491
+ )
492
+
493
+ const linearGradientIds$ = seriesLabels$.pipe(
494
+ takeUntil(destroy$),
495
+ map(d => d.map((d, i) => {
496
+ return createUniID(pluginName, layerName, `lineargradient-${d}`)
497
+ }))
498
+ )
499
+
500
+ // const barData$ = combineLatest({
501
+ // linearGradientIds: linearGradientIds$,
502
+ // computedData: computedData$
503
+ // }).pipe(
504
+ // takeUntil(destroy$),
505
+ // debounceTime(0),
506
+ // map(data => {
507
+ // return data.computedData.map((series, seriesIndex) => {
508
+ // return series.map((_d, _i) => {
509
+ // return <BarDatumGrid>{
510
+ // linearGradientId: data.linearGradientIds[seriesIndex],
511
+ // ..._d
512
+ // }
513
+ // })
514
+ // })
515
+ // })
516
+ // )
517
+
518
+ const barSelection$ = combineLatest({
519
+ graphicGSelection: graphicGSelection$,
520
+ defsSelection: defsSelection$,
521
+ computedData: computedData$,
522
+ visibleComputedAxesData: visibleComputedAxesData$,
523
+ linearGradientIds: linearGradientIds$,
524
+ zeroYArr: zeroYArr$,
525
+ groupLabels: groupLabels$,
526
+ barScale: barScale$,
527
+ params: baseBarsTriangleParams$,
528
+ styles: styles$,
529
+ barWidth: barWidth$,
530
+ delayGroup: delayGroup$,
531
+ transitionItem: transitionItem$,
532
+ isSeriesSeprate: isSeriesSeprate$
533
+ }).pipe(
534
+ takeUntil(destroy$),
535
+ switchMap(async (d) => d),
536
+ map(data => {
537
+ renderLinearGradient({
538
+ defsSelection: data.defsSelection,
539
+ computedData: data.computedData,
540
+ linearGradientIds: data.linearGradientIds,
541
+ params: data.params
542
+ })
543
+
544
+ return renderTriangleBars({
545
+ graphicGSelection: data.graphicGSelection,
546
+ pathGClassName,
547
+ pathClassName,
548
+ visibleComputedAxesData: data.visibleComputedAxesData,
549
+ linearGradientIds: data.linearGradientIds,
550
+ zeroYArr: data.zeroYArr,
551
+ barScale: data.barScale,
552
+ styles: data.styles,
553
+ barWidth: data.barWidth,
554
+ delayGroup: data.delayGroup,
555
+ transitionItem: data.transitionItem,
556
+ isSeriesSeprate: data.isSeriesSeprate
557
+ })
558
+ })
559
+ )
560
+
561
+ combineLatest({
562
+ barSelection: barSelection$,
563
+ computedData: computedData$,
564
+ highlightTarget: highlightTarget$,
565
+ SeriesDataMap: SeriesDataMap$,
566
+ CategoryDataMap: CategoryDataMap$,
567
+ }).subscribe(data => {
568
+
569
+ data.barSelection!
570
+ .on('mouseover', (event, datum) => {
571
+ event.stopPropagation()
572
+
573
+ eventTrigger$.next({
574
+ // type: 'grid',
575
+ // eventName: 'mouseover',
576
+ // pluginName,
577
+ // highlightTarget: data.highlightTarget,
578
+ // datum,
579
+ // gridIndex: datum.gridIndex,
580
+ // series: data.SeriesDataMap.get(datum.seriesLabel)!,
581
+ // seriesIndex: datum.seriesIndex,
582
+ // seriesLabel: datum.seriesLabel,
583
+ // group: data.CategoryDataMap.get(datum.groupLabel)!,
584
+ // groupIndex: datum.groupIndex,
585
+ // groupLabel: datum.groupLabel,
586
+ // event,
587
+ // data: data.computedData
588
+ eventName: 'mouseover',
589
+ pluginName,
590
+ layerName,
591
+ target: datum,
592
+ event
593
+ })
594
+ })
595
+ .on('mousemove', (event, datum) => {
596
+ event.stopPropagation()
597
+
598
+ eventTrigger$.next({
599
+ // type: 'grid',
600
+ // eventName: 'mousemove',
601
+ // pluginName,
602
+ // highlightTarget: data.highlightTarget,
603
+ // datum,
604
+ // gridIndex: datum.gridIndex,
605
+ // series: data.SeriesDataMap.get(datum.seriesLabel)!,
606
+ // seriesIndex: datum.seriesIndex,
607
+ // seriesLabel: datum.seriesLabel,
608
+ // group: data.CategoryDataMap.get(datum.groupLabel)!,
609
+ // groupIndex: datum.groupIndex,
610
+ // groupLabel: datum.groupLabel,
611
+ // event,
612
+ // data: data.computedData
613
+ eventName: 'mousemove',
614
+ pluginName,
615
+ layerName,
616
+ target: datum,
617
+ event
618
+ })
619
+ })
620
+ .on('mouseout', (event, datum) => {
621
+ event.stopPropagation()
622
+
623
+ eventTrigger$.next({
624
+ // type: 'grid',
625
+ // eventName: 'mouseout',
626
+ // pluginName,
627
+ // highlightTarget: data.highlightTarget,
628
+ // datum,
629
+ // gridIndex: datum.gridIndex,
630
+ // series: data.SeriesDataMap.get(datum.seriesLabel)!,
631
+ // seriesIndex: datum.seriesIndex,
632
+ // seriesLabel: datum.seriesLabel,
633
+ // group: data.CategoryDataMap.get(datum.groupLabel)!,
634
+ // groupIndex: datum.groupIndex,
635
+ // groupLabel: datum.groupLabel,
636
+ // event,
637
+ // data: data.computedData
638
+ eventName: 'mouseout',
639
+ pluginName,
640
+ layerName,
641
+ target: datum,
642
+ event
643
+ })
644
+ })
645
+ .on('click', (event, datum) => {
646
+ event.stopPropagation()
647
+
648
+ eventTrigger$.next({
649
+ // type: 'grid',
650
+ // eventName: 'click',
651
+ // pluginName,
652
+ // highlightTarget: data.highlightTarget,
653
+ // datum,
654
+ // gridIndex: datum.gridIndex,
655
+ // series: data.SeriesDataMap.get(datum.seriesLabel)!,
656
+ // seriesIndex: datum.seriesIndex,
657
+ // seriesLabel: datum.seriesLabel,
658
+ // group: data.CategoryDataMap.get(datum.groupLabel)!,
659
+ // groupIndex: datum.groupIndex,
660
+ // groupLabel: datum.groupLabel,
661
+ // event,
662
+ // data: data.computedData
663
+ eventName: 'click',
664
+ pluginName,
665
+ layerName,
666
+ target: datum,
667
+ event
668
+ })
669
+ })
670
+ })
671
+
672
+ combineLatest({
673
+ barSelection: barSelection$,
674
+ highlight: gridHighlight$.pipe(
675
+ map(data => data.map(d => d.id))
676
+ ),
677
+ styles: styles$
678
+ }).pipe(
679
+ takeUntil(destroy$),
680
+ debounceTime(0)
681
+ ).subscribe(data => {
682
+ highlight({
683
+ selection: data.barSelection,
684
+ ids: data.highlight,
685
+ styles: data.styles
686
+ })
687
+ })
688
+
689
+ return () => {
690
+ destroy$.next(undefined)
691
+ }
692
+ }