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

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -12,11 +12,13 @@ import type {
12
12
  ComputedDatumGrid,
13
13
  ComputedDataGrid,
14
14
  EventGrid,
15
- ChartParams,
15
+ ChartParams,
16
+ ContainerPosition,
16
17
  Layout,
17
18
  TransformData } from '@orbcharts/core'
18
19
  import { getD3TransitionEase } from '../utils/d3Utils'
19
20
  import { getClassName, getUniID } from '../utils/orbchartsUtils'
21
+ import { gridSelectionsObservable } from '../grid/gridObservables'
20
22
 
21
23
  export interface BaseBarsTriangleParams {
22
24
  barWidth: number
@@ -28,6 +30,8 @@ export interface BaseBarsTriangleParams {
28
30
  interface BaseBarsContext {
29
31
  selection: d3.Selection<any, unknown, any, unknown>
30
32
  computedData$: Observable<ComputedDataGrid>
33
+ visibleComputedData$: Observable<ComputedDatumGrid[][]>
34
+ existedSeriesLabels$: Observable<string[]>
31
35
  SeriesDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
32
36
  GroupDataMap$: Observable<Map<string, ComputedDatumGrid[]>>
33
37
  fullParams$: Observable<BaseBarsTriangleParams>
@@ -39,14 +43,18 @@ interface BaseBarsContext {
39
43
  height: number;
40
44
  }>
41
45
  gridHighlight$: Observable<string[]>
46
+ gridContainer$: Observable<ContainerPosition[]>
47
+ isSeriesPositionSeprate$: Observable<boolean>
42
48
  event$: Subject<EventGrid>
43
49
  }
44
50
 
45
51
 
46
52
  interface RenderBarParams {
47
- selection: d3.Selection<SVGGElement, unknown, any, any>
53
+ graphicGSelection: d3.Selection<SVGGElement, unknown, any, any>
54
+ pathGClassName: string
55
+ pathClassName: string
48
56
  barData: BarDatumGrid[][]
49
- zeroY: number
57
+ zeroYArr: number[]
50
58
  groupLabels: string[]
51
59
  barScale: d3.ScalePoint<string>
52
60
  params: BaseBarsTriangleParams
@@ -54,6 +62,7 @@ interface RenderBarParams {
54
62
  barWidth: number
55
63
  delayGroup: number
56
64
  transitionItem: number
65
+ isSeriesPositionSeprate: boolean
57
66
  }
58
67
 
59
68
  interface BarDatumGrid extends ComputedDatumGrid {
@@ -68,9 +77,9 @@ type ClipPathDatum = {
68
77
  height: number;
69
78
  }
70
79
 
71
- const pluginName = 'BaseBarsTriangle'
72
- const gClassName = getClassName(pluginName, 'g')
73
- const gContentClassName = getClassName(pluginName, 'g-content')
80
+ // const pluginName = 'BaseBarsTriangle'
81
+ // const pathGClassName = getClassName(pluginName, 'pathG')
82
+ // const pathClassName = getClassName(pluginName, 'path')
74
83
  // group的delay在動畫中的佔比(剩餘部份的時間為圖形本身的動畫時間,因為delay時間和最後一個group的動畫時間加總為1)
75
84
  const groupDelayProportionOfDuration = 0.3
76
85
 
@@ -81,7 +90,8 @@ function calcBarWidth ({ axisWidth, groupAmount, barAmountOfGroup, barPadding =
81
90
  barPadding: number
82
91
  barGroupPadding: number
83
92
  }) {
84
- const width = (axisWidth / groupAmount - barGroupPadding) / barAmountOfGroup - barPadding
93
+ const eachGroupWidth = axisWidth / (groupAmount - 1)
94
+ const width = (eachGroupWidth - barGroupPadding) / barAmountOfGroup - barPadding
85
95
  return width > 1 ? width : 1
86
96
  }
87
97
 
@@ -109,102 +119,99 @@ function calctransitionItem (barGroupAmount: number, totalDuration: number) {
109
119
  return totalDuration * (1 - groupDelayProportionOfDuration) // delay後剩餘的時間
110
120
  }
111
121
 
112
- function renderTriangleBars ({ selection, barData, zeroY, groupLabels, barScale, params, chartParams, barWidth, delayGroup, transitionItem }: RenderBarParams) {
113
- // console.log({ selection, data, zeroY, seriesLabels, barScale, params, chartParams, barWidth, delayGroup })
114
- // if (barWidth <= 0) {
115
- // return
116
- // }
117
- const update = selection!
118
- .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${gClassName}`)
119
- .data(barData, (d, i) => groupLabels[i])
120
- const enter = update.enter()
121
- .append('g')
122
- .classed(gClassName, true)
123
- .attr('cursor', 'pointer')
124
- update.exit().remove()
125
- const graphicGroupSelection = update.merge(enter)
126
- enter
127
- .attr('transform', (d, i) => `translate(${d[0] ? d[0].axisX : 0}, ${0})`)
128
- update
129
- // .transition()
130
- // .duration(200)
131
- .attr('transform', (d, i) => `translate(${d[0] ? d[0].axisX : 0}, ${0})`)
132
-
122
+ function renderTriangleBars ({ graphicGSelection, pathGClassName, pathClassName, barData, zeroYArr, groupLabels, barScale, params, chartParams, barWidth, delayGroup, transitionItem, isSeriesPositionSeprate }: RenderBarParams) {
123
+
133
124
  const barHalfWidth = barWidth! / 2
134
125
 
135
- graphicGroupSelection
136
- .each((d, i, g) => {
137
- const pathUpdate = d3.select(g[i])
138
- .selectAll<SVGGElement, ComputedDatumGrid>('g')
139
- .data(d, _d => _d.id)
140
- const pathEnter = pathUpdate
141
- .enter()
142
- .append('g')
143
- .classed(gContentClassName, true)
144
- pathEnter
145
- .append('path')
146
- // .attr('transform', `translate(${-barHalfWidth}, 0)`)
147
- // .attr('x', d => itemScale(d.itemLabel)!)
148
- // .attr('y', d => 0)
149
- .style('vector-effect', 'non-scaling-stroke')
150
- .attr('height', d => 0)
151
- .attr('d', (d) => {
152
- const x = barScale(d.seriesLabel)!
153
- const y1 = zeroY
154
- const y2 = y1
155
- return `M${x - (barWidth! / 2)},${y1} L${x},${y2} ${x + (barWidth! / 2)},${y1}`
156
- })
157
- pathUpdate.merge(pathEnter)
158
- .select('path')
126
+ graphicGSelection
127
+ .each((d, seriesIndex, g) => {
128
+ // g
129
+ const gSelection = d3.select(g[seriesIndex])
130
+ .selectAll<SVGGElement, ComputedDatumGrid>(`g.${pathGClassName}`)
131
+ .data(barData[seriesIndex] ?? [])
132
+ .join(
133
+ enter => {
134
+ const enterSelection = enter
135
+ .append('g')
136
+ .classed(pathGClassName, true)
137
+ .attr('cursor', 'pointer')
138
+ enterSelection
139
+ .append('path')
140
+ .classed(pathClassName, true)
141
+ .style('vector-effect', 'non-scaling-stroke')
142
+ .attr('d', (d) => {
143
+ const x = -barHalfWidth
144
+ const y1 = zeroYArr[seriesIndex]
145
+ const y2 = zeroYArr[seriesIndex]
146
+ return `M${x},${y1} L${x + (barWidth! / 2)},${y2} ${x + barWidth!},${y1}`
147
+ })
148
+ return enterSelection
149
+ },
150
+ update => update,
151
+ exit => exit.remove()
152
+ )
153
+ .attr('transform', d => `translate(${isSeriesPositionSeprate ? 0 : barScale(d.seriesLabel)!}, 0)`)
154
+
155
+ // path
156
+ gSelection.select(`path.${pathClassName}`)
157
+ .attr('height', d => Math.abs(d.axisYFromZero))
158
+ .attr('y', d => d.axisY < zeroYArr[seriesIndex] ? d.axisY : zeroYArr[seriesIndex])
159
+ .attr('x', d => isSeriesPositionSeprate ? 0 : barScale(d.seriesLabel)!)
159
160
  .style('fill', d => `url(#${d.linearGradientId})`)
160
161
  .attr('stroke', d => d.color)
161
- .attr('transform', `translate(${-barHalfWidth}, 0)`)
162
+ .attr('transform', d => `translate(${(d ? d.axisX : 0)}, ${0})`)
162
163
  .transition()
163
164
  .duration(transitionItem)
164
165
  .ease(getD3TransitionEase(chartParams.transitionEase))
165
166
  .delay((d, i) => d.groupIndex * delayGroup)
166
- .attr('transform', `translate(${-barHalfWidth}, 0)`)
167
+ // .attr('transform', `translate(${-barHalfWidth}, 0)`)
167
168
  // .attr('x', d => itemScale(d.itemLabel)!)
168
169
  // .attr('y', d => -d.y)
169
- .attr('height', d => Math.abs(d.axisYFromZero))
170
170
  .attr('d', (d) => {
171
- const x = barScale(d.seriesLabel)!
172
- const y1 = zeroY
171
+ const x = -barHalfWidth
172
+ const y1 = zeroYArr[seriesIndex]
173
173
  const y2 = d.axisY
174
174
  return `M${x},${y1} L${x + (barWidth! / 2)},${y2} ${x + barWidth!},${y1}`
175
175
  })
176
- // .on('end', () => initHighlight())
177
- pathUpdate.exit().remove()
178
- })
176
+ })
179
177
 
180
- const graphicBarSelection: d3.Selection<SVGPathElement, ComputedDatumGrid, any, any> = graphicGroupSelection.selectAll(`g.${gContentClassName}`)
178
+ const graphicBarSelection: d3.Selection<SVGPathElement, ComputedDatumGrid, any, any> = graphicGSelection.selectAll(`path.${pathClassName}`)
181
179
 
182
180
  return graphicBarSelection
183
181
  }
184
182
 
185
183
  function renderLinearGradient ({ defsSelection, barData, params }: {
186
- defsSelection: d3.Selection<SVGDefsElement, ComputedDatumGrid, any, any>
184
+ defsSelection: d3.Selection<SVGDefsElement, any, any, any>
187
185
  barData: BarDatumGrid[][]
188
186
  params: BaseBarsTriangleParams
189
187
  }) {
190
- const linearGradientUpdate = defsSelection!
191
- .selectAll<SVGLinearGradientElement, ComputedDatumGrid>('linearGradient')
192
- .data(barData[0] ?? [], d => d.seriesLabel)
193
- const linearGradientEnter = linearGradientUpdate
194
- .enter()
195
- .append('linearGradient')
196
- .attr('x1', '0%')
197
- .attr('x2', '0%')
198
- .attr('y1', '100%')
199
- .attr('y2', '0%')
200
- .attr('spreadMethod', 'pad')
201
- linearGradientUpdate.merge(linearGradientEnter)
202
- .attr('id', (d, i) => d.linearGradientId)
203
- .html((d, i) => `
204
- <stop offset="0%" stop-color="${d.color}" stop-opacity="${params.linearGradientOpacity[0]}"/>
205
- <stop offset="100%" stop-color="${d.color}" stop-opacity="${params.linearGradientOpacity[1]}"/>
206
- `)
207
- linearGradientUpdate.exit().remove()
188
+ defsSelection!
189
+ .selectAll<SVGLinearGradientElement, ComputedDatumGrid>('linearGradient')
190
+ .data(barData ?? [])
191
+ .join(
192
+ enter => {
193
+ return enter
194
+ .append('linearGradient')
195
+ .attr('x1', '0%')
196
+ .attr('x2', '0%')
197
+ .attr('y1', '100%')
198
+ .attr('y2', '0%')
199
+ .attr('spreadMethod', 'pad')
200
+ },
201
+ update => update,
202
+ exit => exit.remove()
203
+ )
204
+ .attr('id', (d, i) => {
205
+ return d[0] ? d[0].linearGradientId : ''
206
+ })
207
+ .html((d, i) => {
208
+ const color = d[0] ? d[0].color : ''
209
+ return `
210
+ <stop offset="0%" stop-color="${color}" stop-opacity="${params.linearGradientOpacity[0]}"/>
211
+ <stop offset="100%" stop-color="${color}" stop-opacity="${params.linearGradientOpacity[1]}"/>
212
+ `
213
+ })
214
+
208
215
  }
209
216
 
210
217
 
@@ -212,27 +219,35 @@ function renderClipPath ({ defsSelection, clipPathData }: {
212
219
  defsSelection: d3.Selection<SVGDefsElement, any, any, any>
213
220
  clipPathData: ClipPathDatum[]
214
221
  }) {
215
- const update = defsSelection
222
+ const clipPath = defsSelection
216
223
  .selectAll<SVGClipPathElement, Layout>('clipPath')
217
224
  .data(clipPathData)
218
- const enter = update.enter()
219
- .append('clipPath')
220
- const cutRect = update.merge(enter)
225
+ .join(
226
+ enter => {
227
+ return enter
228
+ .append('clipPath')
229
+ },
230
+ update => update,
231
+ exit => exit.remove()
232
+ )
221
233
  .attr('id', d => d.id)
222
- update.exit().remove()
223
-
224
- update.merge(enter).each((d, i, g) => {
225
- const updateRect = d3.select(g[i])
226
- .selectAll<SVGRectElement, typeof d>('rect')
227
- .data([d])
228
- const enterRect = updateRect.enter().append('rect')
229
- updateRect.merge(enterRect)
230
- .attr('x', 0)
231
- .attr('y', 0)
232
- .attr('width', _d => _d.width)
233
- .attr('height', _d => _d.height)
234
- updateRect.exit().remove()
235
- })
234
+ .each((d, i, g) => {
235
+ const rect = d3.select(g[i])
236
+ .selectAll<SVGRectElement, typeof d>('rect')
237
+ .data([d])
238
+ .join(
239
+ enter => {
240
+ return enter
241
+ .append('rect')
242
+ },
243
+ update => update,
244
+ exit => exit.remove()
245
+ )
246
+ .attr('x', 0)
247
+ .attr('y', 0)
248
+ .attr('width', _d => _d.width)
249
+ .attr('height', _d => _d.height)
250
+ })
236
251
  }
237
252
 
238
253
  function highlight ({ selection, ids, fullChartParams }: {
@@ -270,6 +285,8 @@ function highlight ({ selection, ids, fullChartParams }: {
270
285
  export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName: string, {
271
286
  selection,
272
287
  computedData$,
288
+ visibleComputedData$,
289
+ existedSeriesLabels$,
273
290
  SeriesDataMap$,
274
291
  GroupDataMap$,
275
292
  fullParams$,
@@ -278,86 +295,199 @@ export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName
278
295
  gridGraphicTransform$,
279
296
  gridAxesSize$,
280
297
  gridHighlight$,
298
+ gridContainer$,
299
+ isSeriesPositionSeprate$,
281
300
  event$
282
301
  }) => {
283
302
  const destroy$ = new Subject()
284
303
 
285
304
  const clipPathID = getUniID(pluginName, 'clipPath-box')
305
+ const pathGClassName = getClassName(pluginName, 'pathG')
306
+ const pathClassName = getClassName(pluginName, 'path')
286
307
 
287
- const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
288
- .append('g')
289
- .attr('clip-path', `url(#${clipPathID})`)
290
- const defsSelection: d3.Selection<SVGDefsElement, ComputedDatumGrid, any, any> = axisSelection.append('defs')
291
- const graphicGSelection: d3.Selection<SVGGElement, any, any, any> = axisSelection.append('g')
292
- let graphicSelection: d3.Selection<SVGGElement, any, any, any> | undefined
293
- const pathSelection$: Subject<d3.Selection<SVGPathElement, ComputedDatumGrid, any, any>> = new Subject()
294
- // .style('transform', 'translate(0px, 0px) scale(1)')
295
-
296
- gridAxesTransform$
297
- .pipe(
298
- takeUntil(destroy$),
299
- map(d => d.value),
300
- distinctUntilChanged()
301
- ).subscribe(d => {
302
- axisSelection
303
- .style('transform', d)
304
- })
305
-
306
- gridGraphicTransform$
307
- .pipe(
308
- takeUntil(destroy$),
309
- switchMap(async d => d.value),
310
- distinctUntilChanged()
311
- ).subscribe(d => {
312
- graphicGSelection
313
- .transition()
314
- .duration(50)
315
- .style('transform', d)
316
- })
308
+ // const seriesSelection$ = computedData$.pipe(
309
+ // takeUntil(destroy$),
310
+ // distinctUntilChanged((a, b) => {
311
+ // // 只有當series的數量改變時,才重新計算
312
+ // return a.length === b.length
313
+ // }),
314
+ // map((computedData, i) => {
315
+ // return selection
316
+ // .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${seriesClassName}`)
317
+ // .data(computedData, d => d[0] ? d[0].seriesIndex : i)
318
+ // .join(
319
+ // enter => {
320
+ // return enter
321
+ // .append('g')
322
+ // .classed(seriesClassName, true)
323
+ // .each((d, i, g) => {
324
+ // const axesSelection = d3.select(g[i])
325
+ // .selectAll<SVGGElement, ComputedDatumGrid[]>(`g.${axesClassName}`)
326
+ // .data([i])
327
+ // .join(
328
+ // enter => {
329
+ // return enter
330
+ // .append('g')
331
+ // .classed(axesClassName, true)
332
+ // .attr('clip-path', `url(#${clipPathID})`)
333
+ // .each((d, i, g) => {
334
+ // const defsSelection = d3.select(g[i])
335
+ // .selectAll<SVGDefsElement, any>('defs')
336
+ // .data([i])
337
+ // .join('defs')
338
+
339
+ // const graphicGSelection = d3.select(g[i])
340
+ // .selectAll<SVGGElement, any>('g')
341
+ // .data([i])
342
+ // .join('g')
343
+ // .classed(graphicClassName, true)
344
+ // })
345
+ // },
346
+ // update => update,
347
+ // exit => exit.remove()
348
+ // )
349
+ // })
350
+ // },
351
+ // update => update,
352
+ // exit => exit.remove()
353
+ // )
354
+ // })
355
+ // )
317
356
 
318
- // const axisSize$ = gridAxisSizeObservable({
319
- // dataFormatter$,
320
- // layout$
357
+ // combineLatest({
358
+ // seriesSelection: seriesSelection$,
359
+ // gridContainer: gridContainer$
360
+ // }).pipe(
361
+ // takeUntil(destroy$),
362
+ // switchMap(async d => d)
363
+ // ).subscribe(data => {
364
+ // data.seriesSelection
365
+ // .transition()
366
+ // .attr('transform', (d, i) => {
367
+ // const translate = data.gridContainer[i].translate
368
+ // const scale = data.gridContainer[i].scale
369
+ // return `translate(${translate[0]}, ${translate[1]}) scale(${scale[0]}, ${scale[1]})`
370
+ // })
321
371
  // })
322
372
 
323
- const zeroY$ = computedData$.pipe(
324
- map(d => d[0] && d[0][0]
325
- ? d[0][0].axisY - d[0][0].axisYFromZero
326
- : 0),
373
+
374
+ // const axesSelection$ = combineLatest({
375
+ // seriesSelection: seriesSelection$,
376
+ // gridAxesTransform: gridAxesTransform$
377
+ // }).pipe(
378
+ // takeUntil(destroy$),
379
+ // switchMap(async d => d),
380
+ // map(data => {
381
+ // return data.seriesSelection
382
+ // .select<SVGGElement>(`g.${axesClassName}`)
383
+ // .style('transform', data.gridAxesTransform.value)
384
+ // })
385
+ // )
386
+ // const defsSelection$ = axesSelection$.pipe(
387
+ // takeUntil(destroy$),
388
+ // map(axesSelection => {
389
+ // return axesSelection.select<SVGDefsElement>('defs')
390
+ // })
391
+ // )
392
+ // const graphicGSelection$ = combineLatest({
393
+ // axesSelection: axesSelection$,
394
+ // gridGraphicTransform: gridGraphicTransform$
395
+ // }).pipe(
396
+ // takeUntil(destroy$),
397
+ // switchMap(async d => d),
398
+ // map(data => {
399
+ // const graphicGSelection = data.axesSelection
400
+ // .select<SVGGElement>(`g.${graphicClassName}`)
401
+ // graphicGSelection
402
+ // .transition()
403
+ // .duration(50)
404
+ // .style('transform', data.gridGraphicTransform.value)
405
+ // return graphicGSelection
406
+ // })
407
+ // )
408
+
409
+ const {
410
+ seriesSelection$,
411
+ axesSelection$,
412
+ defsSelection$,
413
+ graphicGSelection$
414
+ } = gridSelectionsObservable({
415
+ selection,
416
+ pluginName,
417
+ clipPathID,
418
+ existedSeriesLabels$,
419
+ gridContainer$,
420
+ gridAxesTransform$,
421
+ gridGraphicTransform$
422
+ })
423
+
424
+ const zeroYArr$ = visibleComputedData$.pipe(
425
+ // map(d => d[0] && d[0][0]
426
+ // ? d[0][0].axisY - d[0][0].axisYFromZero
427
+ // : 0),
428
+ map(data => {
429
+ return data.map(d => {
430
+ return d[0] ? d[0].axisY - d[0].axisYFromZero : 0
431
+ })
432
+ }),
327
433
  distinctUntilChanged()
328
434
  )
329
435
 
330
- const barWidth$ = new Observable<number>(subscriber => {
331
- combineLatest({
332
- computedData: computedData$,
333
- params: fullParams$,
334
- axisSize: gridAxesSize$
335
- }).pipe(
336
- switchMap(async d => d)
337
- ).subscribe(data => {
338
- const barWidth = calcBarWidth({
339
- axisWidth: data.axisSize.width,
340
- groupAmount: data.computedData[0] ? data.computedData[0].length : 0,
341
- barAmountOfGroup: data.computedData.length,
342
- barPadding: data.params.barPadding,
343
- barGroupPadding: data.params.barGroupPadding
344
- })
345
- subscriber.next(barWidth)
346
- })
436
+ const barWidth$ = combineLatest({
437
+ computedData: computedData$,
438
+ visibleComputedData: visibleComputedData$,
439
+ params: fullParams$,
440
+ gridAxesSize: gridAxesSize$,
441
+ isSeriesPositionSeprate: isSeriesPositionSeprate$
347
442
  }).pipe(
348
443
  takeUntil(destroy$),
349
- distinctUntilChanged()
444
+ switchMap(async d => d),
445
+ map(data => {
446
+ if (data.params.barWidth) {
447
+ return data.params.barWidth
448
+ } else if (data.isSeriesPositionSeprate) {
449
+ return calcBarWidth({
450
+ axisWidth: data.gridAxesSize.width,
451
+ groupAmount: data.computedData[0] ? data.computedData[0].length : 0,
452
+ barAmountOfGroup: 1,
453
+ barPadding: data.params.barPadding,
454
+ barGroupPadding: data.params.barGroupPadding
455
+ })
456
+ } else {
457
+ return calcBarWidth({
458
+ axisWidth: data.gridAxesSize.width,
459
+ groupAmount: data.computedData[0] ? data.computedData[0].length : 0,
460
+ barAmountOfGroup: data.visibleComputedData.length,
461
+ barPadding: data.params.barPadding,
462
+ barGroupPadding: data.params.barGroupPadding
463
+ })
464
+ }
465
+ })
350
466
  )
351
-
352
- const seriesLabels$ = computedData$.pipe(
467
+
468
+ const seriesLabels$ = visibleComputedData$.pipe(
353
469
  takeUntil(destroy$),
354
- map(data => data.map((d, i) => d[0] ? d[0].seriesLabel : String(i)))
470
+ map(data => {
471
+ const SeriesLabelSet: Set<string> = new Set()
472
+ data.forEach(d => {
473
+ d.forEach(_d => {
474
+ SeriesLabelSet.add(_d.seriesLabel)
475
+ })
476
+ })
477
+ return Array.from(SeriesLabelSet)
478
+ })
355
479
  )
356
480
 
357
- const groupLabels$ = computedData$.pipe(
481
+ const groupLabels$ = visibleComputedData$.pipe(
358
482
  takeUntil(destroy$),
359
483
  map(data => {
360
- return data[0] ? data[0].map(d => d.groupLabel) : []
484
+ const GroupLabelSet: Set<string> = new Set()
485
+ data.forEach(d => {
486
+ d.forEach(_d => {
487
+ GroupLabelSet.add(_d.groupLabel)
488
+ })
489
+ })
490
+ return Array.from(GroupLabelSet)
361
491
  })
362
492
  )
363
493
 
@@ -411,67 +541,26 @@ export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName
411
541
  distinctUntilChanged()
412
542
  )
413
543
 
414
- const transposedData$ = computedData$.pipe(
415
- takeUntil(destroy$),
416
- map(data => {
417
- // 取得原始陣列的維度
418
- const rows = data.length;
419
- const cols = data.reduce((prev, current) => {
420
- return Math.max(prev, current.length)
421
- }, 0)
422
-
423
- // 初始化轉換後的陣列
424
- const transposedArray: typeof data = new Array(cols).fill(null).map(() => new Array(rows).fill(null))
425
-
426
- // 遍歷原始陣列,進行轉換
427
- for (let i = 0; i < rows; i++) {
428
- for (let j = 0; j < cols; j++) {
429
- transposedArray[j][i] = data[i][j]
430
- }
431
- }
432
-
433
- return transposedArray
434
- })
435
- )
544
+ //
436
545
 
437
- const barData$ = transposedData$.pipe(
546
+ combineLatest({
547
+ defsSelection: defsSelection$,
548
+ gridAxesSize: gridAxesSize$,
549
+ }).pipe(
438
550
  takeUntil(destroy$),
439
- map(data => {
440
- const linearGradientIds = data.length
441
- ? data[0].map(d => getUniID(pluginName, `lineargradient-${d.seriesLabel}`))
442
- : []
443
- return data.map(d => {
444
- return d.map((_d, _i) => {
445
- return <BarDatumGrid>{
446
- linearGradientId: linearGradientIds[_i],
447
- ..._d
448
- }
449
- })
450
- })
451
- })
452
- )
453
-
454
- gridAxesSize$.pipe(
455
- takeUntil(destroy$)
551
+ switchMap(async d => d)
456
552
  ).subscribe(data => {
457
553
  const clipPathData = [{
458
554
  id: clipPathID,
459
- width: data.width,
460
- height: data.height
555
+ width: data.gridAxesSize.width,
556
+ height: data.gridAxesSize.height
461
557
  }]
462
558
  renderClipPath({
463
- defsSelection,
559
+ defsSelection: data.defsSelection,
464
560
  clipPathData
465
561
  })
466
562
  })
467
563
 
468
- // const SeriesDataMap$ = computedData$.pipe(
469
- // map(d => makeGridSeriesDataMap(d))
470
- // )
471
-
472
- // const GroupDataMap$ = computedData$.pipe(
473
- // map(d => makeGridGroupDataMap(d))
474
- // )
475
564
 
476
565
  const highlightTarget$ = fullChartParams$.pipe(
477
566
  takeUntil(destroy$),
@@ -479,10 +568,39 @@ export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName
479
568
  distinctUntilChanged()
480
569
  )
481
570
 
571
+ const barSelection$ = new Subject<d3.Selection<SVGPathElement, ComputedDatumGrid, SVGGElement, unknown>>()
572
+
573
+ const linearGradientIds$ = seriesLabels$.pipe(
574
+ takeUntil(destroy$),
575
+ map(d => d.map((d, i) => {
576
+ return getUniID(pluginName, `lineargradient-${d}`)
577
+ }))
578
+ )
579
+
580
+ const barData$ = combineLatest({
581
+ linearGradientIds: linearGradientIds$,
582
+ computedData: computedData$
583
+ }).pipe(
584
+ takeUntil(destroy$),
585
+ switchMap(async d => d),
586
+ map(data => {
587
+ return data.computedData.map((series, seriesIndex) => {
588
+ return series.map((_d, _i) => {
589
+ return <BarDatumGrid>{
590
+ linearGradientId: data.linearGradientIds[seriesIndex],
591
+ ..._d
592
+ }
593
+ })
594
+ })
595
+ })
596
+ )
597
+
482
598
  combineLatest({
483
- barData: barData$,
599
+ graphicGSelection: graphicGSelection$,
600
+ defsSelection: defsSelection$,
484
601
  computedData: computedData$,
485
- zeroY: zeroY$,
602
+ barData: barData$,
603
+ zeroYArr: zeroYArr$,
486
604
  groupLabels: groupLabels$,
487
605
  barScale: barScale$,
488
606
  params: fullParams$,
@@ -492,34 +610,38 @@ export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName
492
610
  delayGroup: delayGroup$,
493
611
  transitionItem: transitionItem$,
494
612
  SeriesDataMap: SeriesDataMap$,
495
- GroupDataMap: GroupDataMap$
613
+ GroupDataMap: GroupDataMap$,
614
+ isSeriesPositionSeprate: isSeriesPositionSeprate$
496
615
  }).pipe(
497
616
  takeUntil(destroy$),
498
- // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
499
617
  switchMap(async (d) => d),
500
618
  ).subscribe(data => {
501
- const pathSelection = renderTriangleBars({
502
- selection: graphicGSelection,
619
+
620
+ const barSelection = renderTriangleBars({
621
+ graphicGSelection: data.graphicGSelection,
622
+ pathGClassName,
623
+ pathClassName,
503
624
  barData: data.barData,
504
- zeroY: data.zeroY,
625
+ zeroYArr: data.zeroYArr,
505
626
  groupLabels: data.groupLabels,
506
627
  barScale: data.barScale,
507
628
  params: data.params,
508
629
  chartParams: data.chartParams,
509
630
  barWidth: data.barWidth,
510
631
  delayGroup: data.delayGroup,
511
- transitionItem: data.transitionItem
632
+ transitionItem: data.transitionItem,
633
+ isSeriesPositionSeprate: data.isSeriesPositionSeprate
512
634
  })
513
635
  renderLinearGradient({
514
- defsSelection,
636
+ defsSelection: data.defsSelection,
515
637
  barData: data.barData,
516
638
  params: data.params
517
639
  })
518
640
 
519
- pathSelection!
641
+ barSelection!
520
642
  .on('mouseover', (event, datum) => {
521
643
  event.stopPropagation()
522
-
644
+
523
645
  event$.next({
524
646
  type: 'grid',
525
647
  eventName: 'mouseover',
@@ -594,18 +716,12 @@ export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName
594
716
  })
595
717
  })
596
718
 
597
- pathSelection$.next(pathSelection)
719
+ barSelection$.next(barSelection!)
598
720
  })
599
721
 
600
- // const datumList$ = computedData$.pipe(
601
- // takeUntil(destroy$),
602
- // map(d => d.flat())
603
- // )
604
- // const highlight$ = highlightObservable({ datumList$, fullChartParams$, event$: event$ })
605
- const highlightSubscription = gridHighlight$.subscribe()
606
722
 
607
723
  combineLatest({
608
- pathSelection: pathSelection$,
724
+ barSelection: barSelection$,
609
725
  highlight: gridHighlight$,
610
726
  fullChartParams: fullChartParams$
611
727
  }).pipe(
@@ -613,7 +729,7 @@ export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName
613
729
  switchMap(async d => d)
614
730
  ).subscribe(data => {
615
731
  highlight({
616
- selection: data.pathSelection,
732
+ selection: data.barSelection,
617
733
  ids: data.highlight,
618
734
  fullChartParams: data.fullChartParams
619
735
  })
@@ -621,6 +737,5 @@ export const createBaseBarsTriangle: BasePluginFn<BaseBarsContext> = (pluginName
621
737
 
622
738
  return () => {
623
739
  destroy$.next(undefined)
624
- highlightSubscription.unsubscribe()
625
740
  }
626
741
  }