如何在Syncfusion环形图中实现仅圆角无拱形的分段效果?
解决Syncfusion环形图分段仅圆角而非圆拱形的问题
默认的cornerStyle="bothCurve"会把环形分段的内外弧两端都渲染成圆拱形,这不是我们要的纯角落圆角效果。要实现这个需求,核心是重写环形图的分段渲染逻辑,自定义路径生成方式——把原来的圆拱替换为仅在分段的两个直角角落添加圆角。
实现思路
- 自定义
CustomDoughnutSeries继承自DoughnutSeries,指定自定义渲染器 - 自定义
CustomDoughnutSeriesRenderer继承自DoughnutSeriesRenderer,重写CreateSegment方法返回自定义分段 - 自定义
CustomDoughnutSegment继承自DoughnutSegment,重写OnRender方法,修改路径绘制逻辑,仅在分段的起始和结束角落添加圆角
代码示例(以WPF为例,其他平台逻辑通用)
// 自定义环形系列 public class CustomDoughnutSeries : DoughnutSeries { protected override ChartSeriesRenderer CreateRenderer() { return new CustomDoughnutSeriesRenderer(); } } // 自定义系列渲染器 public class CustomDoughnutSeriesRenderer : DoughnutSeriesRenderer { protected override ChartSegment CreateSegment() { return new CustomDoughnutSegment(); } } // 自定义分段,核心修改在这里 public class CustomDoughnutSegment : DoughnutSegment { private double _cornerRadius = 5; // 自定义圆角半径,可按需调整 public override void OnRender(ChartRenderContext context) { var center = Center; var outerRadius = OuterRadius; var innerRadius = InnerRadius; var startAngle = StartAngle; var endAngle = EndAngle; // 计算分段四个顶点坐标 var outerStartPoint = CalculatePoint(center, outerRadius, startAngle); var outerEndPoint = CalculatePoint(center, outerRadius, endAngle); var innerStartPoint = CalculatePoint(center, innerRadius, startAngle); var innerEndPoint = CalculatePoint(center, innerRadius, endAngle); var path = new PathGeometry(); var figure = new PathFigure(); // 从外弧起点的圆角位置开始 figure.StartPoint = new Point( outerStartPoint.X + _cornerRadius * Math.Cos(DegToRad(startAngle + 90)), outerStartPoint.Y + _cornerRadius * Math.Sin(DegToRad(startAngle + 90)) ); // 绘制外弧(跳过原圆拱逻辑) var outerArc = new ArcSegment { Point = new Point( outerEndPoint.X - _cornerRadius * Math.Cos(DegToRad(endAngle + 90)), outerEndPoint.Y - _cornerRadius * Math.Sin(DegToRad(endAngle + 90)) ), Size = new Size(outerRadius, outerRadius), RotationAngle = 0, IsLargeArc = endAngle - startAngle > 180, SweepDirection = SweepDirection.Clockwise }; figure.Segments.Add(outerArc); // 绘制外角落的圆角弧 var outerCornerArc = new ArcSegment { Point = innerEndPoint, Size = new Size(_cornerRadius, _cornerRadius), RotationAngle = 0, IsLargeArc = false, SweepDirection = SweepDirection.Clockwise }; figure.Segments.Add(outerCornerArc); // 绘制内弧 var innerArc = new ArcSegment { Point = new Point( innerStartPoint.X + _cornerRadius * Math.Cos(DegToRad(startAngle - 90)), innerStartPoint.Y + _cornerRadius * Math.Sin(DegToRad(startAngle - 90)) ), Size = new Size(innerRadius, innerRadius), RotationAngle = 0, IsLargeArc = endAngle - startAngle > 180, SweepDirection = SweepDirection.Counterclockwise }; figure.Segments.Add(innerArc); // 绘制内角落的圆角弧,闭合路径 var innerCornerArc = new ArcSegment { Point = figure.StartPoint, Size = new Size(_cornerRadius, _cornerRadius), RotationAngle = 0, IsLargeArc = false, SweepDirection = SweepDirection.Clockwise }; figure.Segments.Add(innerCornerArc); figure.IsClosed = true; path.Figures.Add(figure); // 填充和描边绘制 context.DrawPath(Fill, Stroke, path); } // 角度转弧度工具方法 private double DegToRad(double deg) { return deg * Math.PI / 180; } // 计算圆上点坐标工具方法 private Point CalculatePoint(Point center, double radius, double angle) { var rad = DegToRad(angle); return new Point(center.X + radius * Math.Cos(rad), center.Y + radius * Math.Sin(rad)); } }
使用方式
在XAML中替换原DoughnutSeries为自定义系列即可:
<syncfusion:SfCircularChart> <local:CustomDoughnutSeries ItemsSource="{Binding Data}" XBindingPath="Category" YBindingPath="Value" /> </syncfusion:SfCircularChart>
关键说明
_cornerRadius可根据视觉需求调整圆角大小- 核心逻辑是替换了默认的圆拱连接方式,仅在分段的两个直角角落添加小半径圆角弧
- 其他平台(MAUI、ASP.NET Core等)逻辑完全一致,仅需适配对应平台的绘图API(比如MAUI用
PathF替代PathGeometry)
内容的提问来源于stack exchange,提问作者upendra
相关产品推荐
相关产品推荐

