@orbcharts/core 3.0.0-alpha.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (166) hide show
  1. package/.gitignore +23 -0
  2. package/LICENSE +201 -0
  3. package/dist/orbcharts-core.es.js +5096 -0
  4. package/dist/orbcharts-core.umd.js +3 -0
  5. package/dist/src/AbstractChart.d.ts +17 -0
  6. package/dist/src/GridChart.d.ts +6 -0
  7. package/dist/src/MultiGridChart.d.ts +6 -0
  8. package/dist/src/MultiValueChart.d.ts +6 -0
  9. package/dist/src/RelationshipChart.d.ts +6 -0
  10. package/dist/src/SeriesChart.d.ts +6 -0
  11. package/dist/src/TreeChart.d.ts +6 -0
  12. package/dist/src/base/createBaseChart.d.ts +3 -0
  13. package/dist/src/base/createBasePlugin.d.ts +3 -0
  14. package/dist/src/defaults.d.ts +37 -0
  15. package/dist/src/defineGridPlugin.d.ts +1 -0
  16. package/dist/src/defineMultiGridPlugin.d.ts +1 -0
  17. package/dist/src/defineMultiValuePlugin.d.ts +1 -0
  18. package/dist/src/defineNoneDataPlugin.d.ts +1 -0
  19. package/dist/src/defineRelationshipPlugin.d.ts +1 -0
  20. package/dist/src/defineSeriesPlugin.d.ts +1 -0
  21. package/dist/src/defineTreePlugin.d.ts +1 -0
  22. package/dist/src/grid/computeGridData.d.ts +3 -0
  23. package/dist/src/grid/createGridContextObserver.d.ts +3 -0
  24. package/dist/src/grid/gridObservables.d.ts +25 -0
  25. package/dist/src/index.d.ts +15 -0
  26. package/dist/src/multiGrid/computeMultiGridData.d.ts +3 -0
  27. package/dist/src/multiGrid/createMultiGridContextObserver.d.ts +3 -0
  28. package/dist/src/multiGrid/multiGridObservables.d.ts +0 -0
  29. package/dist/src/multiValue/computeMultiValueData.d.ts +3 -0
  30. package/dist/src/multiValue/createMultiValueContextObserver.d.ts +3 -0
  31. package/dist/src/multiValue/multiValueObservables.d.ts +0 -0
  32. package/dist/src/relationship/computeRelationshipData.d.ts +3 -0
  33. package/dist/src/relationship/createRelationshipContextObserver.d.ts +3 -0
  34. package/dist/src/relationship/relationshipObservables.d.ts +0 -0
  35. package/dist/src/series/computeSeriesData.d.ts +3 -0
  36. package/dist/src/series/createSeriesContextObserver.d.ts +3 -0
  37. package/dist/src/series/seriesObservables.d.ts +8 -0
  38. package/dist/src/tree/computeTreeData.d.ts +3 -0
  39. package/dist/src/tree/createTreeContextObserver.d.ts +3 -0
  40. package/dist/src/tree/treeObservables.d.ts +0 -0
  41. package/dist/src/types/Axis.d.ts +1 -0
  42. package/dist/src/types/Chart.d.ts +41 -0
  43. package/dist/src/types/ChartParams.d.ts +36 -0
  44. package/dist/src/types/ComputedData.d.ts +28 -0
  45. package/dist/src/types/ComputedDataGrid.d.ts +10 -0
  46. package/dist/src/types/ComputedDataMultiGrid.d.ts +3 -0
  47. package/dist/src/types/ComputedDataMultiValue.d.ts +6 -0
  48. package/dist/src/types/ComputedDataRelationship.d.ts +18 -0
  49. package/dist/src/types/ComputedDataSeries.d.ts +6 -0
  50. package/dist/src/types/ComputedDataTree.d.ts +7 -0
  51. package/dist/src/types/ContextObserver.d.ts +28 -0
  52. package/dist/src/types/ContextObserverGrid.d.ts +18 -0
  53. package/dist/src/types/ContextObserverMultiGrid.d.ts +4 -0
  54. package/dist/src/types/ContextObserverMultiValue.d.ts +4 -0
  55. package/dist/src/types/ContextObserverRelationship.d.ts +4 -0
  56. package/dist/src/types/ContextObserverSeries.d.ts +8 -0
  57. package/dist/src/types/ContextObserverTree.d.ts +4 -0
  58. package/dist/src/types/ContextSubject.d.ts +15 -0
  59. package/dist/src/types/Data.d.ts +19 -0
  60. package/dist/src/types/DataFormatter.d.ts +40 -0
  61. package/dist/src/types/DataFormatterGrid.d.ts +20 -0
  62. package/dist/src/types/DataFormatterMultiGrid.d.ts +16 -0
  63. package/dist/src/types/DataFormatterMultiValue.d.ts +13 -0
  64. package/dist/src/types/DataFormatterRelationship.d.ts +5 -0
  65. package/dist/src/types/DataFormatterSeries.d.ts +10 -0
  66. package/dist/src/types/DataFormatterTree.d.ts +5 -0
  67. package/dist/src/types/DataGrid.d.ts +6 -0
  68. package/dist/src/types/DataMultiGrid.d.ts +6 -0
  69. package/dist/src/types/DataMultiValue.d.ts +6 -0
  70. package/dist/src/types/DataRelationship.d.ts +20 -0
  71. package/dist/src/types/DataSeries.d.ts +6 -0
  72. package/dist/src/types/DataTree.d.ts +13 -0
  73. package/dist/src/types/Event.d.ts +64 -0
  74. package/dist/src/types/Layout.d.ts +8 -0
  75. package/dist/src/types/Padding.d.ts +6 -0
  76. package/dist/src/types/Plugin.d.ts +37 -0
  77. package/dist/src/types/TransformData.d.ts +8 -0
  78. package/dist/src/types/index.d.ts +37 -0
  79. package/dist/src/utils/commonUtils.d.ts +8 -0
  80. package/dist/src/utils/d3Utils.d.ts +25 -0
  81. package/dist/src/utils/index.d.ts +4 -0
  82. package/dist/src/utils/observables.d.ts +14 -0
  83. package/dist/src/utils/orbchartsUtils.d.ts +20 -0
  84. package/dist/vite.config.d.ts +2 -0
  85. package/package.json +40 -0
  86. package/src/AbstractChart.ts +48 -0
  87. package/src/GridChart.ts +21 -0
  88. package/src/MultiGridChart.ts +21 -0
  89. package/src/MultiValueChart.ts +21 -0
  90. package/src/RelationshipChart.ts +21 -0
  91. package/src/SeriesChart.ts +21 -0
  92. package/src/TreeChart.ts +21 -0
  93. package/src/base/createBaseChart.ts +329 -0
  94. package/src/base/createBasePlugin.ts +89 -0
  95. package/src/defaults.ts +229 -0
  96. package/src/defineGridPlugin.ts +3 -0
  97. package/src/defineMultiGridPlugin.ts +3 -0
  98. package/src/defineMultiValuePlugin.ts +3 -0
  99. package/src/defineNoneDataPlugin.ts +4 -0
  100. package/src/defineRelationshipPlugin.ts +3 -0
  101. package/src/defineSeriesPlugin.ts +3 -0
  102. package/src/defineTreePlugin.ts +3 -0
  103. package/src/grid/computeGridData.ts +192 -0
  104. package/src/grid/createGridContextObserver.ts +91 -0
  105. package/src/grid/gridObservables.ts +359 -0
  106. package/src/index.ts +21 -0
  107. package/src/multiGrid/computeMultiGridData.ts +48 -0
  108. package/src/multiGrid/createMultiGridContextObserver.ts +12 -0
  109. package/src/multiGrid/multiGridObservables.ts +0 -0
  110. package/src/multiValue/computeMultiValueData.ts +127 -0
  111. package/src/multiValue/createMultiValueContextObserver.ts +12 -0
  112. package/src/multiValue/multiValueObservables.ts +0 -0
  113. package/src/relationship/computeRelationshipData.ts +101 -0
  114. package/src/relationship/createRelationshipContextObserver.ts +12 -0
  115. package/src/relationship/relationshipObservables.ts +0 -0
  116. package/src/series/computeSeriesData.ts +154 -0
  117. package/src/series/createSeriesContextObserver.ts +33 -0
  118. package/src/series/seriesObservables.ts +23 -0
  119. package/src/tree/computeTreeData.ts +104 -0
  120. package/src/tree/createTreeContextObserver.ts +12 -0
  121. package/src/tree/treeObservables.ts +0 -0
  122. package/src/types/Axis.ts +1 -0
  123. package/src/types/Chart.ts +46 -0
  124. package/src/types/ChartParams.ts +50 -0
  125. package/src/types/ComputedData.ts +66 -0
  126. package/src/types/ComputedDataGrid.ts +12 -0
  127. package/src/types/ComputedDataMultiGrid.ts +3 -0
  128. package/src/types/ComputedDataMultiValue.ts +10 -0
  129. package/src/types/ComputedDataRelationship.ts +20 -0
  130. package/src/types/ComputedDataSeries.ts +8 -0
  131. package/src/types/ComputedDataTree.ts +20 -0
  132. package/src/types/ContextObserver.ts +38 -0
  133. package/src/types/ContextObserverGrid.ts +16 -0
  134. package/src/types/ContextObserverMultiGrid.ts +5 -0
  135. package/src/types/ContextObserverMultiValue.ts +5 -0
  136. package/src/types/ContextObserverRelationship.ts +5 -0
  137. package/src/types/ContextObserverSeries.ts +8 -0
  138. package/src/types/ContextObserverTree.ts +5 -0
  139. package/src/types/ContextSubject.ts +18 -0
  140. package/src/types/Data.ts +45 -0
  141. package/src/types/DataFormatter.ts +99 -0
  142. package/src/types/DataFormatterGrid.ts +40 -0
  143. package/src/types/DataFormatterMultiGrid.ts +23 -0
  144. package/src/types/DataFormatterMultiValue.ts +19 -0
  145. package/src/types/DataFormatterRelationship.ts +23 -0
  146. package/src/types/DataFormatterSeries.ts +26 -0
  147. package/src/types/DataFormatterTree.ts +10 -0
  148. package/src/types/DataGrid.ts +11 -0
  149. package/src/types/DataMultiGrid.ts +7 -0
  150. package/src/types/DataMultiValue.ts +11 -0
  151. package/src/types/DataRelationship.ts +27 -0
  152. package/src/types/DataSeries.ts +11 -0
  153. package/src/types/DataTree.ts +18 -0
  154. package/src/types/Event.ts +114 -0
  155. package/src/types/Layout.ts +12 -0
  156. package/src/types/Padding.ts +6 -0
  157. package/src/types/Plugin.ts +60 -0
  158. package/src/types/TransformData.ts +8 -0
  159. package/src/types/index.ts +37 -0
  160. package/src/utils/commonUtils.ts +50 -0
  161. package/src/utils/d3Utils.ts +87 -0
  162. package/src/utils/index.ts +4 -0
  163. package/src/utils/observables.ts +198 -0
  164. package/src/utils/orbchartsUtils.ts +150 -0
  165. package/tsconfig.json +14 -0
  166. package/vite.config.js +45 -0
