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

Flutter中Syncfusion Charts自定义标签及边距调整求助

Flutter Syncfusion 柱状图问题解决

问题说明

我是Flutter新手,正在使用syncfusion_flutter_charts开发柱状图,目前遇到三个问题:

  • X轴日期标签无法设置为上标格式(如1st的st需以上标显示)
  • 条形图开头存在多余边距,未顶到图表左侧
  • Y轴标签贴在轴线上,期望移至轴线外侧

原始代码

数据准备部分

List<_ChartData> data= [];
int daysInMonth(DateTime date){
    var firstDayThisMonth = DateTime(date.year, date.month, date.day);
    var firstDayNextMonth = DateTime(firstDayThisMonth.year, firstDayThisMonth.month + 1, firstDayThisMonth.day);
    return firstDayNextMonth.difference(firstDayThisMonth).inDays;
}
List<String> months = <String>[ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
String ordinal(int number) {
    if(!(number >= 1 && number <= 100)) {
      throw Exception('Invalid number');
    }

    if(number >= 11 && number <= 13) {
      return 'th';
    }

    switch(number % 10) {
      case 1: return 'st';
      case 2: return 'nd';
      case 3: return 'rd';
      default: return 'th';
    }
}
for(int i=1;i<=daysInMonth(DateTime.now());i++){
    data.add(_ChartData('$i${ordinal(i)} ${months[DateTime.now().month-1]}', (Random().nextInt(11)+1).toDouble()));
}

图表组件部分

SizedBox(
  height: 25.h,
  child: SfCartesianChart(
      plotAreaBorderWidth: 0,
      primaryXAxis: CategoryAxis(
          isVisible: true,
          majorGridLines: const MajorGridLines(width: 0),
          interval: (daysInMonth(DateTime.now())+ ((daysInMonth(DateTime.now())-1) - 28))/2,
          labelAlignment: LabelAlignment.center,
          labelStyle: TextStyle(
              color: lightAxisGreyColor,
              fontSize: 10.sp,
          ),
          edgeLabelPlacement: EdgeLabelPlacement.shift,
          labelPlacement: LabelPlacement.onTicks,
        ),
      primaryYAxis: NumericAxis(
          minimum: 0, maximum: 12, interval: 12,
          labelPosition: ChartDataLabelPosition.outside,
          labelAlignment: LabelAlignment.end,
          rangePadding: ChartRangePadding.additional,
          labelStyle: TextStyle(
            color: blackBlueText,
            fontSize: 10.sp
          ),
          axisLine: const AxisLine(width: 0)),
      tooltipBehavior: TooltipBehavior(
        enable: true,
      ),
      series: <ChartSeries<_ChartData, String>>[
        ColumnSeries<_ChartData, String>(
            dataSource: data,
            xValueMapper: (_ChartData data, _) => data.x,
            yValueMapper: (_ChartData data, _) => data.y,
            name: 'Open Tasks',
            width: 1,
            spacing: 0.05,
            borderRadius: BorderRadius.only(topLeft: Radius.circular(0.25.w),topRight: Radius.circular(0.25.w)),
            color: colorPurple)
      ]),
)

解决方案

1. 实现标签上标格式

利用Syncfusion的labelFormatter自定义轴标签,通过RichText实现上标效果:

primaryXAxis: CategoryAxis(
  // 保留原有配置...
  labelFormatter: (dynamic label, dynamic formattedLabel) {
    String text = label.toString();
    // 匹配数字+后缀+月份的格式
    RegExp regExp = RegExp(r'(\d+)(st|nd|rd|th)(.*)');
    Match? match = regExp.firstMatch(text);
    if (match != null) {
      String number = match.group(1)!;
      String suffix = match.group(2)!;
      String month = match.group(3)!;
      return ChartAxisLabel(
        RichText(
          text: TextSpan(
            children: [
              TextSpan(
                text: number,
                style: TextStyle(color: lightAxisGreyColor, fontSize: 10.sp),
              ),
              TextSpan(
                text: suffix,
                style: TextStyle(
                  color: lightAxisGreyColor,
                  fontSize: 7.sp,
                  height: 0.7, // 调整上标垂直位置
                  baseline: TextBaseline.alphabetic,
                ),
              ),
              TextSpan(
                text: month,
                style: TextStyle(color: lightAxisGreyColor, fontSize: 10.sp),
              ),
            ],
          ),
        ),
        TextDirection.ltr,
      );
    }
    return ChartAxisLabel(text, TextStyle(color: lightAxisGreyColor, fontSize: 10.sp));
  },
),

2. 去除条形图开头多余边距

修改X轴的rangePadding为none,并调整edgeLabelPlacement:

primaryXAxis: CategoryAxis(
  // 保留原有配置...
  rangePadding: ChartRangePadding.none,
  edgeLabelPlacement: EdgeLabelPlacement.none,
),

3. 调整Y轴标签到外侧

添加majorTickLines并设置labelOffset,让标签远离轴线:

primaryYAxis: NumericAxis(
  // 保留原有配置...
  labelPosition: ChartDataLabelPosition.outside,
  majorTickLines: const MajorTickLines(length: 6), // 显示刻度线,拉开标签与轴线距离
  labelOffset: 8, // 手动偏移标签位置
),

内容的提问来源于stack exchange,提问作者Umar Ghaffar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:42:22