@orbcharts/plugins-basic 3.0.0-alpha.56 → 3.0.0-alpha.58

Sign up to get free protection for your applications and to get access to all the features.
@@ -26,6 +26,7 @@ interface BaseLineAreasContext {
26
26
  }>;
27
27
  gridHighlight$: Observable<ComputedDatumGrid[]>;
28
28
  gridContainerPosition$: Observable<GridContainerPosition[]>;
29
+ allContainerPosition$: Observable<GridContainerPosition[]>;
29
30
  layout$: Observable<Layout>;
30
31
  event$: Subject<EventGrid>;
31
32
  }
@@ -1,6 +1,6 @@
1
1
  import { Observable, Subject } from 'rxjs';
2
2
  import { BasePluginFn } from './types';
3
- import { ComputedDatumGrid, ComputedDataGrid, ComputedLayoutDataGrid, DataFormatterGrid, EventGrid, GridContainerPosition, ChartParams, TransformData } from '@orbcharts/core';
3
+ import { ComputedDatumGrid, ComputedDataGrid, ComputedLayoutDataGrid, DataFormatterGrid, EventGrid, GridContainerPosition, ChartParams, Layout, TransformData } from '@orbcharts/core';
4
4
  import * as d3 from 'd3';
5
5
  export interface BaseLinesParams {
6
6
  lineCurve: string;
@@ -26,6 +26,8 @@ interface BaseLinesContext {
26
26
  }>;
27
27
  gridHighlight$: Observable<ComputedDatumGrid[]>;
28
28
  gridContainerPosition$: Observable<GridContainerPosition[]>;
29
+ allContainerPosition$: Observable<GridContainerPosition[]>;
30
+ layout$: Observable<Layout>;
29
31
  event$: Subject<EventGrid>;
30
32
  }
31
33
  export declare const createBaseLines: BasePluginFn<BaseLinesContext>;
@@ -1,5 +1,5 @@
1
1
  import { Observable } from 'rxjs';
2
- import { ChartParams, DataFormatterGrid, ComputedDataGrid, TransformData, GridContainerPosition } from '@orbcharts/core';
2
+ import { ChartParams, DataFormatterGrid, ComputedDataGrid, TransformData, GridContainerPosition, Layout } from '@orbcharts/core';
3
3
  import * as d3 from 'd3';
