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

Flutter:为Syncfusion DoughnutSeries图表添加环形标签

环形旋转标签的Doughnut图表实现问题

我使用Syncfusion的SfCircularChart实现了一个环形图,想要让外侧的标签随环形弧度旋转排列(沿环形切线方向对齐),但当前的标签是水平显示的,没有旋转效果。如果有其他Flutter图表包能实现该效果,也欢迎推荐。

当前代码如下:

SfCircularChart(
  annotations: [
    CircularChartAnnotation(
        height: '60%',
        width: '60%',
        widget: PhysicalModel(
          shape: BoxShape.circle,
          elevation: 10,
          color: Colors.white,
          child: Container(),
        )),
    CircularChartAnnotation(
        height: '60%',
        width: '60%',
        widget: PhysicalModel(
          shape: BoxShape.circle,
          elevation: 10,
          color: const Color.fromRGBO(230, 230, 230, 1),
          child: Container(),
        )),
    CircularChartAnnotation(
      widget: const Text(
        'Out of season',
      ),
    )
  ],
  series: <CircularSeries>[
    DoughnutSeries<TestData, String>(
      radius: '100',
      innerRadius: '70',
      dataSource: data,
      xValueMapper: (TestData data, _) => data.title,
      yValueMapper: (TestData data, _) => data.value,
      strokeColor: Colors.white,
      strokeWidth: 2,
      groupMode: CircularChartGroupMode.value,
      enableTooltip: false,
      dataLabelSettings: const DataLabelSettings(
        isVisible: true,
        labelAlignment: ChartDataLabelAlignment.top,
        alignment: ChartAlignment.near,
        labelPosition: ChartDataLabelPosition.outside,
        labelIntersectAction: LabelIntersectAction.shift,
        connectorLineSettings:
            ConnectorLineSettings(width: 0, length: '0'),
      ),
      pointColorMapper: (TestData data, _) => Colors.grey,
    )
  ],
);

List<TestData> data = [
  TestData('21.10', 1),
  TestData('22.10', 1),
  TestData('23.10', 1),
  TestData('24.10', 1),
  TestData('25.10', 1),
];

class TestData {
  TestData(this.title, this.value);
  final String title;
  final double value;
}

解决方案

1. 基于Syncfusion实现旋转标签

Syncfusion默认的DataLabelSettings不支持自动旋转对齐环形,但可以通过builder自定义标签,计算每个数据点的角度来旋转文本:

修改DoughnutSeries中的dataLabelSettings:

dataLabelSettings: DataLabelSettings(
  isVisible: true,
  labelPosition: ChartDataLabelPosition.outside,
  connectorLineSettings: const ConnectorLineSettings(width: 1, length: '10%'),
  builder: (dynamic data, dynamic point, dynamic series, int pointIndex, int seriesIndex) {
    final circularPoint = point as CircularChartPoint;
    // 计算当前分段的中间角度
    final midAngle = circularPoint.startAngle + (circularPoint.endAngle - circularPoint.startAngle) / 2;
    // 将角度转为弧度,旋转文本
    return Transform.rotate(
      angle: midAngle * pi / 180,
      child: Text(
        data.title,
        style: const TextStyle(fontSize: 12, color: Colors.black),
      ),
    );
  },
),

原理:通过每个环形数据点的startAngle和endAngle计算出该段弧度的中间角度,将文本旋转对应角度,实现沿环形切线方向对齐的效果。

2. 推荐其他支持该效果的包

如果觉得Syncfusion的自定义方式繁琐,可以尝试fl_chart包,它的饼图/环形图原生支持更灵活的标签控制:

示例代码片段:

PieChart(
  PieChartData(
    sectionsSpace: 2,
    centerSpaceRadius: 70, // 对应环形图的内半径
    sections: data.map((item) {
      // 计算每个分段的角度
      final segmentAngle = 360 / data.length;
      final itemIndex = data.indexOf(item);
      // 计算当前分段的中间角度
      final midAngle = (segmentAngle * itemIndex + segmentAngle / 2) * pi / 180;
      return PieChartSectionData(
        value: item.value,
        color: Colors.grey,
        radius: 100, // 对应环形图的外半径
        titleWidget: Transform.rotate(
          angle: midAngle,
          child: Padding(
            padding: const EdgeInsets.only(top: 10),
            child: Text(item.title),
          ),
        ),
        titlePositionPercentageOffset: 1.3, // 控制标签距离环形的距离
      );
    }).toList(),
  ),
)

内容的提问来源于stack exchange,提问作者Luis Fernando Scripcaru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 23:27:11