@orbcharts/plugins-basic 3.0.0-alpha.26 → 3.0.0-alpha.28
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.
- package/dist/orbcharts-plugins-basic.es.js +5882 -5805
- package/dist/orbcharts-plugins-basic.umd.js +6 -6
- package/dist/src/base/BaseLegend.d.ts +15 -0
- package/dist/src/base/types.d.ts +3 -0
- package/dist/src/grid/defaults.d.ts +3 -2
- package/dist/src/grid/index.d.ts +1 -0
- package/dist/src/grid/plugins/GridLegend.d.ts +1 -0
- package/dist/src/grid/plugins/GroupAxis.d.ts +2 -2
- package/dist/src/grid/types.d.ts +4 -1
- package/dist/src/series/plugins/SeriesLegend.d.ts +1 -3
- package/dist/src/series/types.d.ts +4 -8
- package/package.json +2 -2
- package/src/base/BaseLegend.ts +543 -0
- package/src/base/types.ts +3 -0
- package/src/grid/defaults.ts +19 -4
- package/src/grid/index.ts +1 -0
- package/src/grid/plugins/GridLegend.ts +40 -0
- package/src/grid/plugins/GroupAxis.ts +5 -5
- package/src/grid/types.ts +3 -1
- package/src/series/defaults.ts +7 -2
- package/src/series/plugins/Bubbles.ts +3 -3
- package/src/series/plugins/SeriesLegend.ts +9 -426
- package/src/series/types.ts +4 -11
- package/src/utils/orbchartsUtils.ts +13 -6
package/src/grid/defaults.ts
CHANGED
@@ -5,10 +5,11 @@ import type {
|
|
5
5
|
BarsPluginParams,
|
6
6
|
BarStackPluginParams,
|
7
7
|
BarsTrianglePluginParams,
|
8
|
-
|
8
|
+
GroupAxisParams,
|
9
9
|
ValueAxisParams,
|
10
10
|
ValueStackAxisParams,
|
11
|
-
ScalingAreaParams
|
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:
|
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 {
|
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:
|
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,
|
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,
|
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,
|
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
|
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 {}
|
package/src/series/defaults.ts
CHANGED
@@ -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
|
-
|
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
|
-
|
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,
|
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:
|
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.
|
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 {
|
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
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
+
|
package/src/series/types.ts
CHANGED
@@ -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
|
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
|
-
|
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 {}
|