@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
@@ -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
  }