@orbcharts/plugins-basic 3.0.0-alpha.63 → 3.0.0-alpha.65
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 +5699 -5476
- package/dist/orbcharts-plugins-basic.umd.js +16 -10
- package/dist/src/base/BaseGroupAxis.d.ts +1 -0
- package/dist/src/noneData/index.d.ts +0 -1
- package/dist/src/noneData/types.d.ts +1 -1
- package/dist/src/series/types.d.ts +6 -1
- package/package.json +2 -2
- package/src/base/BaseGroupAxis.ts +35 -20
- package/src/base/BaseLegend.ts +1 -0
- package/src/grid/plugins/GroupAxis.ts +1 -0
- package/src/multiGrid/plugins/MultiGroupAxis.ts +1 -0
- package/src/multiGrid/plugins/OverlappingValueAxes.ts +3 -0
- package/src/multiGrid/plugins/OverlappingValueStackAxes.ts +1 -0
- package/src/noneData/index.ts +1 -1
- package/src/noneData/plugins/Tooltip.ts +26 -9
- package/src/noneData/types.ts +1 -1
- package/src/series/defaults.ts +15 -10
- package/src/series/plugins/Pie.ts +12 -4
- package/src/series/plugins/PieLabels.ts +357 -63
- package/src/series/plugins/Rose.ts +17 -8
- package/src/series/plugins/RoseLabels.ts +290 -87
- package/src/series/types.ts +9 -5
@@ -27,24 +27,38 @@ import { seriesCenterSelectionObservable } from '../seriesObservables'
|
|
27
27
|
interface RenderDatum {
|
28
28
|
pieDatum: PieDatum
|
29
29
|
arcIndex: number
|
30
|
-
|
30
|
+
arcLabels: string[]
|
31
|
+
lineStartX: number
|
32
|
+
lineStartY: number
|
33
|
+
lineStartMouseoverX: number
|
34
|
+
lineStartMouseoverY: number
|
31
35
|
x: number
|
32
36
|
y: number
|
33
37
|
mouseoverX: number
|
34
38
|
mouseoverY: number
|
39
|
+
textWidth: number, // 文字寬度
|
40
|
+
collisionShiftX: number // 避免碰撞的位移
|
41
|
+
collisionShiftY: number
|
42
|
+
quadrant: number // 第幾象限
|
35
43
|
}
|
36
44
|
|
37
45
|
const pluginName = 'RoseLabels'
|
46
|
+
const labelGClassName = getClassName(pluginName, 'label-g')
|
47
|
+
const lineGClassName = getClassName(pluginName, 'line-g')
|
38
48
|
const textClassName = getClassName(pluginName, 'text')
|
39
49
|
|
40
|
-
|
50
|
+
const pieOuterCentroid = 2
|
51
|
+
|
52
|
+
function makeRenderData ({ pieData, labelCentroid, arcScaleType, maxValue, axisWidth, outerRadius, lineStartCentroid, fullParams }: {
|
41
53
|
pieData: PieDatum[]
|
42
54
|
// arc: d3.Arc<any, d3.DefaultArcObject>
|
43
|
-
|
55
|
+
labelCentroid: number
|
44
56
|
arcScaleType: 'area' | 'radius'
|
45
57
|
maxValue: number
|
46
58
|
axisWidth: number
|
47
59
|
outerRadius: number
|
60
|
+
lineStartCentroid: number
|
61
|
+
fullParams: RoseLabelsParams
|
48
62
|
}): RenderDatum[] {
|
49
63
|
|
50
64
|
const outerRadiusWidth = (axisWidth / 2) * outerRadius
|
@@ -71,118 +85,286 @@ function makeRenderData ({ pieData, centroid, arcScaleType, maxValue, axisWidth,
|
|
71
85
|
|
72
86
|
const [_x, _y] = arc!.centroid(d as any)
|
73
87
|
const [_mouseoverX, _mouseoverY] = [_x, _y]
|
88
|
+
const arcLabel = fullParams.labelFn(d.data)
|
74
89
|
return {
|
75
90
|
pieDatum: d,
|
76
91
|
arcIndex: i,
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
92
|
+
arcLabels: arcLabel.split('\n'),
|
93
|
+
lineStartX: _x * lineStartCentroid,
|
94
|
+
lineStartY: _y * lineStartCentroid,
|
95
|
+
lineStartMouseoverX: _mouseoverX * lineStartCentroid,
|
96
|
+
lineStartMouseoverY: _mouseoverY * lineStartCentroid,
|
97
|
+
x: _x * labelCentroid!,
|
98
|
+
y: _y * labelCentroid!,
|
99
|
+
mouseoverX: _mouseoverX * labelCentroid!,
|
100
|
+
mouseoverY: _mouseoverY * labelCentroid!,
|
101
|
+
textWidth: 0, // 後面再做計算
|
102
|
+
collisionShiftX: 0, // 後面再做計算
|
103
|
+
collisionShiftY: 0, // 後面再做計算
|
104
|
+
quadrant: _x >= 0 && _y <= 0
|
105
|
+
? 1
|
106
|
+
: _x < 0 && _y <= 0
|
107
|
+
? 2
|
108
|
+
: _x < 0 && _y > 0
|
109
|
+
? 3
|
110
|
+
: 4
|
82
111
|
}
|
83
112
|
})
|
84
113
|
.filter(d => d.pieDatum.data.visible)
|
85
114
|
}
|
86
115
|
|
87
116
|
// 繪製圓餅圖
|
88
|
-
function renderLabel (
|
117
|
+
function renderLabel ({ labelGSelection, data, fullParams, fullChartParams, textSizePx }: {
|
118
|
+
labelGSelection: d3.Selection<SVGGElement, undefined, any, any>
|
119
|
+
data: RenderDatum[]
|
120
|
+
fullParams: RoseLabelsParams
|
121
|
+
fullChartParams: ChartParams
|
122
|
+
textSizePx: number
|
123
|
+
}) {
|
89
124
|
// console.log(data)
|
90
125
|
// let update = this.gSelection.selectAll('g').data(pieData)
|
91
|
-
|
92
|
-
.selectAll<
|
126
|
+
const textSelection = labelGSelection
|
127
|
+
.selectAll<SVGTextElement, RenderDatum>('text')
|
93
128
|
.data(data, d => d.pieDatum.id)
|
94
|
-
|
95
|
-
.append<SVGPathElement>('text')
|
129
|
+
.join('text')
|
96
130
|
.classed(textClassName, true)
|
97
|
-
let exit = update.exit()
|
98
|
-
|
99
|
-
enter
|
100
|
-
.append('text')
|
101
|
-
|
102
|
-
const labelSelection = update.merge(enter)
|
103
|
-
labelSelection
|
104
131
|
.attr('font-weight', 'bold')
|
105
|
-
.attr('text-anchor', '
|
106
|
-
.style('dominant-baseline', '
|
132
|
+
.attr('text-anchor', d => d.quadrant == 1 || d.quadrant == 4 ? 'start' : 'end')
|
133
|
+
.style('dominant-baseline', d => d.quadrant == 1 || d.quadrant == 2 ? 'auto' : 'hanging')
|
107
134
|
// .style('pointer-events', 'none')
|
108
135
|
.style('cursor', d => fullChartParams.highlightTarget && fullChartParams.highlightTarget != 'none'
|
109
136
|
? 'pointer'
|
110
137
|
: 'none')
|
111
138
|
// .text((d, i) => d.arcLabel)
|
112
|
-
.text(d =>
|
139
|
+
// .text(d => fullParams.labelFn(d.pieDatum.data))
|
113
140
|
.attr('font-size', fullChartParams.styles.textSize)
|
114
|
-
.attr('fill', (d, i) => getDatumColor({ datum: d.pieDatum.data, colorType:
|
141
|
+
.attr('fill', (d, i) => getDatumColor({ datum: d.pieDatum.data, colorType: fullParams.labelColorType, fullChartParams }))
|
142
|
+
.each((d, i, n) => {
|
143
|
+
const textNode = d3.select<SVGTextElement, RenderDatum>(n[i])
|
144
|
+
.selectAll('tspan')
|
145
|
+
.data(d.arcLabels)
|
146
|
+
.join('tspan')
|
147
|
+
.attr('x', 0)
|
148
|
+
.attr('y', (_d, _i) => d.quadrant == 1 || d.quadrant == 2
|
149
|
+
? - (d.arcLabels.length - 1 - _i) * textSizePx
|
150
|
+
: _i * textSizePx)
|
151
|
+
.text(d => d)
|
152
|
+
})
|
153
|
+
textSelection
|
115
154
|
.transition()
|
116
155
|
.attr('transform', (d) => {
|
117
156
|
return 'translate(' + d.x + ',' + d.y + ')'
|
118
157
|
})
|
119
158
|
// .on('end', () => initHighlight({ labelSelection, data, fullChartParams }))
|
120
|
-
exit.remove()
|
121
159
|
|
122
160
|
// 如無新增資料則不用等動畫
|
123
161
|
// if (enter.size() == 0) {
|
124
162
|
// this.initHighlight()
|
125
163
|
// }
|
126
164
|
|
127
|
-
return
|
165
|
+
return textSelection
|
128
166
|
}
|
129
167
|
|
130
|
-
//
|
131
|
-
|
132
|
-
|
133
|
-
//
|
134
|
-
|
135
|
-
//
|
136
|
-
|
137
|
-
|
138
|
-
//
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
168
|
+
// 獲取每個文字元素的邊界框並檢查是否重疊
|
169
|
+
function resolveCollisions(textSelection: d3.Selection<SVGTextElement, RenderDatum, any, any>, data: RenderDatum[], textSizePx: number) {
|
170
|
+
const textArray = textSelection.nodes();
|
171
|
+
const padding = textSizePx // 調整文字間的間距
|
172
|
+
|
173
|
+
// 存儲每個標籤的當前位置
|
174
|
+
const positions = textArray.map((textNode, i) => {
|
175
|
+
const bbox = textNode.getBBox();
|
176
|
+
// const arcCentroid = arc.centroid(data[i]);
|
177
|
+
const arcCentroid = [data[i].x, data[i].y];
|
178
|
+
return {
|
179
|
+
node: textNode,
|
180
|
+
x: arcCentroid[0],
|
181
|
+
y: arcCentroid[1],
|
182
|
+
width: bbox.width,
|
183
|
+
height: bbox.height
|
184
|
+
}
|
185
|
+
})
|
186
|
+
|
187
|
+
// 順時針碰撞檢測(只處理 2、4 象限,將較後面的文字碰撞時往外偏移)
|
188
|
+
for (let i = 0; i < positions.length; i++) {
|
189
|
+
const a = positions[i]
|
190
|
+
|
191
|
+
for (let j = i + 1; j < positions.length; j++) {
|
192
|
+
const b = positions[j]
|
193
|
+
|
194
|
+
// 記錄文字寬度
|
195
|
+
data[i].textWidth = a.width
|
196
|
+
|
197
|
+
const ax = a.x + data[i].collisionShiftX
|
198
|
+
const ay = a.y + data[i].collisionShiftY
|
199
|
+
const bx = b.x + data[j].collisionShiftX
|
200
|
+
const by = b.y + data[j].collisionShiftY
|
201
|
+
|
202
|
+
// 檢查是否重疊
|
203
|
+
if (!(ax + a.width / 2 < bx - b.width / 2 ||
|
204
|
+
ax - a.width / 2 > bx + b.width / 2 ||
|
205
|
+
ay + a.height / 2 < by - b.height / 2 ||
|
206
|
+
ay - a.height / 2 > by + b.height / 2)) {
|
207
|
+
|
208
|
+
if (data[j].quadrant == 2) {
|
209
|
+
const moveDown = (by > ay)
|
210
|
+
? -padding * 2
|
211
|
+
: -padding
|
212
|
+
data[j].collisionShiftY += moveDown // 由後一個累加高度
|
213
|
+
} else if (data[j].quadrant == 4) {
|
214
|
+
const moveDown = (by > ay)
|
215
|
+
? padding
|
216
|
+
: padding * 2
|
217
|
+
data[j].collisionShiftY += moveDown // 由後一個累加高度
|
218
|
+
}
|
219
|
+
}
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
// 逆時針碰撞檢測(只處理 1、3 象限,將較前面的文字碰撞時往外偏移)
|
224
|
+
for (let i = positions.length - 1; i >= 0; i--) {
|
225
|
+
const a = positions[i]
|
226
|
+
|
227
|
+
for (let j = i - 1; j >= 0; j--) {
|
228
|
+
const b = positions[j]
|
229
|
+
|
230
|
+
// 記錄文字寬度
|
231
|
+
data[i].textWidth = a.width
|
232
|
+
|
233
|
+
const ax = a.x + data[i].collisionShiftX
|
234
|
+
const ay = a.y + data[i].collisionShiftY
|
235
|
+
const bx = b.x + data[j].collisionShiftX
|
236
|
+
const by = b.y + data[j].collisionShiftY
|
237
|
+
|
238
|
+
// 檢查是否重疊
|
239
|
+
if (!(ax + a.width / 2 < bx - b.width / 2 ||
|
240
|
+
ax - a.width / 2 > bx + b.width / 2 ||
|
241
|
+
ay + a.height / 2 < by - b.height / 2 ||
|
242
|
+
ay - a.height / 2 > by + b.height / 2)) {
|
243
|
+
|
244
|
+
if (data[j].quadrant == 1) {
|
245
|
+
const moveDown = (by > ay)
|
246
|
+
? -padding * 2
|
247
|
+
: -padding
|
248
|
+
data[j].collisionShiftY += moveDown // 由前一個累加高度
|
249
|
+
} else if (data[j].quadrant == 3) {
|
250
|
+
const moveDown = (by > ay)
|
251
|
+
? padding
|
252
|
+
: padding * 2
|
253
|
+
data[j].collisionShiftY += moveDown // 由前一個累加高度
|
254
|
+
}
|
255
|
+
}
|
256
|
+
}
|
257
|
+
}
|
258
|
+
|
259
|
+
// 全部算完再來 render
|
260
|
+
textSelection
|
261
|
+
.data(data)
|
262
|
+
.transition()
|
263
|
+
.attr('transform', (d) => {
|
264
|
+
return `translate(${d.x + d.collisionShiftX},${d.y + d.collisionShiftY})`
|
265
|
+
})
|
266
|
+
}
|
267
|
+
|
268
|
+
function renderLine ({ lineGSelection, data, fullParams, fullChartParams }: {
|
269
|
+
lineGSelection: d3.Selection<SVGGElement, undefined, any, any>
|
270
|
+
data: RenderDatum[]
|
271
|
+
fullParams: RoseLabelsParams
|
272
|
+
fullChartParams: ChartParams
|
273
|
+
}) {
|
274
|
+
|
275
|
+
// 只顯示在有偏移的標籤
|
276
|
+
const filteredData = data.filter(d => d.collisionShiftX || d.collisionShiftY)
|
277
|
+
|
278
|
+
// 添加標籤的連接線
|
279
|
+
const lines = lineGSelection.selectAll<SVGPolylineElement, RenderDatum>("polyline")
|
280
|
+
.data(filteredData, d => d.pieDatum.id)
|
281
|
+
.join("polyline")
|
282
|
+
.attr("stroke", d => getDatumColor({ datum: d.pieDatum.data, colorType: fullParams.labelColorType, fullChartParams }))
|
283
|
+
.attr("stroke-width", 1)
|
284
|
+
.attr("fill", "none")
|
285
|
+
.attr("points", (d) => {
|
286
|
+
return [[d.lineStartX, d.lineStartY], [d.lineStartX, d.lineStartY]] as any // 畫出從弧線中心到延伸點的線
|
287
|
+
})
|
288
|
+
lines
|
289
|
+
.transition()
|
290
|
+
.attr("points", (d) => {
|
291
|
+
// const pos = arc.centroid(d) // 起點:弧線的中心點
|
292
|
+
// const outerPos = [pos[0] * 2.5, pos[1] * 2.5] // 外部延伸的點(乘以倍率來延長線段)
|
293
|
+
|
294
|
+
let lineEndX = d.x + d.collisionShiftX
|
295
|
+
let lineEndY = d.y + d.collisionShiftY
|
296
|
+
// if (d.lineStartX >= Math.abs(d.lineStartY)) {
|
297
|
+
// lineEndX -= d.textWidth / 2
|
298
|
+
// } else if (d.lineStartX <= - Math.abs(d.lineStartY)) {
|
299
|
+
// lineEndX += d.textWidth / 2
|
300
|
+
// }
|
301
|
+
|
302
|
+
return [[lineEndX, lineEndY], [d.lineStartX, d.lineStartY]] as any // 畫出從弧線中心到延伸點的線
|
303
|
+
})
|
304
|
+
|
305
|
+
return lines
|
306
|
+
}
|
307
|
+
|
308
|
+
function highlight ({ textSelection, lineSelection, ids, fullChartParams }: {
|
309
|
+
textSelection: d3.Selection<SVGTextElement, RenderDatum, any, any>
|
310
|
+
lineSelection: d3.Selection<SVGPolylineElement, RenderDatum, any, any>
|
149
311
|
ids: string[]
|
150
312
|
fullChartParams: ChartParams
|
151
313
|
}) {
|
152
|
-
|
314
|
+
textSelection.interrupt('highlight')
|
315
|
+
lineSelection.interrupt('highlight')
|
153
316
|
|
154
317
|
if (!ids.length) {
|
155
|
-
|
156
|
-
.transition()
|
318
|
+
textSelection
|
319
|
+
.transition('highlight')
|
157
320
|
.duration(200)
|
158
321
|
.attr('transform', (d) => {
|
159
|
-
return
|
322
|
+
return `translate(${d.x + d.collisionShiftX},${d.y + d.collisionShiftY})`
|
160
323
|
})
|
161
324
|
.style('opacity', 1)
|
325
|
+
lineSelection
|
326
|
+
.transition('highlight')
|
327
|
+
.duration(200)
|
328
|
+
.style('opacity', 1)
|
162
329
|
return
|
163
330
|
}
|
164
331
|
|
165
|
-
|
166
|
-
const segment = d3.select<
|
332
|
+
textSelection.each((d, i, n) => {
|
333
|
+
const segment = d3.select<SVGTextElement, RenderDatum>(n[i])
|
167
334
|
|
168
335
|
if (ids.includes(d.pieDatum.data.id)) {
|
169
336
|
segment
|
170
337
|
.style('opacity', 1)
|
171
|
-
.transition()
|
338
|
+
.transition('highlight')
|
172
339
|
.duration(200)
|
173
340
|
.attr('transform', (d) => {
|
174
|
-
return
|
341
|
+
return `translate(${d.mouseoverX + d.collisionShiftX},${d.mouseoverY + d.collisionShiftY})`
|
175
342
|
})
|
176
343
|
} else {
|
177
344
|
segment
|
178
345
|
.style('opacity', fullChartParams.styles.unhighlightedOpacity)
|
179
|
-
.transition()
|
346
|
+
.transition('highlight')
|
180
347
|
.duration(200)
|
181
348
|
.attr('transform', (d) => {
|
182
|
-
return
|
349
|
+
return `translate(${d.x + d.collisionShiftX},${d.y + d.collisionShiftY})`
|
183
350
|
})
|
184
351
|
}
|
185
352
|
})
|
353
|
+
lineSelection.each((d, i, n) => {
|
354
|
+
const segment = d3.select<SVGPolylineElement, RenderDatum>(n[i])
|
355
|
+
|
356
|
+
if (ids.includes(d.pieDatum.data.id)) {
|
357
|
+
segment
|
358
|
+
.style('opacity', 1)
|
359
|
+
.transition('highlight')
|
360
|
+
.duration(200)
|
361
|
+
} else {
|
362
|
+
segment
|
363
|
+
.style('opacity', fullChartParams.styles.unhighlightedOpacity)
|
364
|
+
.transition('highlight')
|
365
|
+
.duration(200)
|
366
|
+
}
|
367
|
+
})
|
186
368
|
}
|
187
369
|
|
188
370
|
|
@@ -194,13 +376,22 @@ function createEachPieLabel (pluginName: string, context: {
|
|
194
376
|
// SeriesDataMap$: Observable<Map<string, ComputedDatumSeries[]>>
|
195
377
|
fullParams$: Observable<RoseLabelsParams>
|
196
378
|
fullChartParams$: Observable<ChartParams>
|
379
|
+
textSizePx$: Observable<number>
|
197
380
|
seriesHighlight$: Observable<ComputedDatumSeries[]>
|
198
381
|
seriesContainerPosition$: Observable<SeriesContainerPosition>
|
199
382
|
event$: Subject<EventSeries>
|
200
383
|
}) {
|
201
384
|
const destroy$ = new Subject()
|
202
385
|
|
203
|
-
|
386
|
+
context.containerSelection.selectAll('g').remove()
|
387
|
+
|
388
|
+
const lineGSelection: d3.Selection<SVGGElement, any, any, unknown> = context.containerSelection.append('g')
|
389
|
+
lineGSelection.classed(lineGClassName, true)
|
390
|
+
const labelGSelection: d3.Selection<SVGGElement, any, any, unknown> = context.containerSelection.append('g')
|
391
|
+
labelGSelection.classed(labelGClassName, true)
|
392
|
+
|
393
|
+
const textSelection$: Subject<d3.Selection<SVGTextElement, RenderDatum, any, any>> = new Subject()
|
394
|
+
const lineSelection$: Subject<d3.Selection<SVGPolylineElement, RenderDatum, any, any>> = new Subject()
|
204
395
|
let renderData: RenderDatum[] = []
|
205
396
|
|
206
397
|
const shorterSideWith$ = context.seriesContainerPosition$.pipe(
|
@@ -214,6 +405,16 @@ function createEachPieLabel (pluginName: string, context: {
|
|
214
405
|
distinctUntilChanged()
|
215
406
|
)
|
216
407
|
|
408
|
+
const lineStartCentroid$ = context.fullParams$.pipe(
|
409
|
+
takeUntil(destroy$),
|
410
|
+
map(d => {
|
411
|
+
return d.labelCentroid >= pieOuterCentroid
|
412
|
+
? pieOuterCentroid // 當 label在 pie的外側時,線條從 pie的邊緣開始
|
413
|
+
: d.labelCentroid // 當 label在 pie的內側時,線條從 label未偏移前的位置開始
|
414
|
+
|
415
|
+
})
|
416
|
+
)
|
417
|
+
|
217
418
|
combineLatest({
|
218
419
|
// layout: context.seriesContainerPosition$,
|
219
420
|
shorterSideWith: shorterSideWith$,
|
@@ -221,36 +422,13 @@ function createEachPieLabel (pluginName: string, context: {
|
|
221
422
|
maxValue: maxValue$,
|
222
423
|
fullParams: context.fullParams$,
|
223
424
|
fullChartParams: context.fullChartParams$,
|
425
|
+
textSizePx: context.textSizePx$,
|
426
|
+
lineStartCentroid: lineStartCentroid$
|
224
427
|
}).pipe(
|
225
428
|
takeUntil(destroy$),
|
226
429
|
switchMap(async (d) => d),
|
227
430
|
).subscribe(data => {
|
228
431
|
|
229
|
-
// const shorterSideWith = data.layout.width < data.layout.height ? data.layout.width : data.layout.height
|
230
|
-
|
231
|
-
// // 弧產生器 (d3.arc())
|
232
|
-
// const arc = makeD3Arc({
|
233
|
-
// axisWidth: shorterSideWith,
|
234
|
-
// innerRadius: 0,
|
235
|
-
// outerRadius: data.fullParams.outerRadius,
|
236
|
-
// padAngle: 0,
|
237
|
-
// cornerRadius: 0
|
238
|
-
// })
|
239
|
-
|
240
|
-
// const arcMouseover = makeD3Arc({
|
241
|
-
// axisWidth: shorterSideWith,
|
242
|
-
// innerRadius: 0,
|
243
|
-
// outerRadius: data.fullParams.outerRadiusWhileHighlight, // 外半徑變化
|
244
|
-
// padAngle: 0,
|
245
|
-
// cornerRadius: 0
|
246
|
-
// })
|
247
|
-
|
248
|
-
// const pieData = makePieData({
|
249
|
-
// data: data.containerVisibleComputedLayoutData,
|
250
|
-
// startAngle: data.fullParams.startAngle,
|
251
|
-
// endAngle: data.fullParams.endAngle
|
252
|
-
// })
|
253
|
-
|
254
432
|
const eachAngle = Math.PI * 2 / data.containerVisibleComputedLayoutData.length
|
255
433
|
|
256
434
|
const pieData = data.containerVisibleComputedLayoutData.map((d, i) => {
|
@@ -268,21 +446,44 @@ function createEachPieLabel (pluginName: string, context: {
|
|
268
446
|
|
269
447
|
renderData = makeRenderData({
|
270
448
|
pieData,
|
271
|
-
|
449
|
+
labelCentroid: data.fullParams.labelCentroid,
|
272
450
|
arcScaleType: data.fullParams.arcScaleType,
|
273
451
|
maxValue: data.maxValue,
|
274
452
|
axisWidth: data.shorterSideWith,
|
275
|
-
outerRadius: data.fullParams.outerRadius
|
453
|
+
outerRadius: data.fullParams.outerRadius,
|
454
|
+
lineStartCentroid: data.lineStartCentroid,
|
455
|
+
fullParams: data.fullParams
|
276
456
|
})
|
277
457
|
|
278
|
-
|
458
|
+
// 先移除線條,等偏移後再重新繪製
|
459
|
+
lineGSelection.selectAll('polyline').remove()
|
279
460
|
|
280
|
-
|
461
|
+
const textSelection = renderLabel({
|
462
|
+
labelGSelection,
|
463
|
+
data: renderData,
|
464
|
+
fullParams: data.fullParams,
|
465
|
+
fullChartParams: data.fullChartParams,
|
466
|
+
textSizePx: data.textSizePx
|
467
|
+
})
|
468
|
+
|
469
|
+
// 等 label 本身的 transition 結束後再進行碰撞檢測
|
470
|
+
setTimeout(() => {
|
471
|
+
// 偏移 label
|
472
|
+
resolveCollisions(textSelection, renderData, data.textSizePx)
|
473
|
+
|
474
|
+
const lineSelection = renderLine({ lineGSelection, data: renderData, fullParams: data.fullParams, fullChartParams: data.fullChartParams })
|
281
475
|
|
476
|
+
lineSelection$.next(lineSelection)
|
477
|
+
|
478
|
+
}, 1000)
|
479
|
+
|
480
|
+
textSelection$.next(textSelection)
|
481
|
+
|
282
482
|
})
|
283
483
|
|
284
484
|
combineLatest({
|
285
|
-
|
485
|
+
textSelection: textSelection$,
|
486
|
+
lineSelection: lineSelection$,
|
286
487
|
highlight: context.seriesHighlight$.pipe(
|
287
488
|
map(data => data.map(d => d.id))
|
288
489
|
),
|
@@ -292,7 +493,8 @@ function createEachPieLabel (pluginName: string, context: {
|
|
292
493
|
switchMap(async d => d)
|
293
494
|
).subscribe(data => {
|
294
495
|
highlight({
|
295
|
-
|
496
|
+
textSelection: data.textSelection,
|
497
|
+
lineSelection: data.lineSelection,
|
296
498
|
ids: data.highlight,
|
297
499
|
fullChartParams: data.fullChartParams,
|
298
500
|
})
|
@@ -348,6 +550,7 @@ export const RoseLabels = defineSeriesPlugin(pluginName, DEFAULT_ROSE_LABELS_PAR
|
|
348
550
|
// SeriesDataMap$: observer.SeriesDataMap$,
|
349
551
|
fullParams$: observer.fullParams$,
|
350
552
|
fullChartParams$: observer.fullChartParams$,
|
553
|
+
textSizePx$: observer.textSizePx$,
|
351
554
|
seriesHighlight$: observer.seriesHighlight$,
|
352
555
|
seriesContainerPosition$: containerPosition$,
|
353
556
|
event$: subject.event$,
|
package/src/series/types.ts
CHANGED
@@ -20,14 +20,16 @@ export interface BubblesParams {
|
|
20
20
|
|
21
21
|
export interface PieParams {
|
22
22
|
// padding: Padding
|
23
|
-
outerRadius: number
|
24
|
-
innerRadius: number
|
25
|
-
outerRadiusWhileHighlight: number
|
23
|
+
outerRadius: number
|
24
|
+
innerRadius: number
|
25
|
+
outerRadiusWhileHighlight: number
|
26
26
|
// label?: LabelStyle
|
27
27
|
// enterDuration: number
|
28
28
|
startAngle: number
|
29
29
|
endAngle: number
|
30
30
|
padAngle: number
|
31
|
+
strokeColorType: ColorType
|
32
|
+
strokeWidth: number
|
31
33
|
// padRadius: number
|
32
34
|
cornerRadius: number
|
33
35
|
}
|
@@ -55,10 +57,12 @@ export interface PieLabelsParams {
|
|
55
57
|
|
56
58
|
export interface RoseParams {
|
57
59
|
outerRadius: number
|
58
|
-
|
60
|
+
padAngle: number
|
61
|
+
strokeColorType: ColorType
|
62
|
+
strokeWidth: number
|
59
63
|
cornerRadius: number
|
60
64
|
arcScaleType: ArcScaleType
|
61
|
-
|
65
|
+
angleIncreaseWhileHighlight: number
|
62
66
|
}
|
63
67
|
|
64
68
|
export interface RoseLabelsParams {
|