@orbcharts/core 3.0.0-alpha.68 → 3.0.0-beta.10
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.
- package/dist/orbcharts-core.es.js +3239 -2854
- package/dist/orbcharts-core.umd.js +4 -4
- package/dist/src/defaults.d.ts +24 -23
- package/dist/src/utils/d3Scale.d.ts +28 -0
- package/dist/src/utils/gridObservables.d.ts +29 -19
- package/dist/src/utils/index.d.ts +1 -1
- package/dist/src/utils/multiGridObservables.d.ts +2 -2
- package/dist/src/utils/multiValueObservables.d.ts +73 -0
- package/dist/src/utils/orbchartsUtils.d.ts +24 -10
- package/dist/src/utils/relationshipObservables.d.ts +13 -0
- package/dist/src/utils/seriesObservables.d.ts +4 -4
- package/dist/src/utils/treeObservables.d.ts +2 -5
- package/package.json +2 -2
- package/src/GridChart.ts +2 -2
- package/src/MultiGridChart.ts +2 -2
- package/src/MultiValueChart.ts +2 -2
- package/src/RelationshipChart.ts +2 -2
- package/src/SeriesChart.ts +2 -2
- package/src/TreeChart.ts +2 -2
- package/src/base/createBaseChart.ts +13 -13
- package/src/base/validators/chartParamsValidator.ts +6 -6
- package/src/defaults.ts +63 -47
- package/src/grid/computedDataFn.ts +4 -4
- package/src/grid/contextObserverCallback.ts +58 -37
- package/src/grid/dataFormatterValidator.ts +14 -14
- package/src/multiGrid/computedDataFn.ts +2 -2
- package/src/multiValue/computedDataFn.ts +81 -147
- package/src/multiValue/contextObserverCallback.ts +150 -2
- package/src/relationship/computedDataFn.ts +94 -60
- package/src/relationship/contextObserverCallback.ts +68 -0
- package/src/tree/computedDataFn.ts +9 -10
- package/src/tree/contextObserverCallback.ts +6 -9
- package/src/utils/d3Scale.ts +198 -0
- package/src/utils/gridObservables.ts +320 -248
- package/src/utils/index.ts +1 -1
- package/src/utils/multiGridObservables.ts +75 -49
- package/src/utils/multiValueObservables.ts +662 -0
- package/src/utils/observables.ts +30 -12
- package/src/utils/orbchartsUtils.ts +90 -65
- package/src/utils/relationshipObservables.ts +85 -0
- package/src/utils/seriesObservables.ts +7 -7
- package/src/utils/treeObservables.ts +44 -33
- package/src/utils/validator.ts +5 -4
- package/dist/src/utils/d3Utils.d.ts +0 -19
- package/src/utils/d3Utils.ts +0 -108
@@ -26,14 +26,14 @@ import type {
|
|
26
26
|
DataFormatterGroupAxis,
|
27
27
|
ComputedLayoutDatumGrid,
|
28
28
|
ComputedLayoutDataGrid,
|
29
|
-
|
29
|
+
ContainerPositionScaled,
|
30
30
|
HighlightTarget,
|
31
31
|
Layout,
|
32
32
|
TransformData } from '../../lib/core-types'
|
33
|
-
import {
|
34
|
-
import {
|
33
|
+
import { getMinMaxGrid } from './orbchartsUtils'
|
34
|
+
import { createValueToAxisScale, createLabelToAxisScale, createAxisToLabelIndexScale } from './d3Scale'
|
35
35
|
import { calcGridContainerLayout } from './orbchartsUtils'
|
36
|
-
import {
|
36
|
+
import { getMinMaxValue } from './orbchartsUtils'
|
37
37
|
|
38
38
|
export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
|
39
39
|
computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
@@ -41,36 +41,42 @@ export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormat
|
|
41
41
|
layout$: Observable<Layout>
|
42
42
|
}): Observable<ComputedLayoutDatumGrid[][]> => {
|
43
43
|
|
44
|
-
// 未篩選group範圍前的group scale
|
44
|
+
// 未篩選group範圍前的group scale( * 不受到dataFormatter設定影響)
|
45
45
|
function createOriginGroupScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
|
46
|
-
const groupAxisWidth = (dataFormatter.
|
46
|
+
const groupAxisWidth = (dataFormatter.groupAxis.position === 'top' || dataFormatter.groupAxis.position === 'bottom')
|
47
47
|
? layout.width
|
48
48
|
: layout.height
|
49
49
|
const groupEndIndex = computedData[0] ? computedData[0].length - 1 : 0
|
50
|
-
const groupScale: d3.ScaleLinear<number, number> =
|
50
|
+
const groupScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
|
51
51
|
maxValue: groupEndIndex,
|
52
52
|
minValue: 0,
|
53
53
|
axisWidth: groupAxisWidth,
|
54
54
|
scaleDomain: [0, groupEndIndex], // 不使用dataFormatter設定
|
55
55
|
scaleRange: [0, 1] // 不使用dataFormatter設定
|
56
56
|
})
|
57
|
+
|
57
58
|
return groupScale
|
58
59
|
}
|
59
60
|
|
60
|
-
// 未篩選group範圍及visible前的value scale
|
61
|
+
// 未篩選group範圍及visible前的value scale( * 不受到dataFormatter設定影響)
|
61
62
|
function createOriginValueScale (computedData: ComputedDatumGrid[][], dataFormatter: DataFormatterGrid, layout: Layout) {
|
62
|
-
const valueAxisWidth = (dataFormatter.
|
63
|
+
const valueAxisWidth = (dataFormatter.valueAxis.position === 'left' || dataFormatter.valueAxis.position === 'right')
|
63
64
|
? layout.height
|
64
65
|
: layout.width
|
65
66
|
|
66
67
|
const listData = computedData.flat()
|
67
|
-
|
68
|
+
let [minValue, maxValue] = getMinMaxValue(listData)
|
69
|
+
if (minValue === maxValue && maxValue === 0) {
|
70
|
+
// 避免最大及最小值相同造成無法計算scale
|
71
|
+
maxValue = 1
|
72
|
+
}
|
68
73
|
|
69
|
-
const valueScale: d3.ScaleLinear<number, number> =
|
74
|
+
const valueScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
|
70
75
|
maxValue,
|
71
76
|
minValue,
|
72
77
|
axisWidth: valueAxisWidth,
|
73
|
-
scaleDomain: [minValue, maxValue], // 不使用dataFormatter設定
|
78
|
+
// scaleDomain: [minValue, maxValue], // 不使用dataFormatter設定
|
79
|
+
scaleDomain: ['auto', 'auto'], // 不使用dataFormatter設定 --> 以0為基準到最大或最小值為範圍( * 如果是使用[minValue, maxValue]的話,在兩者很接近的情況下有可能造成scale倍率過高而svg變型時失真的情況)
|
74
80
|
scaleRange: [0, 1] // 不使用dataFormatter設定
|
75
81
|
})
|
76
82
|
|
@@ -104,6 +110,261 @@ export const gridComputedLayoutDataObservable = ({ computedData$, fullDataFormat
|
|
104
110
|
)
|
105
111
|
}
|
106
112
|
|
113
|
+
export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
|
114
|
+
fullDataFormatter$: Observable<DataFormatterGrid>
|
115
|
+
layout$: Observable<Layout>
|
116
|
+
}): Observable<{
|
117
|
+
width: number;
|
118
|
+
height: number;
|
119
|
+
}> => {
|
120
|
+
const destroy$ = new Subject()
|
121
|
+
|
122
|
+
function calcAxesSize ({ xAxisPosition, yAxisPosition, width, height }: {
|
123
|
+
xAxisPosition: AxisPosition
|
124
|
+
yAxisPosition: AxisPosition
|
125
|
+
width: number
|
126
|
+
height: number
|
127
|
+
}) {
|
128
|
+
if ((xAxisPosition === 'bottom' || xAxisPosition === 'top') && (yAxisPosition === 'left' || yAxisPosition === 'right')) {
|
129
|
+
return { width, height }
|
130
|
+
} else if ((xAxisPosition === 'left' || xAxisPosition === 'right') && (yAxisPosition === 'bottom' || yAxisPosition === 'top')) {
|
131
|
+
return {
|
132
|
+
width: height,
|
133
|
+
height: width
|
134
|
+
}
|
135
|
+
} else {
|
136
|
+
// default
|
137
|
+
return { width, height }
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
return new Observable(subscriber => {
|
142
|
+
combineLatest({
|
143
|
+
fullDataFormatter: fullDataFormatter$,
|
144
|
+
layout: layout$
|
145
|
+
}).pipe(
|
146
|
+
takeUntil(destroy$),
|
147
|
+
switchMap(async (d) => d),
|
148
|
+
).subscribe(data => {
|
149
|
+
|
150
|
+
const axisSize = calcAxesSize({
|
151
|
+
xAxisPosition: data.fullDataFormatter.groupAxis.position,
|
152
|
+
yAxisPosition: data.fullDataFormatter.valueAxis.position,
|
153
|
+
width: data.layout.width,
|
154
|
+
height: data.layout.height,
|
155
|
+
})
|
156
|
+
|
157
|
+
subscriber.next(axisSize)
|
158
|
+
|
159
|
+
return function unsubscribe () {
|
160
|
+
destroy$.next(undefined)
|
161
|
+
}
|
162
|
+
})
|
163
|
+
})
|
164
|
+
}
|
165
|
+
|
166
|
+
// export const gridHighlightObservable = ({ computedData$, fullChartParams$, event$ }: {
|
167
|
+
// computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
168
|
+
// fullChartParams$: Observable<ChartParams>
|
169
|
+
// event$: Subject<any>
|
170
|
+
// }): Observable<string[]> => {
|
171
|
+
// const datumList$ = computedData$.pipe(
|
172
|
+
// map(d => d.flat())
|
173
|
+
// )
|
174
|
+
// return highlightObservable ({ datumList$, fullChartParams$, event$ })
|
175
|
+
// }
|
176
|
+
|
177
|
+
export const gridSeriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
|
178
|
+
return computedData$.pipe(
|
179
|
+
map(data => {
|
180
|
+
return data
|
181
|
+
.filter(series => series.length)
|
182
|
+
.map(series => {
|
183
|
+
return series[0].seriesLabel
|
184
|
+
})
|
185
|
+
}),
|
186
|
+
distinctUntilChanged((a, b) => {
|
187
|
+
return JSON.stringify(a).length === JSON.stringify(b).length
|
188
|
+
}),
|
189
|
+
)
|
190
|
+
}
|
191
|
+
|
192
|
+
export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
|
193
|
+
return computedData$.pipe(
|
194
|
+
map(data => {
|
195
|
+
const visibleComputedData = data
|
196
|
+
.map(d => {
|
197
|
+
return d.filter(_d => {
|
198
|
+
return _d.visible == true
|
199
|
+
})
|
200
|
+
})
|
201
|
+
.filter(d => d.length)
|
202
|
+
return visibleComputedData
|
203
|
+
})
|
204
|
+
)
|
205
|
+
}
|
206
|
+
|
207
|
+
export const gridVisibleComputedLayoutDataObservable = ({ computedLayoutData$ }: { computedLayoutData$: Observable<ComputedLayoutDataGrid> }) => {
|
208
|
+
return computedLayoutData$.pipe(
|
209
|
+
map(data => {
|
210
|
+
const visibleComputedData = data
|
211
|
+
.map(d => {
|
212
|
+
return d.filter(_d => {
|
213
|
+
return _d.visible == true
|
214
|
+
})
|
215
|
+
})
|
216
|
+
.filter(d => d.length)
|
217
|
+
return visibleComputedData
|
218
|
+
})
|
219
|
+
)
|
220
|
+
}
|
221
|
+
|
222
|
+
// 所有container位置(對應series)
|
223
|
+
export const gridContainerPositionObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
|
224
|
+
computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
225
|
+
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
226
|
+
layout$: Observable<Layout>
|
227
|
+
}): Observable<ContainerPositionScaled[]> => {
|
228
|
+
|
229
|
+
const gridContainerPosition$ = combineLatest({
|
230
|
+
computedData: computedData$,
|
231
|
+
fullDataFormatter: fullDataFormatter$,
|
232
|
+
layout: layout$,
|
233
|
+
}).pipe(
|
234
|
+
switchMap(async (d) => d),
|
235
|
+
map(data => {
|
236
|
+
|
237
|
+
if (data.fullDataFormatter.separateSeries) {
|
238
|
+
// -- 依slotIndexes計算 --
|
239
|
+
return calcGridContainerLayout(data.layout, data.fullDataFormatter.container, data.computedData.length)
|
240
|
+
// return data.computedData.map((seriesData, seriesIndex) => {
|
241
|
+
// const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
|
242
|
+
// const rowIndex = Math.floor(seriesIndex / data.fullDataFormatter.container.columnAmount)
|
243
|
+
// const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
244
|
+
// return {
|
245
|
+
// slotIndex: seriesIndex,
|
246
|
+
// rowIndex,
|
247
|
+
// columnIndex,
|
248
|
+
// translate,
|
249
|
+
// scale,
|
250
|
+
// }
|
251
|
+
// })
|
252
|
+
} else {
|
253
|
+
// -- 無拆分 --
|
254
|
+
const gridContainerPositionArr = calcGridContainerLayout(data.layout, data.fullDataFormatter.container, 1)
|
255
|
+
return data.computedData.map((d, i) => gridContainerPositionArr[0]) // 每個series相同位置
|
256
|
+
// const columnIndex = 0
|
257
|
+
// const rowIndex = 0
|
258
|
+
// return data.computedData.map((seriesData, seriesIndex) => {
|
259
|
+
// const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
260
|
+
// return {
|
261
|
+
// slotIndex: 0,
|
262
|
+
// rowIndex,
|
263
|
+
// columnIndex,
|
264
|
+
// translate,
|
265
|
+
// scale,
|
266
|
+
// }
|
267
|
+
// })
|
268
|
+
}
|
269
|
+
})
|
270
|
+
)
|
271
|
+
|
272
|
+
return gridContainerPosition$
|
273
|
+
}
|
274
|
+
|
275
|
+
// 將原本的value全部替換成加總後的value
|
276
|
+
export const computedStackedDataObservables = ({ isSeriesSeprate$, computedData$ }: {
|
277
|
+
isSeriesSeprate$: Observable<boolean>
|
278
|
+
computedData$: Observable<ComputedDataGrid>
|
279
|
+
}): Observable<ComputedDataGrid> => {
|
280
|
+
const stackedData$: Observable<ComputedDataGrid> = computedData$.pipe(
|
281
|
+
map(data => {
|
282
|
+
// 將同一group的value加總起來
|
283
|
+
const stackedValue = new Array(data[0] ? data[0].length : 0)
|
284
|
+
.fill(null)
|
285
|
+
.map((_, i) => {
|
286
|
+
return data.reduce((prev, current) => {
|
287
|
+
if (current && current[i]) {
|
288
|
+
const currentValue = current[i].value == null || current[i].visible == false
|
289
|
+
? 0
|
290
|
+
: current[i].value!
|
291
|
+
return prev + currentValue
|
292
|
+
}
|
293
|
+
return prev
|
294
|
+
}, 0)
|
295
|
+
})
|
296
|
+
// 將原本的value全部替換成加總後的value
|
297
|
+
const computedData = data.map((series, seriesIndex) => {
|
298
|
+
return series.map((d, i) => {
|
299
|
+
return {
|
300
|
+
...d,
|
301
|
+
value: stackedValue[i],
|
302
|
+
}
|
303
|
+
})
|
304
|
+
})
|
305
|
+
return computedData
|
306
|
+
}),
|
307
|
+
)
|
308
|
+
|
309
|
+
return isSeriesSeprate$.pipe(
|
310
|
+
switchMap(isSeriesSeprate => {
|
311
|
+
return iif(() => isSeriesSeprate, computedData$, stackedData$)
|
312
|
+
})
|
313
|
+
)
|
314
|
+
}
|
315
|
+
|
316
|
+
export const groupScaleDomainValueObservable = ({ computedData$, fullDataFormatter$ }: {
|
317
|
+
computedData$: Observable<ComputedDataGrid>
|
318
|
+
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
319
|
+
}): Observable<[number, number]> => {
|
320
|
+
return combineLatest({
|
321
|
+
computedData: computedData$,
|
322
|
+
fullDataFormatter: fullDataFormatter$
|
323
|
+
}).pipe(
|
324
|
+
switchMap(async (d) => d),
|
325
|
+
map(data => {
|
326
|
+
const groupAxis = data.fullDataFormatter.groupAxis
|
327
|
+
const groupMin = 0
|
328
|
+
const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
|
329
|
+
// const groupScaleDomainMin = groupAxis.scaleDomain[0] === 'min'
|
330
|
+
// ? groupMin - groupAxis.scalePadding
|
331
|
+
// : groupAxis.scaleDomain[0] as number - groupAxis.scalePadding
|
332
|
+
const groupScaleDomainMin = groupAxis.scaleDomain[0] - groupAxis.scalePadding
|
333
|
+
const groupScaleDomainMax = groupAxis.scaleDomain[1] === 'max'
|
334
|
+
? groupMax + groupAxis.scalePadding
|
335
|
+
: groupAxis.scaleDomain[1] as number + groupAxis.scalePadding
|
336
|
+
|
337
|
+
return [groupScaleDomainMin, groupScaleDomainMax]
|
338
|
+
})
|
339
|
+
)
|
340
|
+
}
|
341
|
+
|
342
|
+
export const filteredMinMaxValueObservable = ({ computedData$, groupScaleDomainValue$ }: {
|
343
|
+
computedData$: Observable<ComputedDataGrid>
|
344
|
+
// fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
345
|
+
groupScaleDomainValue$: Observable<[number, number]>
|
346
|
+
}) => {
|
347
|
+
return combineLatest({
|
348
|
+
computedData: computedData$,
|
349
|
+
// fullDataFormatter: fullDataFormatter$,
|
350
|
+
groupScaleDomainValue: groupScaleDomainValue$
|
351
|
+
}).pipe(
|
352
|
+
map(data => {
|
353
|
+
const filteredData = data.computedData.map((d, i) => {
|
354
|
+
return d.filter((_d, _i) => {
|
355
|
+
return _i >= data.groupScaleDomainValue[0] && _i <= data.groupScaleDomainValue[1] && _d.visible == true
|
356
|
+
})
|
357
|
+
})
|
358
|
+
|
359
|
+
const filteredMinMax = getMinMaxGrid(filteredData)
|
360
|
+
// if (filteredMinMax[0] === filteredMinMax[1]) {
|
361
|
+
// filteredMinMax[0] = filteredMinMax[1] - 1 // 避免最大及最小值相同造成無法計算scale
|
362
|
+
// }
|
363
|
+
return filteredMinMax
|
364
|
+
}),
|
365
|
+
)
|
366
|
+
}
|
367
|
+
|
107
368
|
export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
108
369
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
109
370
|
layout$: Observable<Layout>
|
@@ -211,8 +472,8 @@ export const gridAxesTransformObservable = ({ fullDataFormatter$, layout$ }: {
|
|
211
472
|
switchMap(async (d) => d),
|
212
473
|
).subscribe(data => {
|
213
474
|
const axesTransformData = calcAxesTransform({
|
214
|
-
xAxis: data.fullDataFormatter.
|
215
|
-
yAxis: data.fullDataFormatter.
|
475
|
+
xAxis: data.fullDataFormatter.groupAxis,
|
476
|
+
yAxis: data.fullDataFormatter.valueAxis,
|
216
477
|
width: data.layout.width,
|
217
478
|
height: data.layout.height
|
218
479
|
})
|
@@ -250,17 +511,21 @@ export const gridAxesReverseTransformObservable = ({ gridAxesTransform$ }: {
|
|
250
511
|
)
|
251
512
|
}
|
252
513
|
|
253
|
-
export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
|
514
|
+
export const gridGraphicTransformObservable = ({ computedData$, groupScaleDomainValue$, filteredMinMaxValue$, fullDataFormatter$, layout$ }: {
|
254
515
|
computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
516
|
+
groupScaleDomainValue$: Observable<[number, number]>
|
517
|
+
filteredMinMaxValue$: Observable<[number, number]>
|
255
518
|
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
256
519
|
layout$: Observable<Layout>
|
257
520
|
}): Observable<TransformData> => {
|
258
521
|
const destroy$ = new Subject()
|
259
522
|
|
260
|
-
function calcGridDataAreaTransform ({ data, groupAxis, valueAxis, width, height }: {
|
523
|
+
function calcGridDataAreaTransform ({ data, groupAxis, valueAxis, groupScaleDomainValue, filteredMinMaxValue, width, height }: {
|
261
524
|
data: ComputedDataTypeMap<'grid'>
|
262
525
|
groupAxis: DataFormatterGroupAxis
|
263
526
|
valueAxis: DataFormatterValueAxis
|
527
|
+
groupScaleDomainValue: [number, number],
|
528
|
+
filteredMinMaxValue: [number, number],
|
264
529
|
width: number
|
265
530
|
height: number
|
266
531
|
}): TransformData {
|
@@ -275,20 +540,17 @@ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatte
|
|
275
540
|
: height
|
276
541
|
const groupMin = 0
|
277
542
|
const groupMax = data[0] ? data[0].length - 1 : 0
|
278
|
-
// const groupScaleDomainMin = groupAxis.scaleDomain[0]
|
279
|
-
//
|
280
|
-
//
|
281
|
-
|
282
|
-
const groupScaleDomainMax = groupAxis.scaleDomain[1] === 'max'
|
283
|
-
? groupMax + groupAxis.scalePadding
|
284
|
-
: groupAxis.scaleDomain[1] as number + groupAxis.scalePadding
|
543
|
+
// const groupScaleDomainMin = groupAxis.scaleDomain[0] - groupAxis.scalePadding
|
544
|
+
// const groupScaleDomainMax = groupAxis.scaleDomain[1] === 'max'
|
545
|
+
// ? groupMax + groupAxis.scalePadding
|
546
|
+
// : groupAxis.scaleDomain[1] as number + groupAxis.scalePadding
|
285
547
|
|
286
|
-
const groupScale: d3.ScaleLinear<number, number> =
|
548
|
+
const groupScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
|
287
549
|
maxValue: groupMax,
|
288
550
|
minValue: groupMin,
|
289
551
|
axisWidth: groupAxisWidth,
|
290
552
|
// scaleDomain: groupAxis.scaleDomain,
|
291
|
-
scaleDomain:
|
553
|
+
scaleDomain: groupScaleDomainValue,
|
292
554
|
scaleRange: [0, 1]
|
293
555
|
})
|
294
556
|
|
@@ -306,36 +568,45 @@ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatte
|
|
306
568
|
}
|
307
569
|
|
308
570
|
// -- valueScale --
|
309
|
-
const filteredData = data.map((d, i) => {
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
})
|
571
|
+
// const filteredData = data.map((d, i) => {
|
572
|
+
// return d.filter((_d, _i) => {
|
573
|
+
// return _i >= groupScaleDomainMin && _i <= groupScaleDomainMax && _d.visible == true
|
574
|
+
// })
|
575
|
+
// })
|
314
576
|
|
315
|
-
const
|
316
|
-
if (
|
317
|
-
|
577
|
+
// const filteredMinMax = getMinMaxGrid(filteredData)
|
578
|
+
if (filteredMinMaxValue[0] === filteredMinMaxValue[1] && filteredMinMaxValue[1] === 0) {
|
579
|
+
// filteredMinMaxValue[0] = filteredMinMaxValue[1] - 1 // 避免最大及最小值相同造成無法計算scale
|
580
|
+
filteredMinMaxValue[1] = 1 // 避免最大及最小值同等於 0 造成無法計算scale
|
318
581
|
}
|
319
582
|
|
320
583
|
const valueAxisWidth = (valueAxis.position === 'left' || valueAxis.position === 'right')
|
321
584
|
? height
|
322
585
|
: width
|
323
586
|
|
324
|
-
const valueScale: d3.ScaleLinear<number, number> =
|
325
|
-
maxValue:
|
326
|
-
minValue:
|
587
|
+
const valueScale: d3.ScaleLinear<number, number> = createValueToAxisScale({
|
588
|
+
maxValue: filteredMinMaxValue[1],
|
589
|
+
minValue: filteredMinMaxValue[0],
|
327
590
|
axisWidth: valueAxisWidth,
|
328
591
|
scaleDomain: valueAxis.scaleDomain,
|
329
592
|
scaleRange: valueAxis.scaleRange
|
330
593
|
})
|
331
|
-
|
594
|
+
// console.log({
|
595
|
+
// maxValue: filteredMinMaxValue[1],
|
596
|
+
// minValue: filteredMinMaxValue[0],
|
597
|
+
// axisWidth: valueAxisWidth,
|
598
|
+
// scaleDomain: valueAxis.scaleDomain,
|
599
|
+
// scaleRange: valueAxis.scaleRange
|
600
|
+
// })
|
332
601
|
// -- translateY, scaleY --
|
333
|
-
const
|
334
|
-
if (
|
335
|
-
|
602
|
+
const minMax = getMinMaxGrid(data)
|
603
|
+
if (minMax[0] === minMax[1] && minMax[1] === 0) {
|
604
|
+
// minMax[0] = minMax[1] - 1 // 避免最大及最小值相同造成無法計算scale
|
605
|
+
minMax[1] = 1 // 避免最大及最小值同等於 0 造成無法計算scale
|
336
606
|
}
|
337
|
-
const rangeMinY = valueScale(
|
338
|
-
const
|
607
|
+
// const rangeMinY = valueScale(minMax[0])
|
608
|
+
const rangeMinY = valueScale(minMax[0] > 0 ? 0 : minMax[0]) // * 因為原本的座標就是以 0 到最大值或最小值範範圍計算的,所以這邊也是用同樣的方式計算
|
609
|
+
const rangeMaxY = valueScale(minMax[1] < 0 ? 0 : minMax[1]) // * 因為原本的座標就是以 0 到最大值或最小值範範圍計算的,所以這邊也是用同樣的方式計算
|
339
610
|
translateY = rangeMinY
|
340
611
|
const gHeight = rangeMaxY - rangeMinY
|
341
612
|
scaleY = gHeight / valueAxisWidth
|
@@ -353,6 +624,8 @@ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatte
|
|
353
624
|
return new Observable(subscriber => {
|
354
625
|
combineLatest({
|
355
626
|
computedData: computedData$,
|
627
|
+
groupScaleDomainValue: groupScaleDomainValue$,
|
628
|
+
filteredMinMaxValue: filteredMinMaxValue$,
|
356
629
|
fullDataFormatter: fullDataFormatter$,
|
357
630
|
layout: layout$
|
358
631
|
}).pipe(
|
@@ -361,8 +634,10 @@ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatte
|
|
361
634
|
).subscribe(data => {
|
362
635
|
const dataAreaTransformData = calcGridDataAreaTransform ({
|
363
636
|
data: data.computedData,
|
364
|
-
groupAxis: data.fullDataFormatter.
|
365
|
-
valueAxis: data.fullDataFormatter.
|
637
|
+
groupAxis: data.fullDataFormatter.groupAxis,
|
638
|
+
valueAxis: data.fullDataFormatter.valueAxis,
|
639
|
+
groupScaleDomainValue: data.groupScaleDomainValue,
|
640
|
+
filteredMinMaxValue: data.filteredMinMaxValue,
|
366
641
|
width: data.layout.width,
|
367
642
|
height: data.layout.height
|
368
643
|
})
|
@@ -377,7 +652,7 @@ export const gridGraphicTransformObservable = ({ computedData$, fullDataFormatte
|
|
377
652
|
}
|
378
653
|
|
379
654
|
export const gridGraphicReverseScaleObservable = ({ gridContainerPosition$, gridAxesTransform$, gridGraphicTransform$ }: {
|
380
|
-
gridContainerPosition$: Observable<
|
655
|
+
gridContainerPosition$: Observable<ContainerPositionScaled[]>
|
381
656
|
gridAxesTransform$: Observable<TransformData>
|
382
657
|
gridGraphicTransform$: Observable<TransformData>
|
383
658
|
}): Observable<[number, number][]> => {
|
@@ -406,207 +681,4 @@ export const gridGraphicReverseScaleObservable = ({ gridContainerPosition$, grid
|
|
406
681
|
}
|
407
682
|
}),
|
408
683
|
)
|
409
|
-
}
|
410
|
-
|
411
|
-
export const gridAxesSizeObservable = ({ fullDataFormatter$, layout$ }: {
|
412
|
-
fullDataFormatter$: Observable<DataFormatterGrid>
|
413
|
-
layout$: Observable<Layout>
|
414
|
-
}): Observable<{
|
415
|
-
width: number;
|
416
|
-
height: number;
|
417
|
-
}> => {
|
418
|
-
const destroy$ = new Subject()
|
419
|
-
|
420
|
-
function calcAxesSize ({ xAxisPosition, yAxisPosition, width, height }: {
|
421
|
-
xAxisPosition: AxisPosition
|
422
|
-
yAxisPosition: AxisPosition
|
423
|
-
width: number
|
424
|
-
height: number
|
425
|
-
}) {
|
426
|
-
if ((xAxisPosition === 'bottom' || xAxisPosition === 'top') && (yAxisPosition === 'left' || yAxisPosition === 'right')) {
|
427
|
-
return { width, height }
|
428
|
-
} else if ((xAxisPosition === 'left' || xAxisPosition === 'right') && (yAxisPosition === 'bottom' || yAxisPosition === 'top')) {
|
429
|
-
return {
|
430
|
-
width: height,
|
431
|
-
height: width
|
432
|
-
}
|
433
|
-
} else {
|
434
|
-
// default
|
435
|
-
return { width, height }
|
436
|
-
}
|
437
|
-
}
|
438
|
-
|
439
|
-
return new Observable(subscriber => {
|
440
|
-
combineLatest({
|
441
|
-
fullDataFormatter: fullDataFormatter$,
|
442
|
-
layout: layout$
|
443
|
-
}).pipe(
|
444
|
-
takeUntil(destroy$),
|
445
|
-
switchMap(async (d) => d),
|
446
|
-
).subscribe(data => {
|
447
|
-
|
448
|
-
const axisSize = calcAxesSize({
|
449
|
-
xAxisPosition: data.fullDataFormatter.grid.groupAxis.position,
|
450
|
-
yAxisPosition: data.fullDataFormatter.grid.valueAxis.position,
|
451
|
-
width: data.layout.width,
|
452
|
-
height: data.layout.height,
|
453
|
-
})
|
454
|
-
|
455
|
-
subscriber.next(axisSize)
|
456
|
-
|
457
|
-
return function unsubscribe () {
|
458
|
-
destroy$.next(undefined)
|
459
|
-
}
|
460
|
-
})
|
461
|
-
})
|
462
|
-
}
|
463
|
-
|
464
|
-
// export const gridHighlightObservable = ({ computedData$, fullChartParams$, event$ }: {
|
465
|
-
// computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
466
|
-
// fullChartParams$: Observable<ChartParams>
|
467
|
-
// event$: Subject<any>
|
468
|
-
// }): Observable<string[]> => {
|
469
|
-
// const datumList$ = computedData$.pipe(
|
470
|
-
// map(d => d.flat())
|
471
|
-
// )
|
472
|
-
// return highlightObservable ({ datumList$, fullChartParams$, event$ })
|
473
|
-
// }
|
474
|
-
|
475
|
-
export const gridSeriesLabelsObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
|
476
|
-
return computedData$.pipe(
|
477
|
-
map(data => {
|
478
|
-
return data
|
479
|
-
.filter(series => series.length)
|
480
|
-
.map(series => {
|
481
|
-
return series[0].seriesLabel
|
482
|
-
})
|
483
|
-
}),
|
484
|
-
distinctUntilChanged((a, b) => {
|
485
|
-
return JSON.stringify(a).length === JSON.stringify(b).length
|
486
|
-
}),
|
487
|
-
)
|
488
|
-
}
|
489
|
-
|
490
|
-
export const gridVisibleComputedDataObservable = ({ computedData$ }: { computedData$: Observable<ComputedDataTypeMap<'grid'>> }) => {
|
491
|
-
return computedData$.pipe(
|
492
|
-
map(data => {
|
493
|
-
const visibleComputedData = data
|
494
|
-
.map(d => {
|
495
|
-
return d.filter(_d => {
|
496
|
-
return _d.visible == true
|
497
|
-
})
|
498
|
-
})
|
499
|
-
.filter(d => d.length)
|
500
|
-
return visibleComputedData
|
501
|
-
})
|
502
|
-
)
|
503
|
-
}
|
504
|
-
|
505
|
-
export const gridVisibleComputedLayoutDataObservable = ({ computedLayoutData$ }: { computedLayoutData$: Observable<ComputedLayoutDataGrid> }) => {
|
506
|
-
return computedLayoutData$.pipe(
|
507
|
-
map(data => {
|
508
|
-
const visibleComputedData = data
|
509
|
-
.map(d => {
|
510
|
-
return d.filter(_d => {
|
511
|
-
return _d.visible == true
|
512
|
-
})
|
513
|
-
})
|
514
|
-
.filter(d => d.length)
|
515
|
-
return visibleComputedData
|
516
|
-
})
|
517
|
-
)
|
518
|
-
}
|
519
|
-
|
520
|
-
// 所有container位置(對應series)
|
521
|
-
export const gridContainerPositionObservable = ({ computedData$, fullDataFormatter$, layout$ }: {
|
522
|
-
computedData$: Observable<ComputedDataTypeMap<'grid'>>
|
523
|
-
fullDataFormatter$: Observable<DataFormatterTypeMap<'grid'>>
|
524
|
-
layout$: Observable<Layout>
|
525
|
-
}): Observable<GridContainerPosition[]> => {
|
526
|
-
|
527
|
-
const gridContainerPosition$ = combineLatest({
|
528
|
-
computedData: computedData$,
|
529
|
-
fullDataFormatter: fullDataFormatter$,
|
530
|
-
layout: layout$,
|
531
|
-
}).pipe(
|
532
|
-
switchMap(async (d) => d),
|
533
|
-
map(data => {
|
534
|
-
|
535
|
-
if (data.fullDataFormatter.grid.separateSeries) {
|
536
|
-
// -- 依slotIndexes計算 --
|
537
|
-
return calcGridContainerLayout(data.layout, data.fullDataFormatter.container, data.computedData.length)
|
538
|
-
// return data.computedData.map((seriesData, seriesIndex) => {
|
539
|
-
// const columnIndex = seriesIndex % data.fullDataFormatter.container.columnAmount
|
540
|
-
// const rowIndex = Math.floor(seriesIndex / data.fullDataFormatter.container.columnAmount)
|
541
|
-
// const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
542
|
-
// return {
|
543
|
-
// slotIndex: seriesIndex,
|
544
|
-
// rowIndex,
|
545
|
-
// columnIndex,
|
546
|
-
// translate,
|
547
|
-
// scale,
|
548
|
-
// }
|
549
|
-
// })
|
550
|
-
} else {
|
551
|
-
// -- 無拆分 --
|
552
|
-
const gridContainerPositionArr = calcGridContainerLayout(data.layout, data.fullDataFormatter.container, 1)
|
553
|
-
return data.computedData.map((d, i) => gridContainerPositionArr[0]) // 每個series相同位置
|
554
|
-
// const columnIndex = 0
|
555
|
-
// const rowIndex = 0
|
556
|
-
// return data.computedData.map((seriesData, seriesIndex) => {
|
557
|
-
// const { translate, scale } = calcGridContainerPosition(data.layout, data.fullDataFormatter.container, rowIndex, columnIndex)
|
558
|
-
// return {
|
559
|
-
// slotIndex: 0,
|
560
|
-
// rowIndex,
|
561
|
-
// columnIndex,
|
562
|
-
// translate,
|
563
|
-
// scale,
|
564
|
-
// }
|
565
|
-
// })
|
566
|
-
}
|
567
|
-
})
|
568
|
-
)
|
569
|
-
|
570
|
-
return gridContainerPosition$
|
571
|
-
}
|
572
|
-
|
573
|
-
// 將原本的value全部替換成加總後的value
|
574
|
-
export const computedStackedDataObservables = ({ isSeriesSeprate$, computedData$ }: {
|
575
|
-
isSeriesSeprate$: Observable<boolean>
|
576
|
-
computedData$: Observable<ComputedDataGrid>
|
577
|
-
}): Observable<ComputedDataGrid> => {
|
578
|
-
const stackedData$: Observable<ComputedDataGrid> = computedData$.pipe(
|
579
|
-
map(data => {
|
580
|
-
// 將同一group的value加總起來
|
581
|
-
const stackedValue = new Array(data[0] ? data[0].length : 0)
|
582
|
-
.fill(null)
|
583
|
-
.map((_, i) => {
|
584
|
-
return data.reduce((prev, current) => {
|
585
|
-
if (current && current[i]) {
|
586
|
-
const currentValue = current[i].value == null || current[i].visible == false
|
587
|
-
? 0
|
588
|
-
: current[i].value!
|
589
|
-
return prev + currentValue
|
590
|
-
}
|
591
|
-
return prev
|
592
|
-
}, 0)
|
593
|
-
})
|
594
|
-
// 將原本的value全部替換成加總後的value
|
595
|
-
const computedData = data.map((series, seriesIndex) => {
|
596
|
-
return series.map((d, i) => {
|
597
|
-
return {
|
598
|
-
...d,
|
599
|
-
value: stackedValue[i],
|
600
|
-
}
|
601
|
-
})
|
602
|
-
})
|
603
|
-
return computedData
|
604
|
-
}),
|
605
|
-
)
|
606
|
-
|
607
|
-
return isSeriesSeprate$.pipe(
|
608
|
-
switchMap(isSeriesSeprate => {
|
609
|
-
return iif(() => isSeriesSeprate, computedData$, stackedData$)
|
610
|
-
})
|
611
|
-
)
|
612
684
|
}
|