@orbcharts/plugins-basic 3.0.0-alpha.34 → 3.0.0-alpha.35

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. package/dist/orbcharts-plugins-basic.es.js +10198 -9511
  2. package/dist/orbcharts-plugins-basic.umd.js +10 -10
  3. package/dist/src/base/BaseBarStack.d.ts +5 -1
  4. package/dist/src/base/BaseBars.d.ts +5 -1
  5. package/dist/src/base/BaseBarsTriangle.d.ts +5 -1
  6. package/dist/src/base/BaseDots.d.ts +4 -1
  7. package/dist/src/base/BaseGroupAxis.d.ts +35 -0
  8. package/dist/src/base/BaseLines.d.ts +3 -1
  9. package/dist/src/base/BaseValueAxis.d.ts +36 -0
  10. package/dist/src/grid/defaults.d.ts +3 -3
  11. package/dist/src/grid/gridObservables.d.ts +18 -4
  12. package/dist/src/grid/index.d.ts +1 -1
  13. package/dist/src/grid/plugins/GroupAux.d.ts +3 -0
  14. package/dist/src/grid/plugins/GroupAxis.d.ts +1 -3
  15. package/dist/src/grid/plugins/ValueAxis.d.ts +1 -3
  16. package/dist/src/grid/plugins/ValueStackAxis.d.ts +1 -3
  17. package/dist/src/grid/types.d.ts +1 -1
  18. package/dist/src/multiGrid/defaults.d.ts +9 -2
  19. package/dist/src/multiGrid/index.d.ts +8 -1
  20. package/dist/src/multiGrid/multiGridObservables.d.ts +12 -0
  21. package/dist/src/multiGrid/plugins/MultiBarStack.d.ts +1 -0
  22. package/dist/src/multiGrid/plugins/MultiBars.d.ts +1 -0
  23. package/dist/src/multiGrid/plugins/MultiBarsTriangle.d.ts +1 -0
  24. package/dist/src/multiGrid/plugins/MultiDots.d.ts +1 -0
  25. package/dist/src/multiGrid/plugins/MultiGroupAxis.d.ts +1 -0
  26. package/dist/src/multiGrid/plugins/MultiLines.d.ts +1 -0
  27. package/dist/src/multiGrid/plugins/MultiValueAxis.d.ts +1 -0
  28. package/dist/src/multiGrid/plugins/OverlappingValueAxes.d.ts +1 -0
  29. package/dist/src/multiGrid/types.d.ts +31 -0
  30. package/package.json +2 -2
  31. package/src/base/BaseBarStack.ts +375 -198
  32. package/src/base/BaseBars.ts +297 -191
  33. package/src/base/BaseBarsTriangle.ts +344 -229
  34. package/src/base/BaseDots.ts +285 -117
  35. package/src/base/BaseGroupAxis.ts +497 -0
  36. package/src/base/BaseLines.ts +180 -50
  37. package/src/base/BaseValueAxis.ts +475 -0
  38. package/src/grid/defaults.ts +3 -3
  39. package/src/grid/gridObservables.ts +147 -14
  40. package/src/grid/index.ts +1 -1
  41. package/src/grid/plugins/BarStack.ts +4 -0
  42. package/src/grid/plugins/Bars.ts +4 -0
  43. package/src/grid/plugins/BarsTriangle.ts +4 -0
  44. package/src/grid/plugins/Dots.ts +3 -0
  45. package/src/grid/plugins/{GroupArea.ts → GroupAux.ts} +24 -24
  46. package/src/grid/plugins/GroupAxis.ts +16 -348
  47. package/src/grid/plugins/Lines.ts +2 -0
  48. package/src/grid/plugins/ScalingArea.ts +9 -6
  49. package/src/grid/plugins/ValueAxis.ts +13 -337
  50. package/src/grid/plugins/ValueStackAxis.ts +35 -336
  51. package/src/grid/types.ts +1 -1
  52. package/src/index.ts +1 -0
  53. package/src/multiGrid/defaults.ts +120 -14
  54. package/src/multiGrid/index.ts +9 -2
  55. package/src/multiGrid/multiGridObservables.ts +279 -0
  56. package/src/multiGrid/plugins/MultiBarStack.ts +60 -0
  57. package/src/multiGrid/plugins/MultiBars.ts +59 -0
  58. package/src/multiGrid/plugins/MultiBarsTriangle.ts +58 -0
  59. package/src/multiGrid/plugins/MultiDots.ts +58 -0
  60. package/src/multiGrid/plugins/MultiGridLegend.ts +2 -7
  61. package/src/multiGrid/plugins/MultiGroupAxis.ts +53 -0
  62. package/src/multiGrid/plugins/MultiLines.ts +58 -0
  63. package/src/multiGrid/plugins/MultiValueAxis.ts +53 -0
  64. package/src/multiGrid/plugins/OverlappingValueAxes.ts +165 -0
  65. package/src/multiGrid/types.ts +39 -0
  66. package/tsconfig.dev.json +17 -0
  67. package/tsconfig.prod.json +14 -0
  68. package/vite.config.js +5 -0
  69. package/dist/src/grid/plugins/GroupArea.d.ts +0 -3
  70. package/dist/src/multiGrid/plugins/BarsAndLines.d.ts +0 -1
  71. package/dist/src/multiGrid/plugins/FirstGroupScaleAxis.d.ts +0 -0
  72. package/dist/src/multiGrid/plugins/TwoValueScaleAxes.d.ts +0 -0
  73. package/src/multiGrid/plugins/BarStackAndLines.ts +0 -0
  74. package/src/multiGrid/plugins/BarsAndLines.ts +0 -126
  75. package/src/multiGrid/plugins/BarsTriangleAndLines.ts +0 -0
  76. package/src/multiGrid/plugins/FirstGroupScaleAxis.ts +0 -0
  77. package/src/multiGrid/plugins/TwoValueScaleAxes.ts +0 -0
  78. /package/dist/src/{multiGrid/plugins/BarStackAndLines.d.ts → base/BaseGroupArea.d.ts} +0 -0
  79. /package/{dist/src/multiGrid/plugins/BarsTriangleAndLines.d.ts → src/base/BaseGroupArea.ts} +0 -0
