@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,721 @@
1
+ import * as d3 from 'd3'
2
+ import {
3
+ combineLatest,
4
+ map,
5
+ filter,
6
+ switchMap,
7
+ debounceTime,
8
+ takeUntil,
9
+ distinctUntilChanged,
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 { ComputedLayoutDatumGrid, ComputedAxesDataGrid, SeriesPlotPluginParams } from '../plugins/SeriesPlot/types'
23
+ import { getD3TransitionEase } from '../utils/d3Utils'
24
+ import { createClassName, createUniID } from '../utils/orbchartsUtils'
25
+ import { gridCategoryPositionFnObservable, gridSelectionsObservable } from '../utils/gridObservables'
26
+
27
+ export interface BaseLinesParams {
28
+ lineCurve: string;
29
+ lineWidth: number;
30
+ }
31
+
32
+ interface BaseLinesContext {
33
+ selection: d3.Selection<any, unknown, any, unknown>
34
+ pluginName: string
35
+ layerName: string
36
+ computedData$: Observable<ComputedData<'grid'>>
37
+ // computedAxesData$: Observable<ComputedAxesDataGrid>
38
+ // visibleComputedData$: Observable<ComputedDatumGrid[][]>
39
+ visibleComputedAxesData$: Observable<ComputedAxesDataGrid>
40
+ seriesLabels$: Observable<string[]>
41
+ SeriesDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
42
+ CategoryDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
43
+ pluginParams$: Observable<SeriesPlotPluginParams>
44
+ baseLinesParams$: Observable<BaseLinesParams>
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
+ allContainerPosition$: Observable<ContainerPositionScaled[]>
55
+ layout$: Observable<Layout>
56
+ eventTrigger$: Subject<EventData<'grid'>>
57
+ }
58
+
59
+
60
+ type ClipPathDatum = {
61
+ id: string;
62
+ // x: number;
63
+ // y: number;
64
+ width: number;
65
+ height: number;
66
+ }
67
+
68
+ // const pluginName = 'Lines'
69
+ // const pathClassName = createClassName(pluginName, 'path')
70
+
71
+
72
+ function createLinePath (lineCurve: string = 'curveLinear'): d3.Line<ComputedLayoutDatumGrid> {
73
+ return d3.line<ComputedLayoutDatumGrid>()
74
+ .x((d) => d.axisX)
75
+ .y((d) => d.axisY)
76
+ .curve((d3 as any)[lineCurve])
77
+ }
78
+
79
+ // 依無值的資料分段
80
+ function makeSegmentData (data: ComputedLayoutDatumGrid[]): ComputedLayoutDatumGrid[][] {
81
+ let segmentData: ComputedLayoutDatumGrid[][] = [[]]
82
+
83
+ let currentIndex = 0
84
+ for (let i in data) {
85
+ if (data[i].visible == false || data[i].value === undefined || data[i].value === null) {
86
+ // 換下一段的 index
87
+ if (segmentData[currentIndex].length) {
88
+ currentIndex ++
89
+ segmentData[currentIndex] = []
90
+ }
91
+ continue
92
+ }
93
+ segmentData[currentIndex].push(data[i])
94
+ }
95
+
96
+ return segmentData
97
+ }
98
+
99
+
100
+ function renderLines ({ selection, pathClassName, segmentData, linePath, params }: {
101
+ selection: d3.Selection<SVGGElement, unknown, any, unknown>
102
+ pathClassName: string
103
+ segmentData: ComputedLayoutDatumGrid[][]
104
+ linePath: d3.Line<ComputedLayoutDatumGrid>
105
+ params: BaseLinesParams
106
+ }): d3.Selection<SVGPathElement, ComputedLayoutDatumGrid[], any, any> {
107
+ // if (!data[0]) {
108
+ // return undefined
109
+ // }
110
+
111
+ const lines = selection
112
+ .selectAll<SVGPathElement, ComputedLayoutDatumGrid[]>('path')
113
+ .data(segmentData, (d, i) => d.length ? `${d[0].id}_${d[d.length - 1].id}` : i) // 以線段起迄id結合為線段id
114
+ .join(
115
+ enter => {
116
+ return enter
117
+ .append<SVGPathElement>('path')
118
+ .classed(pathClassName, true)
119
+ .attr("fill","none")
120
+ .attr('pointer-events', 'visibleStroke') // 只對線條產生事件
121
+ .style('vector-effect', 'non-scaling-stroke')
122
+ .style('cursor', 'pointer')
123
+ },
124
+ update => update,
125
+ exit => exit.remove()
126
+ )
127
+ .attr("stroke-width", params.lineWidth)
128
+ .attr("stroke", (d, i) => d[0] && d[0].color)
129
+ .attr("d", (d) => {
130
+ return linePath(d)
131
+ })
132
+
133
+ return lines
134
+ }
135
+
136
+ function highlightLines ({ selection, seriesLabel, styles }: {
137
+ selection: d3.Selection<any, string, any, any>
138
+ seriesLabel: string | null
139
+ styles: GraphicStyles
140
+ }) {
141
+ selection.interrupt('highlight')
142
+ if (!seriesLabel) {
143
+ // remove highlight
144
+ selection
145
+ .transition('highlight')
146
+ .duration(200)
147
+ .style('opacity', 1)
148
+ return
149
+ }
150
+
151
+ selection
152
+ .each((currentSeriesLabel, i, n) => {
153
+ // const currentSeriesLabel = d[0] ? d[0].seriesLabel : ''
154
+
155
+ if (currentSeriesLabel === seriesLabel) {
156
+ d3.select(n[i])
157
+ .style('opacity', 1)
158
+ } else {
159
+ d3.select(n[i])
160
+ .style('opacity', styles.unhighlightedOpacity)
161
+ }
162
+ })
163
+ }
164
+
165
+ function renderClipPath ({ defsSelection, clipPathData, transitionDuration, transitionEase }: {
166
+ defsSelection: d3.Selection<SVGDefsElement, any, any, any>
167
+ clipPathData: ClipPathDatum[]
168
+ transitionDuration: number
169
+ transitionEase: string
170
+ }) {
171
+ const clipPath = defsSelection
172
+ .selectAll<SVGClipPathElement, Layout>('clipPath')
173
+ .data(clipPathData)
174
+ .join(
175
+ enter => {
176
+ return enter
177
+ .append('clipPath')
178
+ },
179
+ update => update,
180
+ exit => exit.remove()
181
+ )
182
+ .attr('id', d => d.id)
183
+ .each((d, i, g) => {
184
+ const rect = d3.select(g[i])
185
+ .selectAll<SVGRectElement, typeof d>('rect')
186
+ .data([d])
187
+ .join(
188
+ enter => {
189
+ const enterSelection = enter
190
+ .append('rect')
191
+ enterSelection
192
+ .transition()
193
+ .duration(transitionDuration)
194
+ .ease(getD3TransitionEase(transitionEase))
195
+ // .delay(100) // @Q@ 不知為何如果沒加 delay位置會有點跑掉
196
+ .tween('tween', (_d, _i, _g) => {
197
+ return (t) => {
198
+ const transitionWidth = _d.width * t
199
+
200
+ enterSelection
201
+ .attr('x', 0)
202
+ .attr('y', 0)
203
+ .attr('width', _d => transitionWidth)
204
+ .attr('height', _d => _d.height)
205
+ }
206
+ })
207
+ return enterSelection
208
+ },
209
+ update => {
210
+ return update
211
+ .attr('x', 0)
212
+ .attr('y', 0)
213
+ .attr('width', _d => _d.width)
214
+ .attr('height', _d => _d.height)
215
+ },
216
+ exit => exit.remove()
217
+ )
218
+ })
219
+
220
+ }
221
+
222
+ export const createBaseLines: BaseLayerFn<BaseLinesContext> = ({
223
+ selection,
224
+ pluginName,
225
+ layerName,
226
+ computedData$,
227
+ visibleComputedAxesData$,
228
+ seriesLabels$,
229
+ SeriesDataMap$,
230
+ CategoryDataMap$,
231
+ pluginParams$,
232
+ baseLinesParams$,
233
+ styles$,
234
+ gridAxesTransform$,
235
+ gridGraphicTransform$,
236
+ gridAxesSize$,
237
+ gridHighlight$,
238
+ gridContainerPosition$,
239
+ allContainerPosition$,
240
+ layout$,
241
+ eventTrigger$
242
+ }) => {
243
+
244
+ const destroy$ = new Subject()
245
+
246
+ const clipPathID = createUniID(pluginName, layerName, 'clipPath-box')
247
+ const pathClassName = createClassName(pluginName, layerName, 'path')
248
+ // const clipPathSeriesID = createUniID(pluginName, 'clipPath')
249
+
250
+ // const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
251
+ // .append('g')
252
+ // .attr('clip-path', `url(#${clipPathID})`)
253
+ // const defsSelection: d3.Selection<SVGDefsElement, any, any, any> = axisSelection.append('defs')
254
+ // const graphicGSelection: d3.Selection<SVGGElement, any, any, any> = axisSelection.append('g')
255
+ // const graphicSelection$: Subject<d3.Selection<SVGGElement, string, any, any>> = new Subject()
256
+
257
+
258
+ // gridAxesTransform$
259
+ // .pipe(
260
+ // takeUntil(destroy$),
261
+ // map(d => d.value),
262
+ // distinctUntilChanged()
263
+ // ).subscribe(d => {
264
+ // axisSelection
265
+ // .style('transform', d)
266
+ // })
267
+
268
+ // gridGraphicTransform$
269
+ // .pipe(
270
+ // takeUntil(destroy$),
271
+ // map(d => d.value),
272
+ // distinctUntilChanged()
273
+ // ).subscribe(d => {
274
+ // graphicGSelection
275
+ // .transition()
276
+ // .duration(50)
277
+ // .style('transform', d)
278
+ // })
279
+
280
+ // const seriesSelection$ = computedData$.pipe(
281
+ // takeUntil(destroy$),
282
+ // distinctUntilChanged((a, b) => {
283
+ // // 只有當series的數量改變時,才重新計算
284
+ // return a.length === b.length
285
+ // }),
286
+ // map((computedData, i) => {
287
+ // return selection
288
+ // .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${seriesClassName}`)
289
+ // .data(computedData, d => d[0] ? d[0].seriesIndex : i)
290
+ // .join(
291
+ // enter => {
292
+ // return enter
293
+ // .append('g')
294
+ // .classed(seriesClassName, true)
295
+ // .each((d, i, g) => {
296
+ // const axesSelection = d3.select(g[i])
297
+ // .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${axesClassName}`)
298
+ // .data([i])
299
+ // .join(
300
+ // enter => {
301
+ // return enter
302
+ // .append('g')
303
+ // .classed(axesClassName, true)
304
+ // .attr('clip-path', `url(#${clipPathID})`)
305
+ // .each((d, i, g) => {
306
+ // const defsSelection = d3.select(g[i])
307
+ // .selectAll<SVGDefsElement, any>('defs')
308
+ // .data([i])
309
+ // .join('defs')
310
+
311
+ // const graphicGSelection = d3.select(g[i])
312
+ // .selectAll<SVGGElement, any>('g')
313
+ // .data([i])
314
+ // .join('g')
315
+ // .classed(graphicClassName, true)
316
+ // })
317
+ // },
318
+ // update => update,
319
+ // exit => exit.remove()
320
+ // )
321
+ // })
322
+ // },
323
+ // update => update,
324
+ // exit => exit.remove()
325
+ // )
326
+ // })
327
+ // )
328
+
329
+ // combineLatest({
330
+ // seriesSelection: seriesSelection$,
331
+ // gridContainerPosition: gridContainerPosition$
332
+ // }).pipe(
333
+ // takeUntil(destroy$),
334
+ // debounceTime(0)
335
+ // ).subscribe(data => {
336
+ // data.seriesSelection
337
+ // .transition()
338
+ // .attr('transform', (d, i) => {
339
+ // const translate = data.gridContainerPosition[i].translate
340
+ // const scale = data.gridContainerPosition[i].scale
341
+ // return `translate(${translate[0]}, ${translate[1]}) scale(${scale[0]}, ${scale[1]})`
342
+ // })
343
+ // })
344
+
345
+
346
+ // const axesSelection$ = combineLatest({
347
+ // seriesSelection: seriesSelection$,
348
+ // gridAxesTransform: gridAxesTransform$
349
+ // }).pipe(
350
+ // takeUntil(destroy$),
351
+ // debounceTime(0),
352
+ // map(data => {
353
+ // return data.seriesSelection
354
+ // .select<SVGGElement>(`g.${axesClassName}`)
355
+ // .style('transform', data.gridAxesTransform.value)
356
+ // })
357
+ // )
358
+ // const defsSelection$ = axesSelection$.pipe(
359
+ // takeUntil(destroy$),
360
+ // map(axesSelection => {
361
+ // return axesSelection.select<SVGDefsElement>('defs')
362
+ // })
363
+ // )
364
+ // const graphicGSelection$ = combineLatest({
365
+ // axesSelection: axesSelection$,
366
+ // gridGraphicTransform: gridGraphicTransform$
367
+ // }).pipe(
368
+ // takeUntil(destroy$),
369
+ // debounceTime(0),
370
+ // map(data => {
371
+ // const graphicGSelection = data.axesSelection
372
+ // .select<SVGGElement>(`g.${graphicClassName}`)
373
+ // .attr('clip-path', (d) => `url(#${clipPathSeriesID}-${d[0] ? d[0].seriesLabel : ''})`)
374
+ // graphicGSelection
375
+ // .transition()
376
+ // .duration(50)
377
+ // .style('transform', data.gridGraphicTransform.value)
378
+ // return graphicGSelection
379
+ // })
380
+ // )
381
+
382
+ const {
383
+ seriesSelection$,
384
+ axesSelection$,
385
+ defsSelection$,
386
+ graphicGSelection$
387
+ } = gridSelectionsObservable({
388
+ selection,
389
+ pluginName,
390
+ layerName,
391
+ clipPathID,
392
+ seriesLabels$,
393
+ gridContainerPosition$,
394
+ gridAxesTransform$,
395
+ gridGraphicTransform$
396
+ })
397
+
398
+ const linePath$: Observable<d3.Line<ComputedLayoutDatumGrid>> = new Observable(subscriber => {
399
+ const paramsSubscription = baseLinesParams$
400
+ .pipe(
401
+ takeUntil(destroy$)
402
+ )
403
+ .subscribe(d => {
404
+ if (!d) return
405
+ const linePath = createLinePath(d.lineCurve)
406
+ subscriber.next(linePath)
407
+ })
408
+ return () => {
409
+ paramsSubscription.unsubscribe()
410
+ }
411
+ })
412
+
413
+ // // 顯示範圍內的series labels
414
+ // const seriesLabels$: Observable<string[]> = new Observable(subscriber => {
415
+ // computedData$.pipe(
416
+ // takeUntil(destroy$),
417
+ // switchMap(async (d) => d),
418
+ // ).subscribe(data => {
419
+ // const labels = data[0] && data[0][0]
420
+ // ? data.map(d => d[0].seriesLabel)
421
+ // : []
422
+ // subscriber.next(labels)
423
+ // })
424
+ // })
425
+
426
+ // const axisSize$ = gridAxisSizeObservable({
427
+ // fullDataFormatter$,
428
+ // computedLayout$
429
+ // })
430
+
431
+ const transitionDuration$ = styles$
432
+ .pipe(
433
+ map(d => d.transitionDuration),
434
+ distinctUntilChanged()
435
+ )
436
+
437
+ const transitionEase$ = styles$
438
+ .pipe(
439
+ map(d => d.transitionEase),
440
+ distinctUntilChanged()
441
+ )
442
+
443
+ const clipPathSubscription = combineLatest({
444
+ defsSelection: defsSelection$,
445
+ seriesLabels: seriesLabels$,
446
+ axisSize: gridAxesSize$,
447
+ transitionDuration: transitionDuration$,
448
+ transitionEase: transitionEase$
449
+ }).pipe(
450
+ takeUntil(destroy$),
451
+ switchMap(async (d) => d),
452
+ ).subscribe(data => {
453
+ // 外層的遮罩
454
+ const clipPathBox = [{
455
+ id: clipPathID,
456
+ width: data.axisSize.width,
457
+ height: data.axisSize.height
458
+ }]
459
+ // 各別線條的遮罩(各別動畫)
460
+ const clipPathData = clipPathBox.concat(
461
+ data.seriesLabels.map(d => {
462
+ return {
463
+ id: `orbcharts__clipPath_${d}`,
464
+ width: data.axisSize.width,
465
+ height: data.axisSize.height
466
+ }
467
+ })
468
+ )
469
+ renderClipPath({
470
+ defsSelection: data.defsSelection,
471
+ clipPathData,
472
+ transitionDuration: data.transitionDuration,
473
+ transitionEase: data.transitionEase
474
+ })
475
+ })
476
+
477
+ // const SeriesDataMap$ = computedData$.pipe(
478
+ // map(d => makeGridSeriesDataMap(d))
479
+ // )
480
+
481
+ // const CategoryDataMap$ = computedData$.pipe(
482
+ // map(d => makeGridCategoryDataMap(d))
483
+ // )
484
+
485
+ const DataMap$ = computedData$.pipe(
486
+ map(d => {
487
+ const DataMap: Map<string, ComputedDatumGrid> = new Map()
488
+ d.flat().forEach(_d => DataMap.set(_d.id, _d))
489
+ return DataMap
490
+ })
491
+ )
492
+
493
+ // 取得事件座標的group資料
494
+ const gridGroupPositionFn$ = gridCategoryPositionFnObservable({
495
+ // fullDataFormatter$,
496
+ pluginParams$,
497
+ gridAxesSize$: gridAxesSize$,
498
+ computedData$: computedData$,
499
+ // fullChartParams$: fullChartParams$,
500
+ gridContainerPosition$: allContainerPosition$,
501
+ layout$: layout$
502
+ })
503
+
504
+ const highlightTarget$ = styles$.pipe(
505
+ takeUntil(destroy$),
506
+ map(d => d.highlightTarget),
507
+ distinctUntilChanged()
508
+ )
509
+
510
+ const pathSelectionArr$ = combineLatest({
511
+ graphicGSelection: graphicGSelection$,
512
+ visibleComputedAxesData: visibleComputedAxesData$,
513
+ linePath: linePath$,
514
+ params: baseLinesParams$,
515
+ }).pipe(
516
+ takeUntil(destroy$),
517
+ switchMap(async (d) => d),
518
+ map(data => {
519
+ // const updateGraphic = data.graphicGSelection
520
+ // .selectAll<SVGGElement, number>('g')
521
+ // .data(data.seriesLabels, (d, i) => d)
522
+ // const enterGraphic = updateGraphic.enter()
523
+ // .append('g')
524
+ // .classed(graphicClassName, true)
525
+ // updateGraphic.exit().remove()
526
+ // const graphicSelection = updateGraphic.merge(enterGraphic)
527
+ // .attr('clip-path', (d, i) => `url(#orbcharts__clipPath_${d})`)
528
+ let pathSelectionArr: d3.Selection<SVGPathElement, ComputedLayoutDatumGrid[], any, any>[] = []
529
+
530
+ // 繪圖
531
+ data.graphicGSelection.each((d, i, all) => {
532
+ // 將資料分段
533
+ const segmentData = makeSegmentData(data.visibleComputedAxesData[i] ?? [])
534
+
535
+ pathSelectionArr[i] = renderLines({
536
+ selection: d3.select(all[i]),
537
+ pathClassName,
538
+ linePath: data.linePath,
539
+ segmentData: segmentData,
540
+ params: data.params
541
+ })
542
+ })
543
+
544
+ return pathSelectionArr
545
+ })
546
+ )
547
+
548
+ combineLatest({
549
+ pathSelectionArr: pathSelectionArr$,
550
+ computedData: computedData$,
551
+ SeriesDataMap: SeriesDataMap$,
552
+ CategoryDataMap: CategoryDataMap$,
553
+ highlightTarget: highlightTarget$,
554
+ gridGroupPositionFn: gridGroupPositionFn$,
555
+ }).pipe(
556
+ takeUntil(destroy$),
557
+ switchMap(async (d) => d)
558
+ ).subscribe(data => {
559
+ data.pathSelectionArr.forEach(pathSelection => {
560
+ pathSelection
561
+ .on('mouseover', (event, datum) => {
562
+ // event.stopPropagation()
563
+
564
+ const seriesLabel = datum[0] ? datum[0].series : ''
565
+ const { categoryIndex, categoryLabel } = data.gridGroupPositionFn(event)
566
+ // console.log('categoryIndex', categoryIndex)
567
+ const groupData = data.CategoryDataMap.get(categoryLabel)!
568
+ const targetDatum = groupData.find(d => d.series === seriesLabel)
569
+ const _datum = targetDatum ?? datum[0]
570
+
571
+ eventTrigger$.next({
572
+ // type: 'grid',
573
+ // eventName: 'mouseover',
574
+ // pluginName,
575
+ // highlightTarget: data.highlightTarget,
576
+ // datum: _datum,
577
+ // gridIndex: _datum.gridIndex,
578
+ // series: data.SeriesDataMap.get(_datum.series)!,
579
+ // seriesIndex: _datum.seriesIndex,
580
+ // seriesLabel: _datum.series,
581
+ // group: data.CategoryDataMap.get(_datum.series)!,
582
+ // categoryIndex: _datum.categoryIndex,
583
+ // categoryLabel: _datum.categoryLabel,
584
+ // event,
585
+ // data: data.computedData
586
+ eventName: 'mouseover',
587
+ pluginName,
588
+ layerName,
589
+ target: _datum,
590
+ event
591
+ })
592
+ })
593
+ .on('mousemove', (event, datum) => {
594
+ // event.stopPropagation()
595
+
596
+ const seriesLabel = datum[0] ? datum[0].series : ''
597
+ const { categoryIndex, categoryLabel } = data.gridGroupPositionFn(event)
598
+ const groupData = data.CategoryDataMap.get(categoryLabel)!
599
+ const targetDatum = groupData.find(d => d.series === seriesLabel)
600
+ const _datum = targetDatum ?? datum[0]
601
+
602
+ eventTrigger$.next({
603
+ // type: 'grid',
604
+ // eventName: 'mousemove',
605
+ // pluginName,
606
+ // highlightTarget: data.highlightTarget,
607
+ // datum: _datum,
608
+ // gridIndex: _datum.gridIndex,
609
+ // series: data.SeriesDataMap.get(_datum.seriesLabel)!,
610
+ // seriesIndex: _datum.seriesIndex,
611
+ // seriesLabel: _datum.seriesLabel,
612
+ // group: data.CategoryDataMap.get(_datum.categoryLabel)!,
613
+ // categoryIndex: _datum.categoryIndex,
614
+ // categoryLabel: _datum.categoryLabel,
615
+ // event,
616
+ // data: data.computedData
617
+ eventName: 'mousemove',
618
+ pluginName,
619
+ layerName,
620
+ target: _datum,
621
+ event
622
+ })
623
+ })
624
+ .on('mouseout', (event, datum) => {
625
+ // event.stopPropagation()
626
+
627
+ const seriesLabel = datum[0] ? datum[0].series : ''
628
+ const { categoryIndex, categoryLabel } = data.gridGroupPositionFn(event)
629
+ const groupData = data.CategoryDataMap.get(categoryLabel)!
630
+ const targetDatum = groupData.find(d => d.series === seriesLabel)
631
+ const _datum = targetDatum ?? datum[0]
632
+
633
+ eventTrigger$.next({
634
+ // type: 'grid',
635
+ // eventName: 'mouseout',
636
+ // pluginName,
637
+ // highlightTarget: data.highlightTarget,
638
+ // datum: _datum,
639
+ // gridIndex: _datum.gridIndex,
640
+ // series: data.SeriesDataMap.get(_datum.seriesLabel)!,
641
+ // seriesIndex: _datum.seriesIndex,
642
+ // seriesLabel: _datum.seriesLabel,
643
+ // group: data.CategoryDataMap.get(_datum.categoryLabel)!,
644
+ // categoryIndex: _datum.categoryIndex,
645
+ // categoryLabel: _datum.categoryLabel,
646
+ // event,
647
+ // data: data.computedData
648
+ eventName: 'mouseout',
649
+ pluginName,
650
+ layerName,
651
+ target: _datum,
652
+ event
653
+ })
654
+ })
655
+ .on('click', (event, datum) => {
656
+ // event.stopPropagation()
657
+
658
+ const seriesLabel = datum[0] ? datum[0].series : ''
659
+ const { categoryIndex, categoryLabel } = data.gridGroupPositionFn(event)
660
+ const groupData = data.CategoryDataMap.get(categoryLabel)!
661
+ const targetDatum = groupData.find(d => d.series === seriesLabel)
662
+ const _datum = targetDatum ?? datum[0]
663
+
664
+ eventTrigger$.next({
665
+ // type: 'grid',
666
+ // eventName: 'click',
667
+ // pluginName,
668
+ // highlightTarget: data.highlightTarget,
669
+ // datum: _datum,
670
+ // gridIndex: _datum.gridIndex,
671
+ // series: data.SeriesDataMap.get(_datum.seriesLabel)!,
672
+ // seriesIndex: _datum.seriesIndex,
673
+ // seriesLabel: _datum.seriesLabel,
674
+ // group: data.CategoryDataMap.get(_datum.categoryLabel)!,
675
+ // categoryIndex: _datum.categoryIndex,
676
+ // categoryLabel: _datum.categoryLabel,
677
+ // event,
678
+ // data: data.computedData
679
+ eventName: 'click',
680
+ pluginName,
681
+ layerName,
682
+ target: _datum,
683
+ event
684
+ })
685
+ })
686
+ })
687
+ })
688
+
689
+ // const datumList$ = computedData$.pipe(
690
+ // takeUntil(destroy$),
691
+ // map(d => d.flat())
692
+ // )
693
+ // const highlight$ = highlightObservable({ datumList$, fullChartParams$, eventTrigger$: store.eventTrigger$ })
694
+ // const highlightSubscription = gridHighlight$.subscribe()
695
+
696
+ styles$.pipe(
697
+ takeUntil(destroy$),
698
+ filter(d => d.highlightTarget === 'series'),
699
+ switchMap(d => combineLatest({
700
+ graphicGSelection: graphicGSelection$,
701
+ gridHighlight: gridHighlight$,
702
+ DataMap: DataMap$,
703
+ styles: styles$
704
+ }).pipe(
705
+ takeUntil(destroy$),
706
+ debounceTime(0)
707
+ ))
708
+ ).subscribe(data => {
709
+ const seriesLabel = data.gridHighlight[0] ? data.gridHighlight[0].series : null
710
+ highlightLines({
711
+ selection: data.graphicGSelection,
712
+ seriesLabel,
713
+ styles: data.styles
714
+ })
715
+ })
716
+
717
+ return () => {
718
+ destroy$.next(undefined)
719
+ // highlightSubscription.unsubscribe()
720
+ }
721
+ }