You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 17:48:22