@@ -0,0 +1,359 @@
1
+ import {
2
+ combineLatest,
3
+ distinctUntilChanged,
4
+ filter,
5
+ map,
6
+ merge,
7
+ takeUntil,
8
+ shareReplay,
9
+ switchMap,
10
+ Subject,
11
+ Observable } from 'rxjs'
12
+ import type {
13
+ AxisPosition,
14
+ ChartType,
15
+ ChartParams,
16
+ ComputedDataTypeMap,
17
+ ComputedDatumTypeMap,
18
+ ContextObserverFn,
19
+ DataTypeMap,
20
+ DataFormatterTypeMap,
21
+ DataFormatterGrid,
22
+ DataFormatterContext,
23
+ DataFormatterValueAxis,
24
+ DataFormatterGroupAxis,
25
+ HighlightTarget,
26
+ Layout,
27
+ TransformData } from '../types'
28
+ import { getMinAndMaxGrid, transposeData } from '../utils/orbchartsUtils'
29
+ import { createAxisLinearScale, createAxisPointScale, createAxisQuantizeScale } from '../utils/d3Utils'
30
+ import { highlightObservable } from '../utils/observables'
31
+
32
+ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
33
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
34
+ layout$: Observable<Layout>
35
+ }): Observable<TransformData> => {
36
+ const destroy$ = new Subject()
37
+
38
+ function calcAxesTransform ({ xAxis, yAxis, width, height }: {
39
+ xAxis: DataFormatterGroupAxis | DataFormatterValueAxis,
40
+ yAxis: DataFormatterValueAxis,
41
+ width: number,
42
+ height: number
43
+ }): TransformData {
44
+ if (!xAxis || !yAxis) {
45
+ return {
46
+ translate: [0, 0],
47
+ scale: [0, 0],
48
+ rotate: 0,
49
+ rotateX: 0,
50
+ rotateY: 0,
51
+ value: ''
52
+ }
53
+ }
54
+ // const width = size.width - fullChartParams.layout.left - fullChartParams.layout.right
55
+ // const height = size.height - fullChartParams.layout.top - fullChartParams.layout.bottom
56
+ let translateX = 0
57
+ let translateY = 0
58
+ let rotate = 0
59
+ let rotateX = 0
60
+ let rotateY = 0
61
+ if (xAxis.position === 'bottom') {
62
+ if (yAxis.position === 'left') {
63
+ rotateX = 180
64
+ translateY = height
65
+ } else if (yAxis.position === 'right') {
66
+ rotateX = 180
67
+ rotateY = 180
68
+ translateX = width
69
+ translateY = height
70
+ } else {
71
+ // 預設
72
+ rotateX = 180
73
+ translateY = height
74
+ }
75
+ } else if (xAxis.position === 'top') {
76
+ if (yAxis.position === 'left') {
77
+ } else if (yAxis.position === 'right') {
78
+ rotateY = 180
79
+ translateX = width
80
+ } else {
81
+ // 預設
82
+ rotateX = 180
83
+ translateY = height
84
+ }
85
+ } else if (xAxis.position === 'left') {
86
+ if (yAxis.position === 'bottom') {
87
+ rotate = -90
88
+ translateY = height
89
+ } else if (yAxis.position === 'top') {
90
+ rotate = -90
91
+ rotateY = 180
92
+ } else {
93
+ // 預設
94
+ rotateX = 180
95
+ translateY = height
96
+ }
97
+ } else if (xAxis.position === 'right') {
98
+ if (yAxis.position === 'bottom') {
99
+ rotate = -90
100
+ rotateX = 180
101
+ translateY = height
102
+ translateX = width
103
+ } else if (yAxis.position === 'top') {
104
+ rotate = -90
105
+ translateX = width
106
+ } else {
107
+ // 預設
108
+ rotateX = 180
109
+ translateY = height
110
+ }
111
+ }
112
+
113
+ // selection.style('transform', `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`)
114
+
115
+ return {
116
+ translate: [translateX, translateY],
117
+ scale: [0, 0],
118
+ rotate,
119
+ rotateX,
120
+ rotateY,
121
+ value: `translate(${translateX}px, ${translateY}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
122
+ }
123
+ }
124
+
125
+ return new Observable(subscriber => {
126
+ combineLatest({
127
+ fullDataFormatter: fullDataFormatter$,
128
+ layout: layout$
129
+ }).pipe(
130
+ takeUntil(destroy$)
131
+ ).subscribe(data => {
132
+ const axesTransformData = calcAxesTransform({
133
+ xAxis: data.fullDataFormatter.groupAxis,
134
+ yAxis: data.fullDataFormatter.valueAxis,
135
+ width: data.layout.width,
136
+ height: data.layout.height
137
+ })
138
+
139
+ subscriber.next(axesTransformData)
140
+ })
141
+
142
+ return function unscbscribe () {
143
+ destroy$.next(undefined)
144
+ }
145
+ })
146
+ }
147
+
148
+ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
149
+ computedData$: Observable<ComputedDataTypeMap<'grid'>>
150
+ fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
151
+ layout$: Observable<Layout>
152
+ }): Observable<TransformData> => {
153
+ const destroy$ = new Subject()
154
+
155
+ function calcGridDataAreaTransform ({ data, groupAxis, valueAxis, width, height }: {
156
+ data: ComputedDataTypeMap<'grid'>
157
+ groupAxis: DataFormatterGroupAxis
158
+ valueAxis: DataFormatterValueAxis
159
+ width: number
160
+ height: number
161
+ }): TransformData {
162
+ let translateX = 0
163
+ let translateY = 0
164
+ let scaleX = 0
165
+ let scaleY = 0
166
+
167
+ // -- groupScale --
168
+ const groupAxisWidth = (groupAxis.position === 'top' || groupAxis.position === 'bottom')
169
+ ? width
170
+ : height
171
+ const groupMin = 0
172
+ const groupMax = data[0] ? data[0].length - 1 : 0
173
+ const groupScaleDomainMin = groupAxis.scaleDomain[0] === 'auto'
174
+ ? groupMin - groupAxis.scalePadding
175
+ : groupAxis.scaleDomain[0] as number - groupAxis.scalePadding
176
+ const groupScaleDomainMax = groupAxis.scaleDomain[1] === 'auto'
177
+ ? groupMax + groupAxis.scalePadding
178
+ : groupAxis.scaleDomain[1] as number + groupAxis.scalePadding
179
+
180
+ const groupScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
181
+ maxValue: groupMax,
182
+ minValue: groupMin,
183
+ axisWidth: groupAxisWidth,
184
+ // scaleDomain: groupAxis.scaleDomain,
185
+ scaleDomain: [groupScaleDomainMin, groupScaleDomainMax],
186
+ scaleRange: [0, 1]
187
+ })
188
+
189
+ // -- translateX, scaleX --
190
+ const rangeMinX = groupScale(groupMin)
191
+ const rangeMaxX = groupScale(groupMax)
192
+ translateX = rangeMinX
193
+ const gWidth = rangeMaxX - rangeMinX
194
+ scaleX = gWidth / groupAxisWidth
195
+
196
+ // -- valueScale --
197
+ const filteredData = data.map((d, i) => {
198
+ return d.filter((_d, _i) => {
199
+ return _i >= groupScaleDomainMin && _i <= groupScaleDomainMax && _d.visible == true
200
+ })
201
+ })
202
+
203
+ const filteredMinAndMax = getMinAndMaxGrid(filteredData)
204
+
205
+ const valueAxisWidth = (valueAxis.position === 'left' || valueAxis.position === 'right')
206
+ ? height
207
+ : width
208
+
209
+ const valueScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
210
+ maxValue: filteredMinAndMax[1],
211
+ minValue: filteredMinAndMax[0],
212
+ axisWidth: valueAxisWidth,
213
+ scaleDomain: valueAxis.scaleDomain,
214
+ scaleRange: valueAxis.scaleRange
215
+ })
216
+
217
+ // -- translateY, scaleY --
218
+ const minAndMax = getMinAndMaxGrid(data)
219
+ const rangeMinY = valueScale(minAndMax[0])
220
+ const rangeMaxY = valueScale(minAndMax[1])
221
+ translateY = rangeMinY
222
+ const gHeight = rangeMaxY - rangeMinY
223
+ scaleY = gHeight / valueAxisWidth
224
+
225
+ return {
226
+ translate: [translateX, translateY],
227
+ scale: [scaleX, scaleY],
228
+ rotate: 0,
229
+ rotateX: 0,
230
+ rotateY: 0,
231
+ value: `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`
232
+ }
233
+ }
234
+
235
+ return new Observable(subscriber => {
236
+ combineLatest({
237
+ computedData: computedData$,
238
+ fullDataFormatter: fullDataFormatter$,
239
+ layout: layout$
240
+ }).pipe(
241
+ takeUntil(destroy$)
242
+ ).subscribe(data => {
243
+ const dataAreaTransformData = calcGridDataAreaTransform ({
244
+ data: data.computedData,
245
+ groupAxis: data.fullDataFormatter.groupAxis,
246
+ valueAxis: data.fullDataFormatter.valueAxis,
247
+ width: data.layout.width,
248
+ height: data.layout.height
249
+ })
250
+
251
+ subscriber.next(dataAreaTransformData)
252
+ })
253
+
254
+ return function unscbscribe () {
255
+ destroy$.next(undefined)
256
+ }
257
+ })
258
+ }
259
+
260
+ export const gridAxesOppositeTransformObservable = ({ gridAxesTransform$ }: {
261
+ gridAxesTransform$: Observable<TransformData>
262
+ }): Observable<TransformData> => {
263
+ return gridAxesTransform$.pipe(
264
+ map(d => {
265
+ // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
266
+ const translate: [number, number] = [0, 0] // 無需逆轉
267
+ const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
268
+ const rotate = d.rotate * -1
269
+ const rotateX = d.rotateX * -1
270
+ const rotateY = d.rotateY * -1
271
+ return {
272
+ translate,
273
+ scale,
274
+ rotate,
275
+ rotateX,
276
+ rotateY,
277
+ value: `translate(${translate[0]}px, ${translate[1]}px) rotate(${rotate}deg) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`
278
+ }
279
+ }),
280
+ )
281
+ }
282
+
283
+ export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
284
+ fullDataFormatter$: Observable<DataFormatterGrid>
285
+ layout$: Observable<Layout>
286
+ }): Observable<{
287
+ width: number;
288
+ height: number;
289
+ }> => {
290
+ const destroy$ = new Subject()
291
+
292
+ function calcAxesSize ({ xAxisPosition, yAxisPosition, width, height }: {
293
+ xAxisPosition: AxisPosition
294
+ yAxisPosition: AxisPosition
295
+ width: number
296
+ height: number
297
+ }) {
298
+ if ((xAxisPosition === 'bottom' || xAxisPosition === 'top') && (yAxisPosition === 'left' || yAxisPosition === 'right')) {
299
+ return { width, height }
300
+ } else if ((xAxisPosition === 'left' || xAxisPosition === 'right') && (yAxisPosition === 'bottom' || yAxisPosition === 'top')) {
301
+ return {
302
+ width: height,
303
+ height: width
304
+ }
305
+ }
306
+ }
307
+
308
+ return new Observable(subscriber => {
309
+ combineLatest({
310
+ fullDataFormatter: fullDataFormatter$,
311
+ layout: layout$
312
+ }).pipe(
313
+ takeUntil(destroy$),
314
+ // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
315
+ switchMap(async (d) => d),
316
+ ).subscribe(data => {
317
+
318
+ const axisSize = calcAxesSize({
319
+ xAxisPosition: data.fullDataFormatter.groupAxis.position,
320
+ yAxisPosition: data.fullDataFormatter.valueAxis.position,
321
+ width: data.layout.width,
322
+ height: data.layout.height,
323
+ })
324
+
325
+ subscriber.next(axisSize)
326
+
327
+ return function unsubscribe () {
328
+ destroy$.next(undefined)
329
+ }
330
+ })
331
+ })
332
+ }
333
+
334
+ // export const gridHighlightObservable = ({ computedData$, fullChartParams$, event$ }: {
335
+ // computedData$: Observable<ComputedDataTypeMap<'grid'>>
336
+ // fullChartParams$: Observable<ChartParams>
337
+ // event$: Subject<any>
338
+ // }): Observable<string[]> => {
339
+ // const datumList$ = computedData$.pipe(
340
+ // map(d => d.flat())
341
+ // )
342
+ // return highlightObservable ({ datumList$, fullChartParams$, event$ })
343
+ // }
344
+
345
+ export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
346
+ return computedData$.pipe(
347
+ map(data => {
348
+ const visibleComputedData = data
349
+ .map(d => {
350
+ return d.filter(_d => {
351
+ return _d.visible == true
352
+ })
353
+ })
354
+ .filter(d => d.length)
355
+ return visibleComputedData
356
+ })
357
+ )
358
+ }
359
+
package/src/index.ts ADDED
@@ -0,0 +1,21 @@
1
+
2
+ export { SeriesChart } from './SeriesChart'
3
+ export { GridChart } from './GridChart'
4
+ export { MultiGridChart } from './MultiGridChart'
5
+ export { MultiValueChart } from './MultiValueChart'
6
+ export { RelationshipChart } from './RelationshipChart'
7
+ export { TreeChart } from './TreeChart'
8
+
9
+ export { defineSeriesPlugin } from './defineSeriesPlugin'
10
+ export { defineGridPlugin } from './defineGridPlugin'
11
+ export { defineMultiGridPlugin } from './defineMultiGridPlugin'
12
+ export { defineMultiValuePlugin } from './defineMultiValuePlugin'
13
+ export { defineNoneDataPlugin } from './defineNoneDataPlugin'
14
+ export { defineRelationshipPlugin } from './defineRelationshipPlugin'
15
+ export { defineTreePlugin } from './defineTreePlugin'
16
+
17
+ export * from './types'
18
+ export * from './utils'
19
+
20
+
21
+
@@ -0,0 +1,48 @@
1
+ import type { ComputedDataFn } from '../types/ComputedData'
2
+ import type { DataFormatterGrid } from '../types/DataFormatterGrid'
3
+ import type { ComputedDataGrid } from '../types/ComputedDataGrid'
4
+ import { computeGridData } from '../grid/computeGridData'
5
+
6
+ export const computeMultiGridData: ComputedDataFn<'multiGrid'> = ({ data = [], dataFormatter, chartParams, layout }) => {
7
+ if (!data.length) {
8
+ return []
9
+ }
10
+
11
+ let multiGridData: ComputedDataGrid[] = []
12
+
13
+ try {
14
+ multiGridData = data.map((d, i) => {
15
+ const dataFormatterGrid: DataFormatterGrid = {
16
+ ...dataFormatter.multiGrid[i],
17
+ type: `multiGrid_${i}` as any, // 非規範的名稱,用作 datum id 前綴
18
+ // colors: dataFormatter.colors,
19
+ colorsPredicate: dataFormatter.multiGrid[i].colorsPredicate,
20
+ visibleFilter: dataFormatter.visibleFilter as any, // 用any避開function參數型別不同
21
+ // padding: dataFormatter.padding,
22
+ tooltipContentFormat: dataFormatter.tooltipContentFormat as any, // 用any避開function參數型別不同
23
+ }
24
+ // const layoutGrid: ComputedLayoutBase = {
25
+ // width: layout.width,
26
+ // height: layout.height,
27
+ // top: layout.top,
28
+ // right: layout.right,
29
+ // bottom: layout.bottom,
30
+ // left: layout.left,
31
+ // rootWidth: layout.rootWidth,
32
+ // rootHeight: layout.rootHeight,
33
+ // // content: layout.content[i]
34
+ // }
35
+ return computeGridData({
36
+ data: d,
37
+ dataFormatter: dataFormatterGrid,
38
+ chartParams,
39
+ layout
40
+ })
41
+ })
42
+ } catch (e) {
43
+ // console.error(e)
44
+ throw Error(e)
45
+ }
46
+
47
+ return multiGridData
48
+ }
@@ -0,0 +1,12 @@
1
+ import type { ContextObserverFn } from '../types'
2
+
3
+ export const createMultiGridContextObserver: ContextObserverFn<'multiGrid'> = ({ subject, observer }) => {
4
+
5
+ return {
6
+ fullParams$: observer.fullParams$,
7
+ fullChartParams$: observer.fullChartParams$,
8
+ fullDataFormatter$: observer.fullDataFormatter$,
9
+ computedData$: observer.computedData$,
10
+ layout$: observer.layout$,
11
+ }
12
+ }
File without changes
@@ -0,0 +1,127 @@
1
+ import type { DataMultiValue, DataMultiValueDatum } from '../types/DataMultiValue'
2
+ import type { DataFormatterContext } from '../types/DataFormatter'
3
+ import type { ComputedDataFn } from '../types/ComputedData'
4
+ import type { ComputedDataMultiValue, ComputedDatumMultiValue } from '../types/ComputedDataMultiValue'
5
+ import { formatValueToLabel, createDefaultDatumId } from '../utils/orbchartsUtils'
6
+ import { createAxisLinearScale, createAxisPointScale } from '../utils/d3Utils'
7
+ import { getMinAndMaxValue } from '../utils/orbchartsUtils'
8
+
9
+ export const computeMultiValueData: ComputedDataFn<'multiValue'> = (context) => {
10
+ const { data, dataFormatter, chartParams, layout } = context
11
+ if (!data.length) {
12
+ return []
13
+ }
14
+
15
+ let computedDataMultiValue: ComputedDatumMultiValue[][] = []
16
+
17
+ try {
18
+ const dataMultiValue: DataMultiValueDatum[][] = data.map((d, i) => {
19
+ return d.map((_d, _i) => {
20
+ const datum: DataMultiValueDatum = typeof _d === 'number'
21
+ ? {
22
+ id: '',
23
+ label: '',
24
+ tooltipContent: '',
25
+ data: {},
26
+ value: _d
27
+ }
28
+ : {
29
+ id: _d.id ?? '',
30
+ label: _d.label ?? '',
31
+ tooltipContent: _d.tooltipContent ?? '',
32
+ data: _d.data ?? {},
33
+ value: _d.value
34
+ }
35
+
36
+ return datum
37
+ })
38
+ })
39
+
40
+ // x軸資料最小及最大值(第二維陣列中的第1筆為x軸資料)
41
+ const [xMinValue, xMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[0]))
42
+ // y軸資料最小及最大值(第二維陣列中的第2筆為y軸資料)
43
+ const [yMinValue, yMaxValue] = getMinAndMaxValue(dataMultiValue.map(d => d[1]))
44
+
45
+ // const axisWidth = layout.width - dataFormatter.padding.left - dataFormatter.padding.right
46
+ // const axisHeight = layout.height - dataFormatter.padding.top - dataFormatter.padding.bottom
47
+ // const axisWidth = layout.width
48
+ // const axisHeight = layout.height
49
+ const xAxisWidth = (dataFormatter.xAxis.position === 'top' || dataFormatter.xAxis.position === 'bottom')
50
+ ? layout.width
51
+ : layout.height
52
+ const yAxisWidth = (dataFormatter.yAxis.position === 'left' || dataFormatter.yAxis.position === 'right')
53
+ ? layout.height
54
+ : layout.width
55
+
56
+ const xScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
57
+ maxValue: xMaxValue,
58
+ minValue: xMinValue,
59
+ axisWidth: xAxisWidth,
60
+ // scaleDomain: dataFormatter.xAxis.scaleDomain,
61
+ // scaleRange: dataFormatter.xAxis.scaleRange
62
+ scaleDomain: [xMinValue, xMaxValue],
63
+ scaleRange: [0, 1]
64
+ })
65
+ const yScale: d3.ScaleLinear<number, number> = createAxisLinearScale({
66
+ maxValue: yMaxValue,
67
+ minValue: yMinValue,
68
+ axisWidth: yAxisWidth,
69
+ // scaleDomain: dataFormatter.yAxis.scaleDomain,
70
+ // scaleRange: dataFormatter.yAxis.scaleRange
71
+ scaleDomain: [yMinValue, yMaxValue],
72
+ scaleRange: [0, 1]
73
+ })
74
+
75
+ const _xScaleDoamin: [number, number] = [
76
+ dataFormatter.xAxis.scaleDomain[0] === 'auto' ? xMinValue : dataFormatter.xAxis.scaleDomain[0],
77
+ dataFormatter.xAxis.scaleDomain[1] === 'auto' ? xMaxValue : dataFormatter.xAxis.scaleDomain[1]
78
+ ]
79
+ const _yScaleDoamin: [number, number] = [
80
+ dataFormatter.yAxis.scaleDomain[0] === 'auto' ? yMinValue : dataFormatter.yAxis.scaleDomain[0],
81
+ dataFormatter.yAxis.scaleDomain[1] === 'auto' ? yMaxValue : dataFormatter.yAxis.scaleDomain[1]
82
+ ]
83
+ // 篩選顯示狀態
84
+ const visibleFilter = (datum: DataMultiValueDatum, rowIndex: number, columnIndex: number, context: DataFormatterContext<"multiValue">) => {
85
+ // 如果不在scale的範圍內則為false,不再做visibleFilter的判斷
86
+ if (columnIndex === 0 && datum.value != null && ((datum.value as number) < _xScaleDoamin[0] || datum.value > _xScaleDoamin[1])) {
87
+ return false
88
+ }
89
+ if (columnIndex === 1 && datum.value != null && (datum.value < _yScaleDoamin[0] || datum.value > _yScaleDoamin[1])) {
90
+ return false
91
+ }
92
+
93
+ return dataFormatter.visibleFilter(datum, rowIndex, columnIndex, context)
94
+ }
95
+
96
+ let index = 0
97
+
98
+ computedDataMultiValue = dataMultiValue.map((d, i) => {
99
+ return d.map((_d, _i) => {
100
+ const currentIndex = index
101
+ index++
102
+
103
+ const defaultId = createDefaultDatumId(dataFormatter.type, i, _i)
104
+ // const visible = dataFormatter.visibleFilter(_d, i, _i, context)
105
+ const visible = visibleFilter(_d, i, _i, context)
106
+
107
+ const computedDatum: ComputedDatumMultiValue = {
108
+ id: _d.id ? _d.id : defaultId,
109
+ index: currentIndex,
110
+ label: _d.label ? _d.label : defaultId,
111
+ tooltipContent: _d.tooltipContent ? _d.tooltipContent : dataFormatter.tooltipContentFormat(_d, i, _i, context),
112
+ data: _d.data,
113
+ value: _d.value,
114
+ // valueLabel: formatValueToLabel(_d.value, dataFormatter.multiValue[_i].valueFormat),
115
+ axis: _i == 0 ? xScale(_d.value) : yScale(_d.value),
116
+ visible
117
+ }
118
+ return computedDatum
119
+ })
120
+ })
121
+ } catch (e) {
122
+ // console.error(e)
123
+ throw Error(e)
124
+ }
125
+
126
+ return computedDataMultiValue
127
+ }
@@ -0,0 +1,12 @@
1
+ import type { ContextObserverFn } from '../types'
2
+
3
+ export const createMultiValueContextObserver: ContextObserverFn<'multiValue'> = ({ subject, observer }) => {
4
+
5
+ return {
6
+ fullParams$: observer.fullParams$,
7
+ fullChartParams$: observer.fullChartParams$,
8
+ fullDataFormatter$: observer.fullDataFormatter$,
9
+ computedData$: observer.computedData$,
10
+ layout$: observer.layout$,
11
+ }
12
+ }
File without changes
@@ -0,0 +1,101 @@
1
+ import type { DataRelationship, DataRelationshipObj, DataRelationshipList, Node, Edge } from '../types/DataRelationship'
2
+ import type { ComputedDataFn } from '../types/ComputedData'
3
+ import type { ComputedDataRelationship, ComputedNode, ComputedEdge } from '../types/ComputedDataRelationship'
4
+
5
+ export const computeRelationshipData: ComputedDataFn<'relationship'> = (context) => {
6
+ const { data, dataFormatter, chartParams } = context
7
+
8
+ let computedNodes: ComputedNode[] = []
9
+ let computedEdges: ComputedEdge[] = []
10
+
11
+ try {
12
+ // -- 取得nodes和edges資料 --
13
+ let nodes: Node[] = []
14
+ let edges: Edge[] = []
15
+ if ((data as DataRelationshipObj).nodes) {
16
+ nodes = (data as DataRelationshipObj).nodes
17
+ edges = (data as DataRelationshipObj).edges
18
+ } else if ((data as DataRelationshipList)[0]) {
19
+ nodes = (data as DataRelationshipList)[0]
20
+ edges = (data as DataRelationshipList)[1]
21
+ } else {
22
+ // 無值直接回傳
23
+ return {
24
+ nodes: [],
25
+ edges: []
26
+ } as ComputedDataRelationship
27
+ }
28
+
29
+ // -- nodes --
30
+ computedNodes = nodes.map((node, i) => {
31
+ return {
32
+ id: node.id,
33
+ index: i,
34
+ label: node.label ?? '',
35
+ tooltipContent: node.tooltipContent ? node.tooltipContent : dataFormatter.tooltipContentFormat(node, 0, i, context), // 0代表node
36
+ data: node.data ?? {},
37
+ value: node.value ?? 0,
38
+ startNodes: [], // 後面再取得資料
39
+ startNodeIds: [], // 後面再取得資料
40
+ endNodes: [], // 後面再取得資料
41
+ endNodeIds: [], // 後面再取得資料
42
+ visible: dataFormatter.visibleFilter(node, 0, i, context) // 0代表node
43
+ }
44
+ })
45
+
46
+ const NodesMap: Map<string, ComputedNode> = new Map(computedNodes.map(d => [d.id, d]))
47
+
48
+ // -- edges --
49
+ computedEdges = edges.map((edge, i) => {
50
+ return {
51
+ id: edge.id,
52
+ index: i,
53
+ label: edge.label ?? '',
54
+ tooltipContent: edge.tooltipContent ? edge.tooltipContent : dataFormatter.tooltipContentFormat(edge, 1, i, context), // 1代表edge
55
+ data: edge.data ?? {},
56
+ value: edge.value ?? 0,
57
+ startNode: NodesMap.get(edge.start),
58
+ startNodeId: edge.start,
59
+ endNode: NodesMap.get(edge.end),
60
+ endNodeId: edge.end,
61
+ visible: dataFormatter.visibleFilter(edge, 1, i, context) // 1代表edge
62
+ }
63
+ })
64
+
65
+ const StartNodesMap: Map<string, ComputedNode[]> = (function () {
66
+ const _StartNodesMap = new Map()
67
+ computedEdges.forEach(edge => {
68
+ const startNodes: ComputedNode[] = _StartNodesMap.get(edge.endNodeId) ?? []
69
+ startNodes.push(edge.startNode)
70
+ _StartNodesMap.set(edge.endNodeId, startNodes)
71
+ })
72
+ return _StartNodesMap
73
+ })()
74
+
75
+ const EndNodesMap: Map<string, ComputedNode[]> = (function () {
76
+ const _EndNodesMap = new Map()
77
+ computedEdges.forEach(edge => {
78
+ const endNodes: ComputedNode[] = _EndNodesMap.get(edge.startNodeId) ?? []
79
+ endNodes.push(edge.endNode)
80
+ _EndNodesMap.set(edge.startNodeId, endNodes)
81
+ })
82
+ return _EndNodesMap
83
+ })()
84
+
85
+ // -- 補齊nodes資料 --
86
+ Array.from(NodesMap).forEach(([nodeId, node]) => {
87
+ node.startNodes = StartNodesMap.get(nodeId)
88
+ node.startNodeIds = node.startNodes.map(d => d.id)
89
+ node.endNodes = EndNodesMap.get(nodeId)
90
+ node.endNodeIds = node.endNodes.map(d => d.id)
91
+ })
92
+ } catch (e) {
93
+ // console.error(e)
94
+ throw Error(e)
95
+ }
96
+
97
+ return {
98
+ nodes: computedNodes,
99
+ edges: computedEdges
100
+ }
101
+ }