Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pie): 'itemRadiusScale' function added for pie series #19435

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/chart/pie/PieSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ interface PieItemStyleOption<TCbParams = never> extends ItemStyleOption<TCbParam

export interface PieCallbackDataParams extends CallbackDataParams {
percent: number
maxValue?: number
Pashted marked this conversation as resolved.
Show resolved Hide resolved
sum?: number
}

export interface PieStateOption<TCbParams = never> {
Expand Down Expand Up @@ -107,6 +109,7 @@ export interface PieSeriesOption extends
type?: 'pie'

roseType?: 'radius' | 'area'
itemRadiusScale?: (dataParams: PieCallbackDataParams) => number
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest considering another name than radius because it may cause confusion with emphasis.scaleSize, which is the enlarging animation when emphasizing. You are welcomed to suggest a new name.

Copy link
Author

@Pashted Pashted Dec 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scalePercent
itemStyle.radius
itemStyle.scalePercent (preferred)

also it would be an itemStyle.scaleSize. but I think (not 100% sure yet =), i will lose the ability to use nonlinear functions. because percentages are calculated on the lib side in this case

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personnally perfer itemStyle.radiusPercent to avoid using scaleXXX, but not with very strong preference. If only itemStyle.xxx is used but no series.xxx, I think we should skip the callback function.

In ECharts, for options support both value and percentage form (like radius, we usually use strings like '30%' to represent percentage. But since we don't support number type in our case, I think a 0-1 number type is acceptable.


center?: string | number | (string | number)[]

Expand Down Expand Up @@ -179,12 +182,13 @@ class PieSeriesModel extends SeriesModel<PieSeriesOption> {
*/
getDataParams(dataIndex: number): PieCallbackDataParams {
const data = this.getData();
const valueDim = data.mapDimension('value');
// update seats when data is changed
const dataInner = innerData(data);
let seats = dataInner.seats;
if (!seats) {
const valueList: number[] = [];
data.each(data.mapDimension('value'), function (value: number) {
data.each(valueDim, function (value: number) {
valueList.push(value);
});
seats = dataInner.seats = getPercentSeats(valueList, data.hostModel.get('percentPrecision'));
Expand All @@ -193,6 +197,15 @@ class PieSeriesModel extends SeriesModel<PieSeriesOption> {
// seats may be empty when sum is 0
params.percent = seats[dataIndex] || 0;
params.$vars.push('percent');

const itemRadiusScale = data.hostModel.get('itemRadiusScale');
if (typeof itemRadiusScale === 'function') {
/* useful for custom percentage calculations in formatters etc. */
params.maxValue = data.getDataExtent(valueDim)[1];
params.$vars.push('maxValue');
params.sum = data.getSum(valueDim);
params.$vars.push('sum');
}
return params;
}

Expand Down
18 changes: 15 additions & 3 deletions src/chart/pie/pieLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export default function pieLayout(
const clockwise = seriesModel.get('clockwise');

const roseType = seriesModel.get('roseType');
const itemRadiusScale = seriesModel.get('itemRadiusScale');
const stillShowZeroSum = seriesModel.get('stillShowZeroSum');

// [0...max]
Expand Down Expand Up @@ -188,6 +189,19 @@ export default function pieLayout(
actualEndAngle = endAngle - halfPadAngle;
}

let outerRadius = r;
if (typeof itemRadiusScale === 'function') {
// calculate the radius of the current pie item based on the scale from the user-defined function
let scale = itemRadiusScale(seriesModel.getDataParams(idx)) || 0;
// scale should always be between 0 and 1
scale = Math.max(0, Math.min(scale, 1));
// r0 is used here to scale radius properly in case of 'donut' style.
outerRadius = (r - r0) * scale + r0;
}
else if (roseType) {
outerRadius = linearMap(value, extent, [r0, r]);
}

data.setItemLayout(idx, {
angle: angle,
startAngle: actualStartAngle,
Expand All @@ -196,9 +210,7 @@ export default function pieLayout(
cx: cx,
cy: cy,
r0: r0,
r: roseType
? linearMap(value, extent, [r0, r])
: r
r: outerRadius
});

currentAngle = endAngle;
Expand Down
291 changes: 291 additions & 0 deletions test/pie-itemRadiusScale.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.