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

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.
Files changed (80) hide show
  1. package/dist/orbcharts-plugins-basic.es.js +10246 -9523
  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 +33 -0
  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/Dots.d.ts +1 -3
  14. package/dist/src/grid/plugins/GroupAux.d.ts +3 -0
  15. package/dist/src/grid/plugins/GroupAxis.d.ts +1 -3
  16. package/dist/src/grid/plugins/ValueAxis.d.ts +1 -3
  17. package/dist/src/grid/plugins/ValueStackAxis.d.ts +1 -3
  18. package/dist/src/grid/types.d.ts +1 -1
  19. package/dist/src/multiGrid/defaults.d.ts +9 -2
  20. package/dist/src/multiGrid/index.d.ts +8 -1
  21. package/dist/src/multiGrid/multiGridObservables.d.ts +12 -0
  22. package/dist/src/multiGrid/plugins/MultiBarStack.d.ts +1 -0
  23. package/dist/src/multiGrid/plugins/MultiBars.d.ts +1 -0
  24. package/dist/src/multiGrid/plugins/MultiBarsTriangle.d.ts +1 -0
  25. package/dist/src/multiGrid/plugins/MultiDots.d.ts +1 -0
  26. package/dist/src/multiGrid/plugins/MultiGroupAxis.d.ts +1 -0
  27. package/dist/src/multiGrid/plugins/MultiLines.d.ts +1 -0
  28. package/dist/src/multiGrid/plugins/MultiValueAxis.d.ts +1 -0
  29. package/dist/src/multiGrid/plugins/OverlappingValueAxes.d.ts +1 -0
  30. package/dist/src/multiGrid/types.d.ts +31 -0
  31. package/package.json +2 -2
  32. package/src/base/BaseBarStack.ts +375 -198
  33. package/src/base/BaseBars.ts +297 -191
  34. package/src/base/BaseBarsTriangle.ts +344 -229
  35. package/src/base/BaseDots.ts +634 -0
  36. package/src/base/BaseGroupAxis.ts +497 -0
  37. package/src/base/BaseLines.ts +180 -50
  38. package/src/base/BaseValueAxis.ts +475 -0
  39. package/src/grid/defaults.ts +3 -3
  40. package/src/grid/gridObservables.ts +147 -14
  41. package/src/grid/index.ts +1 -1
  42. package/src/grid/plugins/BarStack.ts +4 -0
  43. package/src/grid/plugins/Bars.ts +4 -0
  44. package/src/grid/plugins/BarsTriangle.ts +4 -0
  45. package/src/grid/plugins/Dots.ts +19 -410
  46. package/src/grid/plugins/{GroupArea.ts → GroupAux.ts} +24 -24
  47. package/src/grid/plugins/GroupAxis.ts +16 -348
  48. package/src/grid/plugins/Lines.ts +2 -0
  49. package/src/grid/plugins/ScalingArea.ts +9 -6
  50. package/src/grid/plugins/ValueAxis.ts +13 -337
  51. package/src/grid/plugins/ValueStackAxis.ts +35 -336
  52. package/src/grid/types.ts +1 -1
  53. package/src/index.ts +1 -0
  54. package/src/multiGrid/defaults.ts +120 -14
  55. package/src/multiGrid/index.ts +9 -2
  56. package/src/multiGrid/multiGridObservables.ts +279 -0
  57. package/src/multiGrid/plugins/MultiBarStack.ts +60 -0
  58. package/src/multiGrid/plugins/MultiBars.ts +59 -0
  59. package/src/multiGrid/plugins/MultiBarsTriangle.ts +58 -0
  60. package/src/multiGrid/plugins/MultiDots.ts +58 -0
  61. package/src/multiGrid/plugins/MultiGridLegend.ts +9 -10
  62. package/src/multiGrid/plugins/MultiGroupAxis.ts +53 -0
  63. package/src/multiGrid/plugins/MultiLines.ts +58 -0
  64. package/src/multiGrid/plugins/MultiValueAxis.ts +53 -0
  65. package/src/multiGrid/plugins/OverlappingValueAxes.ts +165 -0
  66. package/src/multiGrid/types.ts +39 -0
  67. package/tsconfig.dev.json +17 -0
  68. package/tsconfig.prod.json +14 -0
  69. package/vite.config.js +5 -0
  70. package/dist/src/grid/plugins/GroupArea.d.ts +0 -3
  71. package/dist/src/multiGrid/plugins/BarsAndLines.d.ts +0 -1
  72. package/dist/src/multiGrid/plugins/FirstGroupScaleAxis.d.ts +0 -0
  73. package/dist/src/multiGrid/plugins/TwoValueScaleAxes.d.ts +0 -0
  74. package/src/multiGrid/plugins/BarStackAndLines.ts +0 -0
  75. package/src/multiGrid/plugins/BarsAndLines.ts +0 -126
  76. package/src/multiGrid/plugins/BarsTriangleAndLines.ts +0 -0
  77. package/src/multiGrid/plugins/FirstGroupScaleAxis.ts +0 -0
  78. package/src/multiGrid/plugins/TwoValueScaleAxes.ts +0 -0
  79. /package/dist/src/{multiGrid/plugins/BarStackAndLines.d.ts → base/BaseGroupArea.d.ts} +0 -0
  80. /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
  }