@@ -1,5 +1,6 @@
1
1
  import * as d3 from 'd3'
2
2
  import {
3
+ iif,
3
4
  combineLatest,
4
5
  map,
5
6
  switchMap,
@@ -13,11 +14,13 @@ import type {
13
14
  ComputedDataGrid,
14
15
  DataFormatterGrid,
15
16
  EventGrid,
16
- ChartParams,
17
+ ChartParams,
18
+ ContainerPosition,
17
19
  Layout,
18
20
  TransformData } from '@orbcharts/core'
19
21
  import { getD3TransitionEase } from '../utils/d3Utils'
20
22
  import { getClassName, getUniID } from '../utils/orbchartsUtils'
23
+ import { gridSelectionsObservable } from '../grid/gridObservables'
21
24
 
22
25
  export interface BaseBarStackParams {
23
26
  barWidth: number
@@ -29,6 +32,7 @@ interface BaseBarStackContext {
29
32
  selection: d3.Selection<any, unknown, any, unknown>
30
33
  computedData$: Observable<ComputedDataGrid>
31
34
  visibleComputedData$: Observable<ComputedDatumGrid[][]>
35
+ existedSeriesLabels$: Observable<string[]>
32
36
  SeriesDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
33
37
  GroupDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
34
38
  fullParams$: Observable<BaseBarStackParams>
@@ -36,11 +40,14 @@ interface BaseBarStackContext {
36
40
  fullChartParams$: Observable<ChartParams>
37
41
  gridAxesTransform$: Observable<TransformData>
38
42
  gridGraphicTransform$: Observable<TransformData>
43
+ gridGraphicReverseScale$: Observable<[number, number][]>
39
44
  gridAxesSize$: Observable<{
40
45
  width: number;
41
46
  height: number;
42
47
  }>
43
48
  gridHighlight$: Observable<string[]>
49
+ gridContainer$: Observable<ContainerPosition[]>
50
+ isSeriesPositionSeprate$: Observable<boolean>
44
51
  event$: Subject<EventGrid>
45
52
  }
46
53
 
@@ -51,17 +58,19 @@ interface GraphicDatum extends ComputedDatumGrid {
51
58
  }
52
59
 
53
60
  interface RenderBarParams {
54
- selection: d3.Selection<SVGGElement, unknown, any, any>
55
- data: GraphicDatum[][]
61
+ graphicGSelection: d3.Selection<SVGGElement, unknown, any, any>
62
+ rectClassName: string
63
+ barData: GraphicDatum[][]
56
64
  zeroY: number
57
65
  groupLabels: string[]
58
66
  // barScale: d3.ScalePoint<string>
59
67
  params: BaseBarStackParams
60
68
  chartParams: ChartParams
61
69
  barWidth: number
62
- transformedBarRadius: [number, number]
70
+ transformedBarRadius: [number, number][]
63
71
  delayGroup: number
64
72
  transitionItem: number
73
+ isSeriesPositionSeprate: boolean
65
74
  }
66
75
 
67
76
  type ClipPathDatum = {
@@ -72,9 +81,8 @@ type ClipPathDatum = {
72
81
  height: number;
73
82
  }
74
83
 
75
- const pluginName = 'BarStack'
76
- const gClassName = getClassName(pluginName, 'g')
77
- const gContentClassName = getClassName(pluginName, 'g-content')
84
+ // const pluginName = 'BarStack'
85
+ // const rectClassName = getClassName(pluginName, 'rect')
78
86
  // group的delay在動畫中的佔比(剩餘部份的時間為圖形本身的動畫時間,因為delay時間和最後一個group的動畫時間加總為1)
79
87
  const groupDelayProportionOfDuration = 0.3
80
88
 
@@ -113,68 +121,100 @@ function calctransitionItem (barGroupAmount: number, totalDuration: number) {
113
121
  return totalDuration * (1 - groupDelayProportionOfDuration) // delay後剩餘的時間
114
122
  }
115
123
 
116
- function renderRectBars ({ selection, data, zeroY, groupLabels, params, chartParams, barWidth, transformedBarRadius, delayGroup, transitionItem }: RenderBarParams) {
124
+ function renderRectBars ({ graphicGSelection, rectClassName, barData, zeroY, groupLabels, params, chartParams, barWidth, transformedBarRadius, delayGroup, transitionItem, isSeriesPositionSeprate }: RenderBarParams) {
117
125
 
118
126
  const barHalfWidth = barWidth! / 2
119
127
 
120
- const barGroup = selection
121
- .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${gClassName}`)
122
- .data(data, (d, i) => groupLabels[i])
123
- .join(
124
- enter => {
125
- return enter
126
- .append('g')
127
- .classed(gClassName, true)
128
- .attr('cursor', 'pointer')
129
- },
130
- update => update,
131
- exit => exit.remove()
132
- )
133
- .attr('transform', (d, i) => `translate(${d[0] ? d[0].axisX : 0}, ${0})`)
134
- .each((d, i, g) => {
135
- const bars = d3.select(g[i])
136
- .selectAll<SVGGElement, ComputedDatumGrid>('g')
137
- .data(d, _d => _d.id)
128
+ graphicGSelection
129
+ .each((seriesData, seriesIndex, g) => {
130
+ d3.select(g[seriesIndex])
131
+ .selectAll<SVGGElement, ComputedDatumGrid>(`rect.${rectClassName}`)
132
+ .data(barData[seriesIndex] ?? [], d => d.id)
138
133
  .join(
139
134
  enter => {
135
+ // console.log('enter')
140
136
  return enter
141
- .append('g')
142
- .classed(gContentClassName, true)
137
+ .append('rect')
138
+ .classed(rectClassName, true)
139
+ .attr('cursor', 'pointer')
140
+ .attr('height', d => 0)
143
141
  },
144
142
  update => update,
145
143
  exit => exit.remove()
146
144
  )
147
- .each((_d, _i, _g) => {
148
- const rect = d3.select(_g[_i])
149
- .selectAll<SVGRectElement, ComputedDatumGrid>('rect')
150
- .data([_d], _d => _d.id)
151
- .join(
152
- enter => {
153
- return enter
154
- .append('rect')
155
- .attr('y', d => zeroY)
156
- .attr('height', d => 0)
157
- },
158
- update => update,
159
- exit => exit.remove()
160
- )
161
- .attr('rx', transformedBarRadius[0])
162
- .attr('ry', transformedBarRadius[1])
163
- .attr('fill', d => d.color)
164
- .attr('transform', `translate(${-barHalfWidth}, 0)`)
165
- .attr('x', d => 0)
166
- .attr('width', barWidth!)
167
- .transition()
168
- .duration(transitionItem)
169
- .ease(getD3TransitionEase(chartParams.transitionEase))
170
- .delay((d, i) => d.groupIndex * delayGroup)
171
- .attr('y', d => d._barStartY)
172
- .attr('height', d => Math.abs(d._barHeight))
173
- })
174
-
145
+ .attr('transform', (d, i) => `translate(${(d ? d.axisX : 0) - barHalfWidth}, ${0})`)
146
+ .attr('fill', d => d.color)
147
+ .attr('y', d => zeroY)
148
+ .attr('x', d =>0)
149
+ .attr('width', barWidth!)
150
+ .attr('rx', transformedBarRadius[seriesIndex][0] ?? 1)
151
+ .attr('ry', transformedBarRadius[seriesIndex][1] ?? 1)
152
+ .transition()
153
+ .duration(transitionItem)
154
+ .ease(getD3TransitionEase(chartParams.transitionEase))
155
+ .delay((d, i) => d.groupIndex * delayGroup)
156
+ .attr('y', d => d._barStartY)
157
+ .attr('height', d => Math.abs(d._barHeight))
175
158
  })
176
159
 
177
- const graphicBarSelection: d3.Selection<SVGRectElement, ComputedDatumGrid, SVGGElement, unknown> = barGroup.selectAll(`g.${gContentClassName}`)
160
+ // const barGroup = graphicGSelection
161
+ // .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${gClassName}`)
162
+ // .data(data, (d, i) => groupLabels[i])
163
+ // .join(
164
+ // enter => {
165
+ // return enter
166
+ // .append('g')
167
+ // .classed(gClassName, true)
168
+ // .attr('cursor', 'pointer')
169
+ // },
170
+ // update => update,
171
+ // exit => exit.remove()
172
+ // )
173
+ // .attr('transform', (d, i) => `translate(${d[0] ? d[0].axisX : 0}, ${0})`)
174
+ // .each((d, i, g) => {
175
+ // const bars = d3.select(g[i])
176
+ // .selectAll<SVGGElement, ComputedDatumGrid>('g')
177
+ // .data(d, _d => _d.id)
178
+ // .join(
179
+ // enter => {
180
+ // return enter
181
+ // .append('g')
182
+ // .classed(gContentClassName, true)
183
+ // },
184
+ // update => update,
185
+ // exit => exit.remove()
186
+ // )
187
+ // .each((_d, _i, _g) => {
188
+ // const rect = d3.select(_g[_i])
189
+ // .selectAll<SVGRectElement, ComputedDatumGrid>('rect')
190
+ // .data([_d], _d => _d.id)
191
+ // .join(
192
+ // enter => {
193
+ // return enter
194
+ // .append('rect')
195
+ // .attr('y', d => zeroY)
196
+ // .attr('height', d => 0)
197
+ // },
198
+ // update => update,
199
+ // exit => exit.remove()
200
+ // )
201
+ // .attr('rx', transformedBarRadius[0])
202
+ // .attr('ry', transformedBarRadius[1])
203
+ // .attr('fill', d => d.color)
204
+ // .attr('transform', `translate(${-barHalfWidth}, 0)`)
205
+ // .attr('x', d => 0)
206
+ // .attr('width', barWidth!)
207
+ // .transition()
208
+ // .duration(transitionItem)
209
+ // .ease(getD3TransitionEase(chartParams.transitionEase))
210
+ // .delay((d, i) => d.groupIndex * delayGroup)
211
+ // .attr('y', d => d._barStartY)
212
+ // .attr('height', d => Math.abs(d._barHeight))
213
+ // })
214
+
215
+ // })
216
+
217
+ const graphicBarSelection: d3.Selection<SVGRectElement, ComputedDatumGrid, SVGGElement, unknown> = graphicGSelection.selectAll(`rect.${rectClassName}`)
178
218
 
179
219
 
180
220
  return graphicBarSelection
@@ -248,6 +288,7 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
248
288
  selection,
249
289
  computedData$,
250
290
  visibleComputedData$,
291
+ existedSeriesLabels$,
251
292
  SeriesDataMap$,
252
293
  GroupDataMap$,
253
294
  fullParams$,
@@ -255,80 +296,183 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
255
296
  fullChartParams$,
256
297
  gridAxesTransform$,
257
298
  gridGraphicTransform$,
299
+ gridGraphicReverseScale$,
258
300
  gridAxesSize$,
259
301
  gridHighlight$,
302
+ gridContainer$,
303
+ isSeriesPositionSeprate$,
260
304
  event$
261
305
  }) => {
262
306
 
263
307
  const destroy$ = new Subject()
264
308
 
265
309
  const clipPathID = getUniID(pluginName, 'clipPath-box')
310
+ const rectClassName = getClassName(pluginName, 'rect')
266
311
 
267
- const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
268
- .append('g')
269
- .attr('clip-path', `url(#${clipPathID})`)
270
- const defsSelection: d3.Selection<SVGDefsElement, ComputedDatumGrid, any, any> = axisSelection.append('defs')
271
- const graphicGSelection: d3.Selection<SVGGElement, any, any, any> = axisSelection.append('g')
272
- const barSelection$: Subject<d3.Selection<SVGRectElement, ComputedDatumGrid, SVGGElement, unknown>> = new Subject()
273
-
274
- gridAxesTransform$
275
- .pipe(
276
- takeUntil(destroy$),
277
- map(d => d.value),
278
- distinctUntilChanged()
279
- ).subscribe(d => {
280
- axisSelection
281
- .style('transform', d)
282
- })
312
+ // const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
313
+ // .append('g')
314
+ // .attr('clip-path', `url(#${clipPathID})`)
315
+ // const defsSelection: d3.Selection<SVGDefsElement, ComputedDatumGrid, any, any> = axisSelection.append('defs')
316
+ // const graphicGSelection: d3.Selection<SVGGElement, any, any, any> = axisSelection.append('g')
317
+ // const barSelection$: Subject<d3.Selection<SVGRectElement, ComputedDatumGrid, SVGGElement, unknown>> = new Subject()
283
318
 
284
- gridGraphicTransform$
285
- .pipe(
286
- takeUntil(destroy$),
287
- switchMap(async d => d.value),
288
- distinctUntilChanged()
289
- ).subscribe(d => {
290
- graphicGSelection
291
- .transition()
292
- .duration(50)
293
- .style('transform', d)
294
- })
319
+ // gridAxesTransform$
320
+ // .pipe(
321
+ // takeUntil(destroy$),
322
+ // map(d => d.value),
323
+ // distinctUntilChanged()
324
+ // ).subscribe(d => {
325
+ // axisSelection
326
+ // .style('transform', d)
327
+ // })
328
+
329
+ // gridGraphicTransform$
330
+ // .pipe(
331
+ // takeUntil(destroy$),
332
+ // switchMap(async d => d.value),
333
+ // distinctUntilChanged()
334
+ // ).subscribe(d => {
335
+ // graphicGSelection
336
+ // .transition()
337
+ // .duration(50)
338
+ // .style('transform', d)
339
+ // })
295
340
 
296
- // const axisSize$ = gridAxisSizeObservable({
297
- // dataFormatter$,
298
- // layout$
341
+ // const seriesSelection$ = computedData$.pipe(
342
+ // takeUntil(destroy$),
343
+ // distinctUntilChanged((a, b) => {
344
+ // // 只有當series的數量改變時,才重新計算
345
+ // return a.length === b.length
346
+ // }),
347
+ // map((computedData, i) => {
348
+ // return selection
349
+ // .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${seriesClassName}`)
350
+ // .data(computedData, d => d[0] ? d[0].seriesIndex : i)
351
+ // .join(
352
+ // enter => {
353
+ // return enter
354
+ // .append('g')
355
+ // .classed(seriesClassName, true)
356
+ // .each((d, i, g) => {
357
+ // const axesSelection = d3.select(g[i])
358
+ // .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${axesClassName}`)
359
+ // .data([i])
360
+ // .join(
361
+ // enter => {
362
+ // return enter
363
+ // .append('g')
364
+ // .classed(axesClassName, true)
365
+ // .attr('clip-path', `url(#${clipPathID})`)
366
+ // .each((d, i, g) => {
367
+ // const defsSelection = d3.select(g[i])
368
+ // .selectAll<SVGDefsElement, any>('defs')
369
+ // .data([i])
370
+ // .join('defs')
371
+
372
+ // const graphicGSelection = d3.select(g[i])
373
+ // .selectAll<SVGGElement, any>('g')
374
+ // .data([i])
375
+ // .join('g')
376
+ // .classed(graphicClassName, true)
377
+ // })
378
+ // },
379
+ // update => update,
380
+ // exit => exit.remove()
381
+ // )
382
+ // })
383
+ // },
384
+ // update => update,
385
+ // exit => exit.remove()
386
+ // )
387
+ // })
388
+ // )
389
+
390
+ // combineLatest({
391
+ // seriesSelection: seriesSelection$,
392
+ // gridContainer: gridContainer$
393
+ // }).pipe(
394
+ // takeUntil(destroy$),
395
+ // switchMap(async d => d)
396
+ // ).subscribe(data => {
397
+ // data.seriesSelection
398
+ // .transition()
399
+ // .attr('transform', (d, i) => {
400
+ // const translate = data.gridContainer[i].translate
401
+ // const scale = data.gridContainer[i].scale
402
+ // return `translate(${translate[0]}, ${translate[1]}) scale(${scale[0]}, ${scale[1]})`
403
+ // })
299
404
  // })
300
405
 
301
- // const visibleComputedData$ = computedData$.pipe(
406
+
407
+ // const axesSelection$ = combineLatest({
408
+ // seriesSelection: seriesSelection$,
409
+ // gridAxesTransform: gridAxesTransform$
410
+ // }).pipe(
302
411
  // takeUntil(destroy$),
412
+ // switchMap(async d => d),
303
413
  // map(data => {
304
- // const visibleComputedData = data
305
- // .map(d => {
306
- // return d.filter(_d => {
307
- // return _d.visible == true
308
- // })
309
- // })
310
- // .filter(d => d.length)
311
- // // console.log('visibleComputedData', visibleComputedData)
312
- // return visibleComputedData
414
+ // return data.seriesSelection
415
+ // .select<SVGGElement>(`g.${axesClassName}`)
416
+ // .style('transform', data.gridAxesTransform.value)
417
+ // })
418
+ // )
419
+ // const defsSelection$ = axesSelection$.pipe(
420
+ // takeUntil(destroy$),
421
+ // map(axesSelection => {
422
+ // return axesSelection.select<SVGDefsElement>('defs')
423
+ // })
424
+ // )
425
+ // const graphicGSelection$ = combineLatest({
426
+ // axesSelection: axesSelection$,
427
+ // gridGraphicTransform: gridGraphicTransform$
428
+ // }).pipe(
429
+ // takeUntil(destroy$),
430
+ // switchMap(async d => d),
431
+ // map(data => {
432
+ // const graphicGSelection = data.axesSelection
433
+ // .select<SVGGElement>(`g.${graphicClassName}`)
434
+ // graphicGSelection
435
+ // .transition()
436
+ // .duration(50)
437
+ // .style('transform', data.gridGraphicTransform.value)
438
+ // return graphicGSelection
313
439
  // })
314
440
  // )
315
441
 
442
+ const {
443
+ seriesSelection$,
444
+ axesSelection$,
445
+ defsSelection$,
446
+ graphicGSelection$
447
+ } = gridSelectionsObservable({
448
+ selection,
449
+ pluginName,
450
+ clipPathID,
451
+ existedSeriesLabels$,
452
+ gridContainer$,
453
+ gridAxesTransform$,
454
+ gridGraphicTransform$
455
+ })
456
+
457
+
316
458
  const zeroY$ = visibleComputedData$.pipe(
459
+ takeUntil(destroy$),
317
460
  map(d => d[0] && d[0][0]
318
461
  ? d[0][0].axisY - d[0][0].axisYFromZero
319
462
  : 0),
320
463
  distinctUntilChanged()
321
464
  )
322
465
 
323
- const barWidth$ = new Observable<number>(subscriber => {
324
- combineLatest({
325
- computedData: computedData$,
326
- // visibleComputedData: visibleComputedData$,
327
- params: fullParams$,
328
- axisSize: gridAxesSize$
329
- }).pipe(
330
- switchMap(async d => d)
331
- ).subscribe(data => {
466
+ const barWidth$ = combineLatest({
467
+ computedData: computedData$,
468
+ // visibleComputedData: visibleComputedData$,
469
+ params: fullParams$,
470
+ axisSize: gridAxesSize$,
471
+ isSeriesPositionSeprate: isSeriesPositionSeprate$
472
+ }).pipe(
473
+ takeUntil(destroy$),
474
+ switchMap(async d => d),
475
+ map(data => {
332
476
  const barWidth = data.params.barWidth
333
477
  ? data.params.barWidth
334
478
  : calcBarWidth({
@@ -336,18 +480,18 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
336
480
  groupAmount: data.computedData[0] ? data.computedData[0].length : 0,
337
481
  barGroupPadding: data.params.barGroupPadding
338
482
  })
339
- subscriber.next(barWidth)
340
- })
341
- }).pipe(
342
- takeUntil(destroy$),
483
+ return barWidth
484
+ }),
343
485
  distinctUntilChanged()
344
486
  )
345
487
 
346
488
  // 圓角的值 [rx, ry]
347
- const transformedBarRadius$: Observable<[number, number]> = combineLatest({
348
- gridGraphicTransform: gridGraphicTransform$,
489
+ const transformedBarRadius$: Observable<[number, number][]> = combineLatest({
490
+ computedData: computedData$,
491
+ // gridGraphicTransform: gridGraphicTransform$,
349
492
  barWidth: barWidth$,
350
- params: fullParams$
493
+ params: fullParams$,
494
+ gridGraphicReverseScale: gridGraphicReverseScale$
351
495
  }).pipe(
352
496
  takeUntil(destroy$),
353
497
  switchMap(async data => data),
@@ -357,13 +501,15 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
357
501
  : data.params.barRadius === false ? 0
358
502
  : typeof data.params.barRadius == 'number' ? data.params.barRadius
359
503
  : 0
360
- const transformedRx = radius == 0
361
- ? 0
362
- : radius / data.gridGraphicTransform.scale[0] // 反向外層scale的變型
363
- const transformedRy = radius == 0
364
- ? 0
365
- : radius / data.gridGraphicTransform.scale[1]
366
- return [transformedRx, transformedRy]
504
+
505
+ return data.computedData.map((series, seriesIndex) => {
506
+ const gridGraphicReverseScale = data.gridGraphicReverseScale[seriesIndex] ?? data.gridGraphicReverseScale[0]
507
+
508
+ const transformedRx = radius * gridGraphicReverseScale[0]
509
+ const transformedRy = radius * gridGraphicReverseScale[1]
510
+
511
+ return [transformedRx, transformedRy]
512
+ })
367
513
  })
368
514
  )
369
515
 
@@ -393,20 +539,6 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
393
539
  })
394
540
  )
395
541
 
396
- // const barScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
397
- // combineLatest({
398
- // seriesLabels: seriesLabels$,
399
- // barWidth: barWidth$,
400
- // params: fullParams$,
401
- // }).pipe(
402
- // takeUntil(destroy$),
403
- // switchMap(async d => d)
404
- // ).subscribe(data => {
405
- // const barScale = makeBarScale(data.barWidth, data.seriesLabels, data.params)
406
- // subscriber.next(barScale)
407
- // })
408
- // })
409
-
410
542
  const transitionDuration$ = fullChartParams$.pipe(
411
543
  takeUntil(destroy$),
412
544
  map(d => d.transitionDuration),
@@ -443,46 +575,46 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
443
575
  distinctUntilChanged()
444
576
  )
445
577
 
446
- const transposedVisibleData$: Observable<ComputedDataGrid> = visibleComputedData$.pipe(
447
- takeUntil(destroy$),
448
- map(data => {
449
- console.log('visibleComputedData', data)
450
- // 取得原始陣列的維度
451
- const rows = data.length;
452
- const cols = data.reduce((prev, current) => {
453
- return Math.max(prev, current.length)
454
- }, 0)
455
-
456
- // 初始化轉換後的陣列
457
- const transposedArray = new Array(cols).fill(null).map(() => new Array(rows).fill(null))
458
-
459
- // 遍歷原始陣列,進行轉換
460
- for (let i = 0; i < rows; i++) {
461
- for (let j = 0; j < cols; j++) {
462
- transposedArray[j][i] = data[i][j]
463
- }
464
- }
465
- return transposedArray
466
- })
467
- )
578
+ // const transposedVisibleData$: Observable<ComputedDataGrid> = visibleComputedData$.pipe(
579
+ // takeUntil(destroy$),
580
+ // map(data => {
581
+ // console.log('visibleComputedData', data)
582
+ // // 取得原始陣列的維度
583
+ // const rows = data.length;
584
+ // const cols = data.reduce((prev, current) => {
585
+ // return Math.max(prev, current.length)
586
+ // }, 0)
587
+
588
+ // // 初始化轉換後的陣列
589
+ // const transposedArray = new Array(cols).fill(null).map(() => new Array(rows).fill(null))
590
+
591
+ // // 遍歷原始陣列,進行轉換
592
+ // for (let i = 0; i < rows; i++) {
593
+ // for (let j = 0; j < cols; j++) {
594
+ // transposedArray[j][i] = data[i][j]
595
+ // }
596
+ // }
597
+ // return transposedArray
598
+ // })
599
+ // )
468
600
 
469
601
  const yRatio$ = combineLatest({
470
- transposedVisibleData: transposedVisibleData$,
602
+ computedData: computedData$,
471
603
  dataFormatter: fullDataFormatter$,
472
604
  }).pipe(
473
605
  takeUntil(destroy$),
474
606
  switchMap(async d => d),
475
607
  map(data => {
476
608
  const groupMin = 0
477
- const groupMax = data.transposedVisibleData.length - 1
478
- const groupScaleDomainMin = data.dataFormatter.groupAxis.scaleDomain[0] === 'auto'
479
- ? groupMin - data.dataFormatter.groupAxis.scalePadding
480
- : data.dataFormatter.groupAxis.scaleDomain[0] as number - data.dataFormatter.groupAxis.scalePadding
481
- const groupScaleDomainMax = data.dataFormatter.groupAxis.scaleDomain[1] === 'auto'
482
- ? groupMax + data.dataFormatter.groupAxis.scalePadding
483
- : data.dataFormatter.groupAxis.scaleDomain[1] as number + data.dataFormatter.groupAxis.scalePadding
609
+ const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
610
+ const groupScaleDomainMin = data.dataFormatter.grid.groupAxis.scaleDomain[0] === 'auto'
611
+ ? groupMin - data.dataFormatter.grid.groupAxis.scalePadding
612
+ : data.dataFormatter.grid.groupAxis.scaleDomain[0] as number - data.dataFormatter.grid.groupAxis.scalePadding
613
+ const groupScaleDomainMax = data.dataFormatter.grid.groupAxis.scaleDomain[1] === 'auto'
614
+ ? groupMax + data.dataFormatter.grid.groupAxis.scalePadding
615
+ : data.dataFormatter.grid.groupAxis.scaleDomain[1] as number + data.dataFormatter.grid.groupAxis.scalePadding
484
616
 
485
- const filteredData = data.transposedVisibleData
617
+ const filteredData = data.computedData
486
618
  .map(d => {
487
619
  return d.filter((_d, i) => {
488
620
  return _d.groupIndex >= groupScaleDomainMin && _d.groupIndex <= groupScaleDomainMax
@@ -490,12 +622,20 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
490
622
  })
491
623
  // console.log('filteredData', filteredData)
492
624
 
493
- if (!filteredData.flat().length) {
625
+ if (filteredData.length <= 1) {
494
626
  return 1
495
627
  } else {
496
628
  const yArr = filteredData.flat().map(d => d.axisYFromZero)
497
629
  const barMaxY = Math.max(...yArr)
498
- const stackYArr = filteredData.map(d => d.reduce((prev, current) => prev + current.axisYFromZero, 0))
630
+ // const stackYArr = filteredData.map(d => d.reduce((prev, current) => prev + current.axisYFromZero, 0))
631
+ const stackYArr = data.computedData[0]
632
+ ? data.computedData[0].map((_, groupIndex) => {
633
+ // 加總同一group的value
634
+ return data.computedData.reduce((prev, current) => {
635
+ return prev + current[groupIndex].axisYFromZero
636
+ }, 0)
637
+ })
638
+ : []
499
639
  const barStackMaxY = Math.max(...stackYArr)
500
640
 
501
641
  return barMaxY / barStackMaxY
@@ -503,60 +643,97 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
503
643
  })
504
644
  )
505
645
 
506
- const graphicData$ = combineLatest({
507
- transposedVisibleData: transposedVisibleData$,
646
+ const stackedData$ = combineLatest({
647
+ computedData: computedData$,
508
648
  yRatio: yRatio$,
509
649
  zeroY: zeroY$
510
650
  }).pipe(
511
651
  takeUntil(destroy$),
512
652
  map(data => {
513
- console.log(data.transposedVisibleData)
514
- return data.transposedVisibleData.map(d => {
515
- let accY = data.zeroY
516
- return d.map(_d => {
517
- const _barStartY = accY
518
- const _barHeight = _d.axisYFromZero * data.yRatio
519
- accY = accY + _barHeight
653
+ let accYArr: number[] = data.computedData[0]
654
+ ? data.computedData[0].map(() => data.zeroY)
655
+ : []
656
+ return data.computedData.map((series, seriesIndex) => {
657
+ return series.map((datum, groupIndex) => {
658
+ const _barStartY = accYArr[groupIndex] // 前一次的累加高度
659
+ const _barHeight = datum.axisYFromZero * data.yRatio
660
+ accYArr[groupIndex] = accYArr[groupIndex] + _barHeight // 累加高度
520
661
  return <GraphicDatum>{
521
- ..._d,
662
+ ...datum,
522
663
  _barStartY,
523
664
  _barHeight
524
665
  }
525
666
  })
526
667
  })
668
+ // return data.computedData.map(d => {
669
+ // let accY = data.zeroY
670
+ // return d.map(_d => {
671
+ // const _barStartY = accY
672
+ // const _barHeight = _d.axisYFromZero * data.yRatio
673
+ // accY = accY + _barHeight
674
+ // return <GraphicDatum>{
675
+ // ..._d,
676
+ // _barStartY,
677
+ // _barHeight
678
+ // }
679
+ // })
680
+ // })
681
+ })
682
+ )
683
+
684
+ const noneStackedData$ = combineLatest({
685
+ computedData: computedData$,
686
+ // yRatio: yRatio$,
687
+ zeroY: zeroY$
688
+ }).pipe(
689
+ takeUntil(destroy$),
690
+ map(data => {
691
+ return data.computedData.map((series, seriesIndex) => {
692
+ return series.map((datum, groupIndex) => {
693
+ return <GraphicDatum>{
694
+ ...datum,
695
+ _barStartY: data.zeroY,
696
+ _barHeight: datum.axisYFromZero
697
+ }
698
+ })
699
+ })
527
700
  })
528
701
  )
529
702
 
530
- gridAxesSize$.pipe(
531
- takeUntil(destroy$)
703
+ const graphicData$ = isSeriesPositionSeprate$.pipe(
704
+ switchMap(isSeriesPositionSeprate => {
705
+ return iif(() => isSeriesPositionSeprate, noneStackedData$, stackedData$)
706
+ })
707
+ )
708
+
709
+ combineLatest({
710
+ defsSelection: defsSelection$,
711
+ gridAxesSize: gridAxesSize$,
712
+ }).pipe(
713
+ takeUntil(destroy$),
714
+ switchMap(async d => d)
532
715
  ).subscribe(data => {
533
716
  const clipPathData = [{
534
717
  id: clipPathID,
535
- width: data.width,
536
- height: data.height
718
+ width: data.gridAxesSize.width,
719
+ height: data.gridAxesSize.height
537
720
  }]
538
721
  renderClipPath({
539
- defsSelection,
722
+ defsSelection: data.defsSelection,
540
723
  clipPathData
541
724
  })
542
725
  })
543
726
 
544
- // const SeriesDataMap$ = visibleComputedData$.pipe(
545
- // map(d => makeGridSeriesDataMap(d))
546
- // )
547
-
548
- // const GroupDataMap$ = visibleComputedData$.pipe(
549
- // map(d => makeGridGroupDataMap(d))
550
- // )
551
-
552
727
  const highlightTarget$ = fullChartParams$.pipe(
553
728
  takeUntil(destroy$),
554
729
  map(d => d.highlightTarget),
555
730
  distinctUntilChanged()
556
731
  )
557
732
 
733
+ const barSelection$ = new Subject<d3.Selection<SVGRectElement, ComputedDatumGrid, SVGGElement, unknown>>()
734
+
558
735
  combineLatest({
559
- // renderBarsFn: renderBarsFn$,
736
+ graphicGSelection: graphicGSelection$,
560
737
  graphicData: graphicData$,
561
738
  zeroY: zeroY$,
562
739
  groupLabels: groupLabels$,
@@ -569,15 +746,16 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
569
746
  delayGroup: delayGroup$,
570
747
  transitionItem: transitionItem$,
571
748
  SeriesDataMap: SeriesDataMap$,
572
- GroupDataMap: GroupDataMap$
749
+ GroupDataMap: GroupDataMap$,
750
+ isSeriesPositionSeprate: isSeriesPositionSeprate$
573
751
  }).pipe(
574
752
  takeUntil(destroy$),
575
- // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
576
753
  switchMap(async (d) => d),
577
754
  ).subscribe(data => {
578
755
  const barSelection = renderRectBars({
579
- selection: graphicGSelection,
580
- data: data.graphicData,
756
+ graphicGSelection: data.graphicGSelection,
757
+ rectClassName,
758
+ barData: data.graphicData,
581
759
  zeroY: data.zeroY,
582
760
  groupLabels: data.groupLabels,
583
761
  // barScale: data.barScale,
@@ -586,7 +764,8 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
586
764
  barWidth: data.barWidth,
587
765
  transformedBarRadius: data.transformedBarRadius,
588
766
  delayGroup: data.delayGroup,
589
- transitionItem: data.transitionItem
767
+ transitionItem: data.transitionItem,
768
+ isSeriesPositionSeprate: data.isSeriesPositionSeprate
590
769
  })
591
770
 
592
771
  barSelection!
@@ -675,7 +854,6 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
675
854
  // map(d => d.flat())
676
855
  // )
677
856
  // const highlight$ = highlightObservable({ datumList$, chartParams$, event$: store.event$ })
678
- const highlightSubscription = gridHighlight$.subscribe()
679
857
 
680
858
  combineLatest({
681
859
  barSelection: barSelection$,
@@ -694,6 +872,5 @@ export const createBaseBarStack: BasePluginFn<BaseBarStackContext> = (pluginName
694
872
 
695
873
  return () => {
696
874
  destroy$.next(undefined)
697
- highlightSubscription.unsubscribe()
698
875
  }
699
876
  }