4
4
  export declare const gridSelectionsObservable: ({ selection, pluginName, clipPathID, seriesLabels$, gridContainerPosition$, gridAxesTransform$, gridGraphicTransform$ }: {
5
5
  selection: d3.Selection<any, unknown, any, unknown>;
@@ -15,7 +15,7 @@ export declare const gridSelectionsObservable: ({ selection, pluginName, clipPat
15
15
  defsSelection$: Observable<d3.Selection<SVGDefsElement, string, any, unknown>>;
16
16
  graphicGSelection$: Observable<d3.Selection<SVGGElement, string, any, unknown>>;
17
17
  };
18
- export declare const gridGroupPositionFnObservable: ({ fullDataFormatter$, gridAxesSize$, computedData$, fullChartParams$ }: {
18
+ export declare const gridGroupPositionFnObservable: ({ fullDataFormatter$, gridAxesSize$, computedData$, fullChartParams$, gridContainerPosition$, layout$ }: {
19
19
  fullDataFormatter$: Observable<DataFormatterGrid>;
20
20
  gridAxesSize$: Observable<{
21
21
  width: number;
@@ -23,7 +23,24 @@ export declare const gridGroupPositionFnObservable: ({ fullDataFormatter$, gridA
23
23
  }>;
24
24
  computedData$: Observable<ComputedDataGrid>;
25
25
  fullChartParams$: Observable<ChartParams>;
26
+ gridContainerPosition$: Observable<GridContainerPosition[]>;
27
+ layout$: Observable<Layout>;
26
28
  }) => Observable<(event: any) => {
27
29
  groupIndex: number;
28
30
  groupLabel: string;
29
31
  }>;
32
+ export declare const gridGroupPosition: ({ rootSelection, fullDataFormatter$, gridAxesSize$, computedData$, fullChartParams$, gridContainerPosition$, layout$ }: {
33
+ rootSelection: d3.Selection<any, unknown, any, unknown>;
34
+ fullDataFormatter$: Observable<DataFormatterGrid>;
35
+ gridAxesSize$: Observable<{
36
+ width: number;
37
+ height: number;
38
+ }>;
39
+ computedData$: Observable<ComputedDataGrid>;
40
+ fullChartParams$: Observable<ChartParams>;
41
+ gridContainerPosition$: Observable<GridContainerPosition[]>;
42
+ layout$: Observable<Layout>;
43
+ }) => Observable<{
44
+ groupIndex: number;
45
+ groupLabel: string;
46
+ }>;
@@ -24,6 +24,7 @@ export interface GroupAuxParams {
24
24
  labelTextColorType: ColorType;
25
25
  labelTextFormat: string | ((text: any) => string);
26
26
  labelPadding: number;
27
+ labelRotate: number;
27
28
  }
28
29
  export interface BarsParams {
29
30
  barWidth: number;
@@ -0,0 +1,2 @@
1
+ declare const _default: import('vite').UserConfigFnObject;
2
+ export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orbcharts/plugins-basic",
3
- "version": "3.0.0-alpha.56",
3
+ "version": "3.0.0-alpha.58",
4
4
  "description": "plugins for OrbCharts",
5
5
  "author": "Blue Planet Inc.",
6
6
  "license": "Apache-2.0",
@@ -25,17 +25,18 @@
25
25
  "types": "./dist/src/index.d.ts",
26
26
  "scripts": {
27
27
  "test": "echo \"Error: no test specified\" && exit 1",
28
- "build": "vite build --mode release"
28
+ "build": "vite build --mode production"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/d3": "^7.4.0",
32
32
  "ts-loader": "^9.4.2",
33
33
  "typescript": "^5.0.4",
34
34
  "vite": "^5.3.5",
35
- "vite-plugin-dts": "^3.7.3"
35
+ "vite-plugin-dts": "^3.7.3",
36
+ "vite-plugin-tsconfig": "^1.0.5"
36
37
  },
37
38
  "dependencies": {
38
- "@orbcharts/core": "^3.0.0-alpha.52",
39
+ "@orbcharts/core": "^3.0.0-alpha.54",
39
40
  "d3": "^7.8.5",
40
41
  "rxjs": "^7.8.1"
41
42
  }
@@ -115,7 +115,7 @@ function renderAxis ({ selection, xAxisClassName, groupingLabelClassName, params
115
115
  .attr('dominant-baseline', axisLabelAlign.dominantBaseline)
116
116
  .attr('font-size', chartParams.styles.textSize)
117
117
  .style('fill', getColor(params.labelColorType, chartParams))
118
- .style('transform', textTransform)
118
+ // .style('transform', textTransform)
119
119
  .text(d => fullDataFormatter.grid.groupAxis.label)
120
120
  })
121
121
  .attr('transform', d => `translate(${gridAxesSize.width + d.tickPadding + params.labelOffset[0]}, ${- d.tickPadding - defaultTickSize - params.labelOffset[1]})`)
@@ -52,6 +52,7 @@ interface BaseLineAreasContext {
52
52
  }>
53
53
  gridHighlight$: Observable<ComputedDatumGrid[]>
54
54
  gridContainerPosition$: Observable<GridContainerPosition[]>
55
+ allContainerPosition$: Observable<GridContainerPosition[]>
55
56
  layout$: Observable<Layout>
56
57
  event$: Subject<EventGrid>
57
58
  }
@@ -408,7 +409,9 @@ export const createBaseLineAreas: BasePluginFn<BaseLineAreasContext> = (pluginNa
408
409
  fullDataFormatter$,
409
410
  gridAxesSize$: gridAxesSize$,
410
411
  computedData$: computedData$,
411
- fullChartParams$: fullChartParams$
412
+ fullChartParams$: fullChartParams$,
413
+ gridContainerPosition$: gridContainerPosition$,
414
+ layout$: layout$
412
415
  })
413
416
 
414
417
  const highlightTarget$ = fullChartParams$.pipe(
@@ -57,6 +57,8 @@ interface BaseLinesContext {
57
57
  }>
58
58
  gridHighlight$: Observable<ComputedDatumGrid[]>
59
59
  gridContainerPosition$: Observable<GridContainerPosition[]>
60
+ allContainerPosition$: Observable<GridContainerPosition[]>
61
+ layout$: Observable<Layout>
60
62
  event$: Subject<EventGrid>
61
63
  }
62
64
 
@@ -240,6 +242,8 @@ export const createBaseLines: BasePluginFn<BaseLinesContext> = (pluginName: stri
240
242
  gridAxesSize$,
241
243
  gridHighlight$,
242
244
  gridContainerPosition$,
245
+ allContainerPosition$,
246
+ layout$,
243
247
  event$
244
248
  }) => {
245
249
 
@@ -496,7 +500,9 @@ export const createBaseLines: BasePluginFn<BaseLinesContext> = (pluginName: stri
496
500
  fullDataFormatter$,
497
501
  gridAxesSize$: gridAxesSize$,
498
502
  computedData$: computedData$,
499
- fullChartParams$: fullChartParams$
503
+ fullChartParams$: fullChartParams$,
504
+ gridContainerPosition$: allContainerPosition$,
505
+ layout$: layout$
500
506
  })
501
507
 
502
508
  const highlightTarget$ = fullChartParams$.pipe(
@@ -541,8 +547,6 @@ export const createBaseLines: BasePluginFn<BaseLinesContext> = (pluginName: stri
541
547
 
542
548
  return pathSelectionArr
543
549
  })
544
-
545
-
546
550
  )
547
551
 
548
552
  combineLatest({
@@ -563,6 +567,7 @@ export const createBaseLines: BasePluginFn<BaseLinesContext> = (pluginName: stri
563
567
 
564
568
  const seriesLabel = datum[0] ? datum[0].seriesLabel : ''
565
569
  const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
570
+ // console.log('groupIndex', groupIndex)
566
571
  const groupData = data.GroupDataMap.get(groupLabel)!
567
572
  const targetDatum = groupData.find(d => d.seriesLabel === seriesLabel)
568
573
  const _datum = targetDatum ?? datum[0]
@@ -109,7 +109,7 @@ function renderAxis ({ selection, yAxisClassName, textClassName, fullParams, tic
109
109
  .attr('dominant-baseline', axisLabelAlign.dominantBaseline)
110
110
  .attr('font-size', fullChartParams.styles.textSize)
111
111
  .style('fill', getColor(fullParams.labelColorType, fullChartParams))
112
- .style('transform', textTransform)
112
+ // .style('transform', textTransform)
113
113
  .text(d => fullDataFormatter.grid.valueAxis.label)
114
114
  })
115
115
  .attr('transform', d => `translate(${- d.tickPadding + fullParams.labelOffset[0]}, ${gridAxesSize.height + d.tickPadding + fullParams.labelOffset[1]})`)
@@ -40,6 +40,7 @@ export const DEFAULT_GROUP_AREA_PARAMS: GroupAuxParams = {
40
40
  labelTextColorType: 'background',
41
41
  labelTextFormat: text => text,
42
42
  labelPadding: 24,
43
+ labelRotate: 0
43
44
  }
44
45
  DEFAULT_GROUP_AREA_PARAMS.labelTextFormat.toString = () => `text => text`
45
46
 
@@ -23,6 +23,7 @@ import type {
23
23
  Layout } from '@orbcharts/core'
24
24
  import { createAxisQuantizeScale } from '@orbcharts/core'
25
25
  import { getClassName, getUniID } from '../utils/orbchartsUtils'
26
+ import { d3EventObservable } from '../utils/observables'
26
27
 
27
28
  // grid選取器
28
29
  export const gridSelectionsObservable = ({ selection, pluginName, clipPathID, seriesLabels$, gridContainerPosition$, gridAxesTransform$, gridGraphicTransform$ }: {
@@ -144,7 +145,8 @@ export const gridSelectionsObservable = ({ selection, pluginName, clipPathID, se
144
145
  }
145
146
 
146
147
  // 由事件取得group data的function
147
- export const gridGroupPositionFnObservable = ({ fullDataFormatter$, gridAxesSize$, computedData$, fullChartParams$ }: {
148
+ // @Q@ 之後重構改用 gridGroupPosition
149
+ export const gridGroupPositionFnObservable = ({ fullDataFormatter$, gridAxesSize$, computedData$, fullChartParams$, gridContainerPosition$, layout$ }: {
148
150
  fullDataFormatter$: Observable<DataFormatterGrid>
149
151
  gridAxesSize$: Observable<{
150
152
  width: number;
@@ -153,56 +155,128 @@ export const gridGroupPositionFnObservable = ({ fullDataFormatter$, gridAxesSize
153
155
  computedData$: Observable<ComputedDataGrid>
154
156
  // GroupDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
155
157
  fullChartParams$: Observable<ChartParams>
158
+ gridContainerPosition$: Observable<GridContainerPosition[]>
159
+ layout$: Observable<Layout>
156
160
  }): Observable<(event: any) => { groupIndex: number; groupLabel: string }> => {
157
161
  const destroy$ = new Subject()
158
162
 
159
163
  // 顯示範圍內的group labels
160
- const scaleRangeGroupLabels$: Observable<string[]> = new Observable(subscriber => {
161
- combineLatest({
162
- dataFormatter: fullDataFormatter$,
163
- computedData: computedData$
164
- }).pipe(
165
- takeUntil(destroy$),
166
- switchMap(async (d) => d),
167
- ).subscribe(data => {
164
+ // const scaleRangeGroupLabels$: Observable<string[]> = new Observable(subscriber => {
165
+ // combineLatest({
166
+ // dataFormatter: fullDataFormatter$,
167
+ // computedData: computedData$
168
+ // }).pipe(
169
+ // takeUntil(destroy$),
170
+ // switchMap(async (d) => d),
171
+ // ).subscribe(data => {
172
+ // const groupMin = 0
173
+ // const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
174
+ // const groupScaleDomainMin = data.dataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
175
+ // ? groupMin - data.dataFormatter.grid.groupAxis.scalePadding
176
+ // : data.dataFormatter.grid.groupAxis.scaleDomain[0] as number - data.dataFormatter.grid.groupAxis.scalePadding
177
+ // const groupScaleDomainMax = data.dataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
178
+ // ? groupMax + data.dataFormatter.grid.groupAxis.scalePadding
179
+ // : data.dataFormatter.grid.groupAxis.scaleDomain[1] as number + data.dataFormatter.grid.groupAxis.scalePadding
180
+
181
+ // // const groupingAmount = data.computedData[0]
182
+ // // ? data.computedData[0].length
183
+ // // : 0
184
+
185
+ // let _labels = data.dataFormatter.grid.seriesDirection === 'row'
186
+ // ? (data.computedData[0] ?? []).map(d => d.groupLabel)
187
+ // : data.computedData.map(d => d[0].groupLabel)
188
+
189
+ // const _axisLabels =
190
+ // // new Array(groupingAmount).fill(0)
191
+ // // .map((d, i) => {
192
+ // // return _labels[i] != null
193
+ // // ? _labels[i]
194
+ // // : String(i) // 沒有label則用序列號填充
195
+ // // })
196
+ // _labels
197
+ // .filter((d, i) => {
198
+ // return i >= groupScaleDomainMin && i <= groupScaleDomainMax
199
+ // })
200
+ // subscriber.next(_axisLabels)
201
+ // })
202
+ // })
203
+ const groupScaleDomain$ = combineLatest({
204
+ fullDataFormatter: fullDataFormatter$,
205
+ gridAxesSize: gridAxesSize$,
206
+ computedData: computedData$
207
+ }).pipe(
208
+ switchMap(async (d) => d),
209
+ map(data => {
168
210
  const groupMin = 0
169
211
  const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
170
- const groupScaleDomainMin = data.dataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
171
- ? groupMin - data.dataFormatter.grid.groupAxis.scalePadding
172
- : data.dataFormatter.grid.groupAxis.scaleDomain[0] as number - data.dataFormatter.grid.groupAxis.scalePadding
173
- const groupScaleDomainMax = data.dataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
174
- ? groupMax + data.dataFormatter.grid.groupAxis.scalePadding
175
- : data.dataFormatter.grid.groupAxis.scaleDomain[1] as number + data.dataFormatter.grid.groupAxis.scalePadding
176
-
177
- // const groupingAmount = data.computedData[0]
178
- // ? data.computedData[0].length
179
- // : 0
212
+ const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
213
+ ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
214
+ : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
215
+ const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
216
+ ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
217
+ : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
180
218
 
181
- let _labels = data.dataFormatter.grid.seriesDirection === 'row'
219
+ return [groupScaleDomainMin, groupScaleDomainMax]
220
+ }),
221
+ shareReplay(1)
222
+ )
223
+
224
+ const groupLabels$ = combineLatest({
225
+ fullDataFormatter: fullDataFormatter$,
226
+ computedData: computedData$
227
+ }).pipe(
228
+ switchMap(async d => d),
229
+ map(data => {
230
+ return data.fullDataFormatter.grid.seriesDirection === 'row'
182
231
  ? (data.computedData[0] ?? []).map(d => d.groupLabel)
183
232
  : data.computedData.map(d => d[0].groupLabel)
233
+ })
234
+ )
184
235
 
185
- const _axisLabels =
186
- // new Array(groupingAmount).fill(0)
187
- // .map((d, i) => {
188
- // return _labels[i] != null
189
- // ? _labels[i]
190
- // : String(i) // 沒有label則用序列號填充
191
- // })
192
- _labels
236
+ // 顯示範圍內的group labels
237
+ const scaleRangeGroupLabels$ = combineLatest({
238
+ groupScaleDomain: groupScaleDomain$,
239
+ groupLabels: groupLabels$
240
+ }).pipe(
241
+ switchMap(async d => d),
242
+ map(data => {
243
+ return data.groupLabels
193
244
  .filter((d, i) => {
194
- return i >= groupScaleDomainMin && i <= groupScaleDomainMax
245
+ return i >= data.groupScaleDomain[0] && i <= data.groupScaleDomain[1]
195
246
  })
196
- subscriber.next(_axisLabels)
197
247
  })
198
- })
248
+ )
249
+
250
+ const columnAmount$ = gridContainerPosition$.pipe(
251
+ map(gridContainerPosition => {
252
+ const maxColumnIndex = gridContainerPosition.reduce((acc, current) => {
253
+ return current.columnIndex > acc ? current.columnIndex : acc
254
+ }, 0)
255
+ return maxColumnIndex + 1
256
+ }),
257
+ distinctUntilChanged()
258
+ )
259
+
260
+ const rowAmount$ = gridContainerPosition$.pipe(
261
+ map(gridContainerPosition => {
262
+ const maxRowIndex = gridContainerPosition.reduce((acc, current) => {
263
+ return current.rowIndex > acc ? current.rowIndex : acc
264
+ }, 0)
265
+ return maxRowIndex + 1
266
+ }),
267
+ distinctUntilChanged()
268
+ )
199
269
 
200
270
  return new Observable<(event: any) => { groupIndex: number; groupLabel: string }>(subscriber => {
201
271
  combineLatest({
202
272
  dataFormatter: fullDataFormatter$,
203
273
  axisSize: gridAxesSize$,
204
274
  fullChartParams: fullChartParams$,
205
- scaleRangeGroupLabels: scaleRangeGroupLabels$
275
+ scaleRangeGroupLabels: scaleRangeGroupLabels$,
276
+ groupScaleDomain: groupScaleDomain$,
277
+ columnAmount: columnAmount$,
278
+ rowAmount: rowAmount$,
279
+ layout: layout$
206
280
  }).pipe(
207
281
  takeUntil(destroy$),
208
282
  switchMap(async (d) => d),
@@ -213,9 +287,10 @@ export const gridGroupPositionFnObservable = ({ fullDataFormatter$, gridAxesSize
213
287
  ? true : false
214
288
 
215
289
  // 比例尺座標對應非連續資料索引
216
- const groupIndexScale = createAxisQuantizeScale({
290
+ const xIndexScale = createAxisQuantizeScale({
217
291
  axisLabels: data.scaleRangeGroupLabels,
218
292
  axisWidth: data.axisSize.width,
293
+ padding: data.dataFormatter.grid.groupAxis.scalePadding,
219
294
  reverse
220
295
  })
221
296
 
@@ -229,8 +304,16 @@ export const gridGroupPositionFnObservable = ({ fullDataFormatter$, gridAxesSize
229
304
 
230
305
  // 比例尺座標取得groupData的function
231
306
  const createEventGroupData: (event: any) => { groupIndex: number; groupLabel: string } = (event: any) => {
232
- const axisValue = axisValuePredicate(event)
233
- const groupIndex = groupIndexScale(axisValue)
307
+ // 由於event座標是基於底層的,但是container會有多欄,所以要重新計算
308
+ const eventData = {
309
+ offsetX: event.offsetX * data.columnAmount % data.layout.rootWidth,
310
+ offsetY: event.offsetY * data.rowAmount % data.layout.rootHeight
311
+ }
312
+ // console.log('data.columnAmount', data.columnAmount, 'data.rowAmount', data.rowAmount, 'data.layout.rootWidth', data.layout.rootWidth, 'data.layout.rootHeight', data.layout.rootHeight)
313
+ const axisValue = axisValuePredicate(eventData)
314
+ const xIndex = xIndexScale(axisValue)
315
+ const currentxIndexStart = Math.ceil(data.groupScaleDomain[0]) // 因為有padding所以會有小數點,所以要無條件進位
316
+ const groupIndex = xIndex + currentxIndexStart
234
317
  return {
235
318
  groupIndex,
236
319
  groupLabel: data.scaleRangeGroupLabels[groupIndex] ?? ''
@@ -246,3 +329,214 @@ export const gridGroupPositionFnObservable = ({ fullDataFormatter$, gridAxesSize
246
329
  })
247
330
  }
248
331
 
332
+ export const gridGroupPosition = ({ rootSelection, fullDataFormatter$, gridAxesSize$, computedData$, fullChartParams$, gridContainerPosition$, layout$ }: {
333
+ rootSelection: d3.Selection<any, unknown, any, unknown>
334
+ fullDataFormatter$: Observable<DataFormatterGrid>
335
+ gridAxesSize$: Observable<{
336
+ width: number;
337
+ height: number;
338
+ }>
339
+ computedData$: Observable<ComputedDataGrid>
340
+ fullChartParams$: Observable<ChartParams>
341
+ gridContainerPosition$: Observable<GridContainerPosition[]>
342
+ layout$: Observable<Layout>
343
+ }) => {
344
+ const rootMousemove$: Observable<any> = d3EventObservable(rootSelection, 'mousemove')
345
+
346
+ const groupScaleDomain$ = combineLatest({
347
+ fullDataFormatter: fullDataFormatter$,
348
+ gridAxesSize: gridAxesSize$,
349
+ computedData: computedData$
350
+ }).pipe(
351
+ switchMap(async (d) => d),
352
+ map(data => {
353
+ const groupMin = 0
354
+ const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
355
+ const groupScaleDomainMin = data.fullDataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
356
+ ? groupMin - data.fullDataFormatter.grid.groupAxis.scalePadding
357
+ : data.fullDataFormatter.grid.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.grid.groupAxis.scalePadding
358
+ const groupScaleDomainMax = data.fullDataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
359
+ ? groupMax + data.fullDataFormatter.grid.groupAxis.scalePadding
360
+ : data.fullDataFormatter.grid.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.grid.groupAxis.scalePadding
361
+
362
+ return [groupScaleDomainMin, groupScaleDomainMax]
363
+ }),
364
+ shareReplay(1)
365
+ )
366
+
367
+ const groupLabels$ = combineLatest({
368
+ fullDataFormatter: fullDataFormatter$,
369
+ computedData: computedData$
370
+ }).pipe(
371
+ switchMap(async d => d),
372
+ map(data => {
373
+ return data.fullDataFormatter.grid.seriesDirection === 'row'
374
+ ? (data.computedData[0] ?? []).map(d => d.groupLabel)
375
+ : data.computedData.map(d => d[0].groupLabel)
376
+ })
377
+ )
378
+
379
+ const scaleRangeGroupLabels$ = combineLatest({
380
+ groupScaleDomain: groupScaleDomain$,
381
+ groupLabels: groupLabels$
382
+ }).pipe(
383
+ switchMap(async d => d),
384
+ map(data => {
385
+ return data.groupLabels
386
+ .filter((d, i) => {
387
+ return i >= data.groupScaleDomain[0] && i <= data.groupScaleDomain[1]
388
+ })
389
+ })
390
+ )
391
+
392
+ const reverse$ = fullDataFormatter$.pipe(
393
+ map(d => {
394
+ return d.grid.valueAxis.position === 'right' || d.grid.valueAxis.position === 'bottom'
395
+ ? true
396
+ : false
397
+ })
398
+ )
399
+
400
+ // 比例尺座標對應非連續資料索引
401
+ const xIndexScale$ = combineLatest({
402
+ reverse: reverse$,
403
+ gridAxesSize: gridAxesSize$,
404
+ scaleRangeGroupLabels: scaleRangeGroupLabels$,
405
+ fullDataFormatter: fullDataFormatter$
406
+ }).pipe(
407
+ switchMap(async d => d),
408
+ map(data => {
409
+ return createAxisQuantizeScale({
410
+ axisLabels: data.scaleRangeGroupLabels,
411
+ axisWidth: data.gridAxesSize.width,
412
+ padding: data.fullDataFormatter.grid.groupAxis.scalePadding,
413
+ reverse: data.reverse
414
+ })
415
+ })
416
+ )
417
+
418
+ const columnAmount$ = gridContainerPosition$.pipe(
419
+ map(gridContainerPosition => {
420
+ const maxColumnIndex = gridContainerPosition.reduce((acc, current) => {
421
+ return current.columnIndex > acc ? current.columnIndex : acc
422
+ }, 0)
423
+ return maxColumnIndex + 1
424
+ }),
425
+ distinctUntilChanged()
426
+ )
427
+
428
+ const rowAmount$ = gridContainerPosition$.pipe(
429
+ map(gridContainerPosition => {
430
+ const maxRowIndex = gridContainerPosition.reduce((acc, current) => {
431
+ return current.rowIndex > acc ? current.rowIndex : acc
432
+ }, 0)
433
+ return maxRowIndex + 1
434
+ }),
435
+ distinctUntilChanged()
436
+ )
437
+
438
+ const axisValue$ = combineLatest({
439
+ fullDataFormatter: fullDataFormatter$,
440
+ fullChartParams: fullChartParams$,
441
+ rootMousemove: rootMousemove$,
442
+ columnAmount: columnAmount$,
443
+ rowAmount: rowAmount$,
444
+ layout: layout$
445
+ }).pipe(
446
+ switchMap(async d => d),
447
+ map(data => {
448
+ // 由於event座標是基於底層的,但是container會有多欄,所以要重新計算
449
+ const eventData = {
450
+ offsetX: data.rootMousemove.offsetX * data.columnAmount % data.layout.rootWidth,
451
+ offsetY: data.rootMousemove.offsetY * data.rowAmount % data.layout.rootHeight
452
+ }
453
+ return data.fullDataFormatter.grid.groupAxis.position === 'bottom'
454
+ || data.fullDataFormatter.grid.groupAxis.position === 'top'
455
+ ? eventData.offsetX - data.fullChartParams.padding.left
456
+ : eventData.offsetY - data.fullChartParams.padding.top
457
+ })
458
+ )
459
+
460
+ const groupIndex$ = combineLatest({
461
+ xIndexScale: xIndexScale$,
462
+ axisValue: axisValue$,
463
+ groupScaleDomain: groupScaleDomain$
464
+ }).pipe(
465
+ switchMap(async d => d),
466
+ map(data => {
467
+ const xIndex = data.xIndexScale(data.axisValue)
468
+ const currentxIndexStart = Math.ceil(data.groupScaleDomain[0]) // 因為有padding所以會有小數點,所以要無條件進位
469
+ return xIndex + currentxIndexStart
470
+ })
471
+ )
472
+
473
+ const groupLabel$ = combineLatest({
474
+ groupIndex: groupIndex$,
475
+ groupLabels: groupLabels$
476
+ }).pipe(
477
+ switchMap(async d => d),
478
+ map(data => {
479
+ return data.groupLabels[data.groupIndex] ?? ''
480
+ })
481
+ )
482
+
483
+ return combineLatest({
484
+ groupIndex: groupIndex$,
485
+ groupLabel: groupLabel$
486
+ }).pipe(
487
+ switchMap(async d => d),
488
+ map(data => {
489
+ return {
490
+ groupIndex: data.groupIndex,
491
+ groupLabel: data.groupLabel
492
+ }
493
+ })
494
+ )
495
+ }
496
+
497
+ // const gridContainerEventData$ = ({ eventData$, gridContainerPosition$, layout$ }: {
498
+ // eventData$: Observable<any>
499
+ // gridContainerPosition$: Observable<GridContainerPosition[]>
500
+ // layout$: Observable<Layout>
501
+ // }): Observable<{
502
+ // offsetX: number;
503
+ // offsetY: number;
504
+ // }> => {
505
+ // const columnAmount$ = gridContainerPosition$.pipe(
506
+ // map(gridContainerPosition => {
507
+ // const maxColumnIndex = gridContainerPosition.reduce((acc, current) => {
508
+ // return current.columnIndex > acc ? current.columnIndex : acc
509
+ // }, 0)
510
+ // return maxColumnIndex + 1
511
+ // }),
512
+ // distinctUntilChanged()
513
+ // )
514
+
515
+ // const rowAmount$ = gridContainerPosition$.pipe(
516
+ // map(gridContainerPosition => {
517
+ // const maxRowIndex = gridContainerPosition.reduce((acc, current) => {
518
+ // return current.rowIndex > acc ? current.rowIndex : acc
519
+ // }, 0)
520
+ // return maxRowIndex + 1
521
+ // }),
522
+ // distinctUntilChanged()
523
+ // )
524
+
525
+ // return combineLatest({
526
+ // eventData: eventData$,
527
+ // gridContainerPosition: gridContainerPosition$,
528
+ // layout: layout$,
529
+ // columnAmount: columnAmount$,
530
+ // rowAmount: rowAmount$
531
+ // }).pipe(
532
+ // switchMap(async d => d),
533
+ // map(data => {
534
+ // // 由於event座標是基於底層的,但是container會有多欄,所以要重新計算
535
+ // const eventData = {
536
+ // offsetX: data.eventData.offsetX * data.columnAmount % data.layout.rootWidth,
537
+ // offsetY: data.eventData.offsetY * data.rowAmount % data.layout.rootHeight
538
+ // }
539
+ // return eventData
540
+ // })
541
+ // )
542
+ // }