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

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.
@@ -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
+ // }