From 4ce776ccfe0cd0b89bc1c2434367fd448d2f4288 Mon Sep 17 00:00:00 2001 From: "linghao.su" Date: Sun, 3 Sep 2023 19:37:12 +0800 Subject: [PATCH] feat(pie): add padAngle for pie --- src/chart/pie/PieSeries.ts | 3 + src/chart/pie/pieLayout.ts | 72 ++++++++++++++++---- test/pie-pad-angle.html | 133 +++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 13 deletions(-) create mode 100644 test/pie-pad-angle.html diff --git a/src/chart/pie/PieSeries.ts b/src/chart/pie/PieSeries.ts index 5d0fd4ade6..13e220dc58 100644 --- a/src/chart/pie/PieSeries.ts +++ b/src/chart/pie/PieSeries.ts @@ -113,6 +113,8 @@ export interface PieSeriesOption extends clockwise?: boolean startAngle?: number endAngle?: number | 'auto' + padAngle?: number; + minAngle?: number minShowLabelAngle?: number @@ -219,6 +221,7 @@ class PieSeriesModel extends SeriesModel { clockwise: true, startAngle: 90, endAngle: 'auto', + padAngle: 0, // 最小角度改为0 minAngle: 0, diff --git a/src/chart/pie/pieLayout.ts b/src/chart/pie/pieLayout.ts index e81afae432..2acdcda394 100644 --- a/src/chart/pie/pieLayout.ts +++ b/src/chart/pie/pieLayout.ts @@ -94,10 +94,14 @@ export default function pieLayout( let startAngle = -seriesModel.get('startAngle') * RADIAN; let endAngle = seriesModel.get('endAngle'); + const padAngle = seriesModel.get('padAngle') * RADIAN; + endAngle = endAngle === 'auto' ? startAngle - PI2 : -endAngle * RADIAN; const minAngle = seriesModel.get('minAngle') * RADIAN; + const minAndPadAngle = minAngle + padAngle; + let validDataCount = 0; data.each(valueDim, function (value: number) { !isNaN(value) && validDataCount++; @@ -118,6 +122,7 @@ export default function pieLayout( const dir = clockwise ? 1 : -1; const angles = [startAngle, endAngle]; + const halfPadAngle = dir * padAngle / 2; normalizeArcAngles(angles, !clockwise); [startAngle, endAngle] = angles; @@ -159,19 +164,34 @@ export default function pieLayout( angle = angleRange / validDataCount; } - if (angle < minAngle) { - angle = minAngle; - restAngle -= minAngle; + + if (angle < minAndPadAngle) { + angle = minAndPadAngle; + restAngle -= minAndPadAngle; } else { valueSumLargerThanMinAngle += value; } const endAngle = currentAngle + dir * angle; + + // calculate display angle + let actualStartAngle = 0; + let actualEndAngle = 0; + + if (padAngle > angle) { + actualStartAngle = currentAngle + dir * angle / 2; + actualEndAngle = actualStartAngle; + } + else { + actualStartAngle = currentAngle + halfPadAngle; + actualEndAngle = endAngle - halfPadAngle; + } + data.setItemLayout(idx, { angle: angle, - startAngle: currentAngle, - endAngle: endAngle, + startAngle: actualStartAngle, + endAngle: actualEndAngle, clockwise: clockwise, cx: cx, cy: cy, @@ -184,19 +204,32 @@ export default function pieLayout( currentAngle = endAngle; }); - // Some sector is constrained by minAngle + // Some sector is constrained by minAngle and padAngle // Rest sectors needs recalculate angle if (restAngle < PI2 && validDataCount) { // Average the angle if rest angle is not enough after all angles is - // Constrained by minAngle + // Constrained by minAngle and padAngle if (restAngle <= 1e-3) { const angle = angleRange / validDataCount; data.each(valueDim, function (value: number, idx: number) { if (!isNaN(value)) { const layout = data.getItemLayout(idx); layout.angle = angle; - layout.startAngle = startAngle + dir * idx * angle; - layout.endAngle = startAngle + dir * (idx + 1) * angle; + + let actualStartAngle = 0; + let actualEndAngle = 0; + + if (angle < padAngle) { + actualStartAngle = startAngle + dir * (idx + 1 / 2) * angle; + actualEndAngle = actualStartAngle; + } + else { + actualStartAngle = startAngle + dir * idx * angle + halfPadAngle; + actualEndAngle = startAngle + dir * (idx + 1) * angle - halfPadAngle; + } + + layout.startAngle = actualStartAngle; + layout.endAngle = actualEndAngle; } }); } @@ -206,10 +239,23 @@ export default function pieLayout( data.each(valueDim, function (value: number, idx: number) { if (!isNaN(value)) { const layout = data.getItemLayout(idx); - const angle = layout.angle === minAngle - ? minAngle : value * unitRadian; - layout.startAngle = currentAngle; - layout.endAngle = currentAngle + dir * angle; + const angle = layout.angle === minAndPadAngle + ? minAndPadAngle : value * unitRadian; + + let actualStartAngle = 0; + let actualEndAngle = 0; + + if (angle < padAngle) { + actualStartAngle = currentAngle + dir * angle / 2; + actualEndAngle = actualStartAngle; + } + else { + actualStartAngle = currentAngle + halfPadAngle; + actualEndAngle = currentAngle + dir * angle - halfPadAngle; + } + + layout.startAngle = actualStartAngle; + layout.endAngle = actualEndAngle; currentAngle += dir * angle; } }); diff --git a/test/pie-pad-angle.html b/test/pie-pad-angle.html new file mode 100644 index 0000000000..a458e6f6bc --- /dev/null +++ b/test/pie-pad-angle.html @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file