@orbcharts/plugins-basic 3.0.0-alpha.26 → 3.0.0-alpha.28

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,10 +5,11 @@ import type {
5
5
  BarsPluginParams,
6
6
  BarStackPluginParams,
7
7
  BarsTrianglePluginParams,
8
- GroupingAxisParams,
8
+ GroupAxisParams,
9
9
  ValueAxisParams,
10
10
  ValueStackAxisParams,
11
- ScalingAreaParams } from './types'
11
+ ScalingAreaParams,
12
+ GridLegendParams } from './types'
12
13
 
13
14
  export const DEFAULT_LINES_PLUGIN_PARAMS: LinesPluginParams = {
14
15
  lineCurve: 'curveLinear',
@@ -55,7 +56,7 @@ export const DEFAULT_BARS_TRIANGLE_PLUGIN_PARAMS: BarsTrianglePluginParams = {
55
56
  linearGradientOpacity: [1, 0]
56
57
  }
57
58
 
58
- export const DEFAULT_GROUPING_AXIS_PLUGIN_PARAMS: GroupingAxisParams = {
59
+ export const DEFAULT_GROUPING_AXIS_PLUGIN_PARAMS: GroupAxisParams = {
59
60
  // labelAnchor: 'start',
60
61
  labelOffset: [0, 0],
61
62
  labelColorType: 'primary',
@@ -92,4 +93,18 @@ export const DEFAULT_VALUE_STACK_AXIS_PLUGIN_PARAMS: ValueStackAxisParams = DEFA
92
93
 
93
94
  export const DEFAULT_SCALING_AREA_PLUGIN_PARAMS: ScalingAreaParams = {
94
95
 
95
- }
96
+ }
97
+
98
+ export const DEFAULT_GRID_LEGEND_PARAMS: GridLegendParams = {
99
+ position: 'right',
100
+ justify: 'end',
101
+ padding: 28,
102
+ // offset: [0, 0],
103
+ backgroundFill: 'none',
104
+ backgroundStroke: 'none',
105
+ gap: 10,
106
+ listRectWidth: 14,
107
+ listRectHeight: 14,
108
+ listRectRadius: 0,
109
+ // highlightEvent: false
110
+ }
package/src/grid/index.ts CHANGED
@@ -5,6 +5,7 @@ export { Bars } from './plugins/Bars'
5
5
  export { BarStack } from './plugins/BarStack'
6
6
  export { BarsTriangle } from './plugins/BarsTriangle'
7
7
  export { Dots } from './plugins/Dots'
8
+ export { GridLegend } from './plugins/GridLegend'
8
9
  export { GroupAxis } from './plugins/GroupAxis'
9
10
  export { ValueAxis } from './plugins/ValueAxis'
10
11
  export { ValueStackAxis } from './plugins/ValueStackAxis'
@@ -0,0 +1,40 @@
1
+ import * as d3 from 'd3'
2
+ import {
3
+ combineLatest,
4
+ map,
5
+ switchMap,
6
+ takeUntil,
7
+ Observable,
8
+ Subject } from 'rxjs'
9
+ import {
10
+ defineGridPlugin } from '@orbcharts/core'
11
+ import { DEFAULT_GRID_LEGEND_PARAMS } from '../defaults'
12
+ import { createBaseLegend } from '../../base/BaseLegend'
13
+
14
+ const pluginName = 'GridLegend'
15
+
16
+ export const GridLegend = defineGridPlugin(pluginName, DEFAULT_GRID_LEGEND_PARAMS)(({ selection, rootSelection, observer, subject }) => {
17
+
18
+ const destroy$ = new Subject()
19
+
20
+ const seriesLabels$: Observable<string[]> = observer.SeriesDataMap$.pipe(
21
+ takeUntil(destroy$),
22
+ map(data => {
23
+ return Array.from(data.keys())
24
+ })
25
+ )
26
+
27
+ const unsubscribeBaseLegend = createBaseLegend(pluginName, {
28
+ rootSelection,
29
+ seriesLabels$,
30
+ fullParams$: observer.fullParams$,
31
+ layout$: observer.layout$,
32
+ fullChartParams$: observer.fullChartParams$
33
+ })
34
+
35
+ return () => {
36
+ destroy$.next(undefined)
37
+ unsubscribeBaseLegend()
38
+ }
39
+ })
40
+
@@ -15,7 +15,7 @@ import type {
15
15
  DataFormatterGrid,
16
16
  ChartParams,
17
17
  TransformData } from '@orbcharts/core'
18
- import type { GroupingAxisParams } from '../types'
18
+ import type { GroupAxisParams } from '../types'
19
19
  import { DEFAULT_GROUPING_AXIS_PLUGIN_PARAMS } from '../defaults'
20
20
  import { parseTickFormatValue } from '../../utils/d3Utils'
21
21
  import { getColor, getClassName } from '../../utils/orbchartsUtils'
@@ -32,7 +32,7 @@ const defaultTickSize = 6
32
32
 
33
33
  function renderPointAxis ({ selection, params, tickTextAlign, axisLabelAlign, gridAxesSize, fullDataFormatter, chartParams, groupScale, contentTransform }: {
34
34
  selection: d3.Selection<SVGGElement, any, any, any>,
35
- params: GroupingAxisParams
35
+ params: GroupAxisParams
36
36
  tickTextAlign: TextAlign
37
37
  axisLabelAlign: TextAlign
38
38
  gridAxesSize: { width: number, height: number }
@@ -44,19 +44,19 @@ function renderPointAxis ({ selection, params, tickTextAlign, axisLabelAlign, gr
44
44
  }) {
45
45
 
46
46
  const xAxisSelection = selection
47
- .selectAll<SVGGElement, GroupingAxisParams>(`g.${xAxisClassName}`)
47
+ .selectAll<SVGGElement, GroupAxisParams>(`g.${xAxisClassName}`)
48
48
  .data([params])
49
49
  .join('g')
50
50
  .classed(xAxisClassName, true)
51
51
 
52
52
  const axisLabelSelection = selection
53
- .selectAll<SVGGElement, GroupingAxisParams>(`g.${groupingLabelClassName}`)
53
+ .selectAll<SVGGElement, GroupAxisParams>(`g.${groupingLabelClassName}`)
54
54
  .data([params])
55
55
  .join('g')
56
56
  .classed(groupingLabelClassName, true)
57
57
  .each((d, i, g) => {
58
58
  const text = d3.select(g[i])
59
- .selectAll<SVGTextElement, GroupingAxisParams>('text')
59
+ .selectAll<SVGTextElement, GroupAxisParams>('text')
60
60
  .data([d])
61
61
  .join(
62
62
  enter => {
package/src/grid/types.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { ColorType } from '@orbcharts/core'
2
+ import type { BaseLegendParams } from '../base/BaseLegend'
2
3
 
3
4
  // export type LineType = 'line' | 'area' | 'gradientArea'
4
5
  // export type BarType = 'rect' | 'triangle'
@@ -55,7 +56,7 @@ export interface BarsTrianglePluginParams {
55
56
  linearGradientOpacity: [number, number]
56
57
  }
57
58
 
58
- export interface GroupingAxisParams {
59
+ export interface GroupAxisParams {
59
60
  // xLabel: string
60
61
  // labelAnchor: 'start' | 'end'
61
62
  labelOffset: [number, number]
@@ -100,3 +101,4 @@ export interface ScalingAreaParams {
100
101
 
101
102
  }
102
103
 
104
+ export interface GridLegendParams extends BaseLegendParams {}
@@ -6,6 +6,7 @@ import type {
6
6
  PieLabelsPluginParams,
7
7
  SeriesLegendParams } from './types'
8
8
 
9
+
9
10
  export const DEFAULT_BUBBLES_PLUGIN_PARAMS: BubblesPluginParams = {
10
11
  force: {
11
12
  strength: 0.03, // 泡泡引力
@@ -18,7 +19,7 @@ export const DEFAULT_BUBBLES_PLUGIN_PARAMS: BubblesPluginParams = {
18
19
  lineLengthMin: 4
19
20
  },
20
21
  highlightRIncrease: 0,
21
- scaleType: 'area'
22
+ bubbleScaleType: 'area'
22
23
  }
23
24
 
24
25
  export const DEFAULT_PIE_PLUGIN_PARAMS: PiePluginParams = {
@@ -87,7 +88,11 @@ export const DEFAULT_SERIES_LEGEND_PARAMS: SeriesLegendParams = {
87
88
  justify: 'end',
88
89
  padding: 28,
89
90
  // offset: [0, 0],
91
+ backgroundFill: 'none',
92
+ backgroundStroke: 'none',
90
93
  gap: 10,
91
- rectRadius: 0,
94
+ listRectWidth: 14,
95
+ listRectHeight: 14,
96
+ listRectRadius: 0,
92
97
  // highlightEvent: false
93
98
  }
@@ -17,7 +17,7 @@ import type {
17
17
  ComputedDatumSeries } from '@orbcharts/core'
18
18
  import {
19
19
  defineSeriesPlugin } from '@orbcharts/core'
20
- import type { BubblesPluginParams, ScaleType } from '../types'
20
+ import type { BubblesPluginParams, BubbleScaleType } from '../types'
21
21
  import { DEFAULT_BUBBLES_PLUGIN_PARAMS } from '../defaults'
22
22
  import { renderCircleText } from '../../utils/d3Graphics'
23
23
 
@@ -86,7 +86,7 @@ function createBubblesData ({ data, LastBubbleDataMap, graphicWidth, graphicHeig
86
86
  LastBubbleDataMap: Map<string, BubblesDatum>
87
87
  graphicWidth: number
88
88
  graphicHeight: number
89
- scaleType: ScaleType
89
+ scaleType: BubbleScaleType
90
90
  // highlightIds: string[]
91
91
  }) {
92
92
  const bubbleGroupR = Math.min(...[graphicWidth, graphicHeight]) / 2
@@ -363,7 +363,7 @@ export const Bubbles = defineSeriesPlugin('Bubbles', DEFAULT_BUBBLES_PLUGIN_PARA
363
363
 
364
364
  const scaleType$ = observer.fullParams$.pipe(
365
365
  takeUntil(destroy$),
366
- map(d => d.scaleType),
366
+ map(d => d.bubbleScaleType),
367
367
  distinctUntilChanged()
368
368
  )
369
369
 
@@ -8,90 +8,10 @@ import {
8
8
  Subject } from 'rxjs'
9
9
  import {
10
10
  defineSeriesPlugin } from '@orbcharts/core'
11
- import type {
12
- ChartParams } from '@orbcharts/core'
13
- import type { SeriesLegendParams } from '../types'
14
11
  import { DEFAULT_SERIES_LEGEND_PARAMS } from '../defaults'
15
- import { getSeriesColor, getClassName } from '../../utils/orbchartsUtils'
16
- import { measureTextWidth } from '../../utils/commonUtils'
17
-
18
-
19
- // 第1層 - 定位的容器(絕對位置)
20
- interface Position {
21
- x:number
22
- y:number
23
- }
24
-
25
- // 第2層 - 圖例列表
26
- interface LegendList {
27
- direction: 'row' | 'column'
28
- width: number
29
- height: number
30
- translateX:number
31
- translateY:number
32
- list: LegendItem[][]
33
- }
34
-
35
- // 第3層 - 圖例項目
36
- interface LegendItem {
37
- id: string // seriesLabel
38
- seriesLabel: string
39
- seriesIndex: number
40
- lineIndex: number
41
- itemIndex: number // 行內的item
42
- text: string
43
- itemWidth: number
44
- translateX: number
45
- translateY: number
46
- color: string
47
- // fontSize: number
48
- // rectRadius: number
49
- }
12
+ import { createBaseLegend } from '../../base/BaseLegend'
50
13
 
51
14
  const pluginName = 'SeriesLegend'
52
- const boxClassName = getClassName(pluginName, 'box')
53
- const legendListClassName = getClassName(pluginName, 'legend-list')
54
- const itemClassName = getClassName(pluginName, 'item')
55
-
56
- function renderSeriesLegend ({ itemSelection, lengendList, seriesLabel, fullParams, fullChartParams }: {
57
- itemSelection: d3.Selection<SVGGElement, LegendItem, any, any>
58
- lengendList: LegendList
59
- seriesLabel: string[]
60
- fullParams: SeriesLegendParams
61
- fullChartParams: ChartParams
62
- }) {
63
- itemSelection
64
- .each((d, i, g) => {
65
- // 方塊
66
- d3.select(g[i])
67
- .selectAll('rect')
68
- .data([d])
69
- .join('rect')
70
- .attr('width', fullChartParams.styles.textSize)
71
- .attr('height', fullChartParams.styles.textSize)
72
- .attr('fill', _d => _d.color)
73
- .attr('rx', fullParams.rectRadius)
74
- // 文字
75
- d3.select(g[i])
76
- .selectAll('text')
77
- .data([d])
78
- .join(
79
- enter => {
80
- return enter
81
- .append('text')
82
- .attr('dominant-baseline', 'hanging')
83
- },
84
- update => {
85
- return update
86
- },
87
- exit => exit.remove()
88
- )
89
- .attr('x', fullChartParams.styles.textSize * 1.5)
90
- .attr('font-size', fullChartParams.styles.textSize)
91
- .text(d => d.text)
92
- })
93
- }
94
-
95
15
 
96
16
  export const SeriesLegend = defineSeriesPlugin(pluginName, DEFAULT_SERIES_LEGEND_PARAMS)(({ selection, rootSelection, observer, subject }) => {
97
17
 
@@ -104,354 +24,17 @@ export const SeriesLegend = defineSeriesPlugin(pluginName, DEFAULT_SERIES_LEGEND
104
24
  })
105
25
  )
106
26
 
107
- const lineDirection$ = observer.fullParams$.pipe(
108
- takeUntil(destroy$),
109
- map(data => {
110
- return data.position === 'bottom' || data.position === 'top'
111
- ? 'row'
112
- : 'column'
113
- })
114
- )
115
-
116
- const lineMaxSize$ = combineLatest({
117
- fullParams: observer.fullParams$,
118
- layout: observer.layout$
119
- }).pipe(
120
- takeUntil(destroy$),
121
- map(data => {
122
- return data.fullParams.position === 'bottom' || data.fullParams.position === 'top'
123
- ? data.layout.rootWidth - 2 // 減2是避免完全貼到邊線上
124
- : data.layout.rootHeight - 2
125
- })
126
- )
127
-
128
- const boxPosition$ = combineLatest({
129
- layout: observer.layout$,
130
- fullParams: observer.fullParams$,
131
- }).pipe(
132
- takeUntil(destroy$),
133
- switchMap(async d => d),
134
- map(data => {
135
- let x = 0
136
- let y = 0
137
- if (data.fullParams.position === 'bottom') {
138
- y = data.layout.rootHeight
139
- if (data.fullParams.justify === 'start') {
140
- x = 0
141
- } else if (data.fullParams.justify === 'center') {
142
- x = data.layout.rootWidth / 2
143
- } else if (data.fullParams.justify === 'end') {
144
- x = data.layout.rootWidth
145
- }
146
- } else if (data.fullParams.position === 'right') {
147
- x = data.layout.rootWidth
148
- if (data.fullParams.justify === 'start') {
149
- y = 0
150
- } else if (data.fullParams.justify === 'center') {
151
- y = data.layout.rootHeight / 2
152
- } else if (data.fullParams.justify === 'end') {
153
- y = data.layout.rootHeight
154
- }
155
- } else if (data.fullParams.position === 'top') {
156
- y = 0
157
- if (data.fullParams.justify === 'start') {
158
- x = 0
159
- } else if (data.fullParams.justify === 'center') {
160
- x = data.layout.rootWidth / 2
161
- } else if (data.fullParams.justify === 'end') {
162
- x = data.layout.rootWidth
163
- }
164
- } else if (data.fullParams.position === 'left') {
165
- x = 0
166
- if (data.fullParams.justify === 'start') {
167
- y = 0
168
- } else if (data.fullParams.justify === 'center') {
169
- y = data.layout.rootHeight / 2
170
- } else if (data.fullParams.justify === 'end') {
171
- y = data.layout.rootHeight
172
- }
173
- }
174
-
175
- return {
176
- x,
177
- y
178
- }
179
- })
180
- )
181
-
182
- const boxSelection$: Observable<d3.Selection<SVGGElement, Position, any, any>> = boxPosition$.pipe(
183
- takeUntil(destroy$),
184
- map(data => {
185
-
186
- return rootSelection
187
- .selectAll<SVGGElement, Position>(`g.${boxClassName}`)
188
- .data([data])
189
- .join(
190
- enter => {
191
- return enter
192
- .append('g')
193
- .classed(boxClassName, true)
194
- .attr('transform', d => `translate(${d.x}, ${d.y})`)
195
- },
196
- update => {
197
- return update
198
- .transition()
199
- .attr('transform', d => `translate(${d.x}, ${d.y})`)
200
- },
201
- exit => exit.remove()
202
- )
203
- })
204
- )
205
-
206
- const lengendList$: Observable<LegendList> = combineLatest({
207
- layout: observer.layout$,
208
- fullParams: observer.fullParams$,
209
- fullChartParams: observer.fullChartParams$,
210
- seriesLabels: seriesLabels$,
211
- lineDirection: lineDirection$,
212
- lineMaxSize: lineMaxSize$
213
- }).pipe(
214
- takeUntil(destroy$),
215
- switchMap(async d => d),
216
- map(data => {
217
- const list: LegendItem[][] = data.seriesLabels.reduce((prev: LegendItem[][], current, currentIndex) => {
218
- const textWidth = measureTextWidth(current, data.fullChartParams.styles.textSize)
219
- const itemWidth = (data.fullChartParams.styles.textSize * 1.5) + textWidth
220
- const color = getSeriesColor(currentIndex, data.fullChartParams)
221
- const lastItem: LegendItem | null = prev[0] && prev[0][0]
222
- ? prev[prev.length - 1][prev[prev.length - 1].length - 1]
223
- : null
224
-
225
- const { translateX, translateY, lineIndex, itemIndex } = ((_data, _prev, _lastItem) => {
226
- let translateX = 0
227
- let translateY = 0
228
- let lineIndex = 0
229
- let itemIndex = 0
230
-
231
- if (_data.lineDirection === 'column') {
232
- let tempTranslateY = _lastItem
233
- ? _lastItem.translateY + _data.fullChartParams.styles.textSize + _data.fullParams.gap
234
- : 0
235
-
236
- if ((tempTranslateY + _data.fullChartParams.styles.textSize) > _data.lineMaxSize) {
237
- // 換行
238
- lineIndex = _lastItem.lineIndex + 1
239
- itemIndex = 0
240
- translateY = 0
241
- // 前一行最寬寬度
242
- const maxItemWidthInLastLine = _prev[_prev.length - 1].reduce((p, c) => {
243
- return c.itemWidth > p ? c.itemWidth : p
244
- }, 0)
245
- translateX = _lastItem.translateX + maxItemWidthInLastLine + _data.fullParams.gap
246
- } else {
247
- lineIndex = _lastItem ? _lastItem.lineIndex : 0
248
- itemIndex = _lastItem ? _lastItem.itemIndex + 1 : 0
249
- translateY = tempTranslateY
250
- translateX = _lastItem ? _lastItem.translateX : 0
251
- }
252
- } else {
253
- let tempTranslateX = _lastItem
254
- ? _lastItem.translateX + _lastItem.itemWidth + _data.fullParams.gap
255
- : 0
256
- if ((tempTranslateX + itemWidth) > _data.lineMaxSize) {
257
- // 換行
258
- lineIndex = _lastItem.lineIndex + 1
259
- itemIndex = 0
260
- translateX = 0
261
- } else {
262
- lineIndex = _lastItem ? _lastItem.lineIndex : 0
263
- itemIndex = _lastItem ? _lastItem.itemIndex + 1 : 0
264
- translateX = tempTranslateX
265
- }
266
- translateY = (_data.fullChartParams.styles.textSize + _data.fullParams.gap) * lineIndex
267
- }
268
-
269
- return { translateX, translateY, lineIndex, itemIndex }
270
- })(data, prev, lastItem)
271
-
272
- if (!prev[lineIndex]) {
273
- prev[lineIndex] = []
274
- }
275
-
276
- prev[lineIndex].push({
277
- id: current,
278
- seriesLabel: current,
279
- seriesIndex: currentIndex,
280
- lineIndex,
281
- itemIndex,
282
- text: current,
283
- itemWidth,
284
- translateX,
285
- translateY,
286
- color,
287
- })
288
-
289
- return prev
290
- }, [])
291
-
292
- // 依list計算出來的排序位置來計算整體的偏移位置
293
- const { width, height, translateX, translateY } = ((_data, _list) => {
294
- let width = 0
295
- let height = 0
296
- let translateX = 0
297
- let translateY = 0
298
-
299
- if (!_list.length || !_list[0].length) {
300
- return { width, height, translateX, translateY }
301
- }
302
-
303
- const firstLineLastItem = _list[0][_list[0].length - 1]
304
- if (_data.lineDirection === 'column') {
305
- width = _list.reduce((p, c) => {
306
- const maxWidthInLine = c.reduce((_p, _c) => {
307
- // 找出最寬的寬度
308
- return _c.itemWidth > _p ? _c.itemWidth : _p
309
- }, 0)
310
- // 每行寬度加總
311
- return p + maxWidthInLine
312
- }, 0)
313
- height = firstLineLastItem.translateY + _data.fullChartParams.styles.textSize + _data.fullParams.gap
314
- } else {
315
- width = firstLineLastItem.translateX + firstLineLastItem.itemWidth
316
- height = (_data.fullChartParams.styles.textSize * _list.length) + (_data.fullParams.gap * (_list.length - 1))
317
- }
318
-
319
- if (_data.fullParams.position === 'left') {
320
- if (_data.fullParams.justify === 'start') {
321
- translateX = _data.fullParams.padding
322
- translateY = _data.fullParams.padding
323
- } else if (_data.fullParams.justify === 'center') {
324
- translateX = _data.fullParams.padding
325
- translateY = - height / 2
326
- } else if (_data.fullParams.justify === 'end') {
327
- translateX = _data.fullParams.padding
328
- translateY = - height - _data.fullParams.padding
329
- }
330
- } else if (_data.fullParams.position === 'right') {
331
- if (_data.fullParams.justify === 'start') {
332
- translateX = - width - _data.fullParams.padding
333
- translateY = _data.fullParams.padding
334
- } else if (_data.fullParams.justify === 'center') {
335
- translateX = - width - _data.fullParams.padding
336
- translateY = - height / 2
337
- } else if (_data.fullParams.justify === 'end') {
338
- translateX = - width - _data.fullParams.padding
339
- translateY = - height - _data.fullParams.padding
340
- }
341
- } else if (_data.fullParams.position === 'top') {
342
- if (_data.fullParams.justify === 'start') {
343
- translateX = _data.fullParams.padding
344
- translateY = _data.fullParams.padding
345
- } else if (_data.fullParams.justify === 'center') {
346
- translateX = - width / 2
347
- translateY = _data.fullParams.padding
348
- } else if (_data.fullParams.justify === 'end') {
349
- translateX = - width - _data.fullParams.padding
350
- translateY = _data.fullParams.padding
351
- }
352
- } else {
353
- if (_data.fullParams.justify === 'start') {
354
- translateX = _data.fullParams.padding
355
- translateY = - height - _data.fullParams.padding
356
- } else if (_data.fullParams.justify === 'center') {
357
- translateX = - width / 2
358
- translateY = - height - _data.fullParams.padding
359
- } else if (_data.fullParams.justify === 'end') {
360
- translateX = - width - _data.fullParams.padding
361
- translateY = - height - _data.fullParams.padding
362
- }
363
- }
364
-
365
- // translateX += _data.fullParams.offset[0]
366
- // translateY += _data.fullParams.offset[1]
367
-
368
- return { width, height, translateX, translateY }
369
- })(data, list)
370
-
371
- return {
372
- direction: data.lineDirection,
373
- width,
374
- height,
375
- translateX,
376
- translateY,
377
- list
378
- }
379
- })
380
- )
381
-
382
- const lengendListSelection$ = combineLatest({
383
- boxSelection: boxSelection$,
384
- fullParams: observer.fullParams$,
385
- lengendList: lengendList$
386
- }).pipe(
387
- takeUntil(destroy$),
388
- switchMap(async d => d),
389
- map(data => {
390
- return data.boxSelection
391
- .selectAll<SVGGElement, SeriesLegendParams>('g')
392
- .data([data.lengendList])
393
- .join(
394
- enter => {
395
- return enter
396
- .append('g')
397
- .classed(legendListClassName, true)
398
- .attr('transform', d => `translate(${d.translateX}, ${d.translateY})`)
399
- },
400
- update => {
401
- return update
402
- .transition()
403
- .attr('transform', d => `translate(${d.translateX}, ${d.translateY})`)
404
- },
405
- exit => exit.remove()
406
- )
407
- })
408
- )
409
-
410
- const itemSelection$ = lengendListSelection$.pipe(
411
- takeUntil(destroy$),
412
- map(lengendListSelection => {
413
- const legendListData = lengendListSelection.data()
414
- const data = legendListData[0] ? legendListData[0].list.flat() : []
415
-
416
- return lengendListSelection
417
- .selectAll<SVGGElement, string>(`g.${itemClassName}`)
418
- .data(data)
419
- .join(
420
- enter => {
421
- return enter
422
- .append('g')
423
- .classed(itemClassName, true)
424
- .attr('cursor', 'default')
425
- },
426
- update => update,
427
- exit => exit.remove()
428
- )
429
- .attr('transform', (d, i) => {
430
- return `translate(${d.translateX}, ${d.translateY})`
431
- })
432
- })
433
- )
434
-
435
- combineLatest({
436
- itemSelection: itemSelection$,
437
- lengendList: lengendList$,
438
- seriesLabels: seriesLabels$,
439
- fullParams: observer.fullParams$,
440
- fullChartParams: observer.fullChartParams$
441
- }).pipe(
442
- takeUntil(destroy$),
443
- switchMap(async d => d),
444
- ).subscribe(data => {
445
- renderSeriesLegend({
446
- itemSelection: data.itemSelection,
447
- lengendList: data.lengendList,
448
- seriesLabel: data.seriesLabels,
449
- fullParams: data.fullParams,
450
- fullChartParams: data.fullChartParams
451
- })
27
+ const unsubscribeBaseLegend = createBaseLegend(pluginName, {
28
+ rootSelection,
29
+ seriesLabels$,
30
+ fullParams$: observer.fullParams$,
31
+ layout$: observer.layout$,
32
+ fullChartParams$: observer.fullChartParams$
452
33
  })
453
34
 
454
35
  return () => {
455
36
  destroy$.next(undefined)
37
+ unsubscribeBaseLegend()
456
38
  }
457
39
  })
40
+
@@ -1,6 +1,7 @@
1
1
  import type { ComputedDatumSeries, EventSeries, EventName, ColorType } from '@orbcharts/core'
2
+ import type { BaseLegendParams } from '../base/BaseLegend'
2
3
 
3
- export type ScaleType = 'area' | 'radius'
4
+ export type BubbleScaleType = 'area' | 'radius'
4
5
 
5
6
  export interface BubblesPluginParams {
6
7
  force: {
@@ -14,7 +15,7 @@ export interface BubblesPluginParams {
14
15
  lineLengthMin: number
15
16
  }
16
17
  highlightRIncrease: number
17
- scaleType: ScaleType
18
+ bubbleScaleType: BubbleScaleType
18
19
  }
19
20
 
20
21
  export interface PiePluginParams {
@@ -52,12 +53,4 @@ export interface PieLabelsPluginParams {
52
53
  labelColorType: ColorType
53
54
  }
54
55
 
55
- export interface SeriesLegendParams {
56
- position: 'top' | 'bottom' | 'left' | 'right'
57
- justify: 'start' | 'center' | 'end'
58
- padding: number
59
- // offset: [number, number]
60
- gap: number
61
- rectRadius: number
62
- // highlightEvent: boolean
63
- }
56
+ export interface SeriesLegendParams extends BaseLegendParams {}