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

如何在Flutter charts_flutter折线图中添加单条平均参考线?

需求说明

已完成基础折线图开发,需要在折线图中添加一条白色平均参考线,要求通过StaticNumericTickProviderSpec实现。

原有业务代码如下:

import 'package:charts_flutter/flutter.dart';
import 'package:flutter/cupertino.dart';
import 'package:charts_flutter/flutter.dart' as charts;
class WeightTracker_time_series_chart extends StatelessWidget {
  final List<charts.Series> seriesList;
  final bool animate;
  WeightTracker_time_series_chart(this.seriesList, {this.animate});

  factory WeightTracker_time_series_chart.withSampleData() {
    return new WeightTracker_time_series_chart(
      _createSampleData(),
      animate: false,
    );
  }
  List getdata =["1","2","3"];

  @override
  Widget build(BuildContext context) {

    return new charts.LineChart(seriesList,

        animate: animate,
        defaultRenderer: new charts.LineRendererConfig( includeArea: true,
          includePoints: true,
          includeLine: true,
          stacked: true,),
        layoutConfig: charts.LayoutConfig(
            leftMarginSpec: charts.MarginSpec.fixedPixel(60),
            topMarginSpec: charts.MarginSpec.fixedPixel(10),
            rightMarginSpec: charts.MarginSpec.fixedPixel(0),
            bottomMarginSpec: charts.MarginSpec.fixedPixel(20)
        ),
        flipVerticalAxis: false,
        defaultInteractions: false,
        behaviors: [new charts.PanAndZoomBehavior()],
        domainAxis: new charts.NumericAxisSpec(
          viewport: new charts.NumericExtents(20, 120),
            renderSpec: charts.GridlineRendererSpec(
                lineStyle: charts.LineStyleSpec(
                  color: charts.MaterialPalette.white,
                  thickness: 1,
                )
            ),

            tickProviderSpec: new charts.StaticNumericTickProviderSpec(
              // Create the ticks to be used the domain axis.
                _createTickSpec(),
            )),
        selectionModels: [
          new charts.SelectionModelConfig(
              changedListener: (SelectionModel model) {
                print( model.selectedSeries[0].measureFn(
                    model.selectedDatum[0].index));
                }
          )
        ],

        primaryMeasureAxis: new charts.NumericAxisSpec(
            renderSpec:
            charts.GridlineRendererSpec(
                labelOffsetFromAxisPx: 20,

                labelAnchor: charts.TickLabelAnchor.before,
                lineStyle: charts.LineStyleSpec(
                  color: charts.MaterialPalette.white,
                  thickness: 2,
                )
            ),
            tickProviderSpec: new charts.StaticNumericTickProviderSpec(

              // Create the ticks to be used the domain axis.
              <charts.TickSpec<num>>[


                new charts.TickSpec(50, label: '80 ', style: charts.TextStyleSpec(fontSize: 14)),

              ],
            )

        ),
        
  }

  List<charts.TickSpec<num>> _createTickSpec() {
    List<charts.TickSpec<num>> _tickProvidSpecs = new List<charts.TickSpec<num>>();
    double d = 0;
    double day= 0;
   for(int i = 0; i< getdata.length ; i++) {

      _tickProvidSpecs.add(new charts.TickSpec(d,label: '$day%', style: charts.TextStyleSpec(fontSize: 14)));
      d +=20;
      day+=1;
    }

   return _tickProvidSpecs;
  }


  static List<charts.Series<day_kg, int>> _createSampleData() {
    final myFakeDesktopData = [
      new day_kg(0, 70),
      new day_kg(20, 85),
      new day_kg(40, 80),

    ];

    return [
      new charts.Series<day_kg, int>(
        id: 'weight',
        fillColorFn: (_, __) => charts.MaterialPalette.white,
        colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
        domainFn: (day_kg data, _) => data.date,
        measureFn: (day_kg data, _) => data.kg,

        domainLowerBoundFn: (day_kg data, _) => data.domainLower,

        measureLowerBoundFn: (day_kg data, _) => data.measureLower,
        strokeWidthPxFn: (_, __) => 4,
        data: myFakeDesktopData,
      ),


    ];
  }

}

class day_kg {
  final int date;
  final int kg;

  final int domainUpper = 100;
  final int domainLower = 0;

  final int measureUpper = 100;
  final int measureLower = 0;

  day_kg(this.date, this.kg);
}
实现方案

以下提供两种符合需求的实现方式,优先匹配你要求的tickProviderSpec实现逻辑:

方案1:通过StaticNumericTickProviderSpec实现

实现逻辑

  • 先遍历计算所有数据的体重平均值
  • 将平均值作为自定义刻度加入纵轴的静态刻度列表,单独配置该刻度的网格线为白色,隐藏原有其他刻度的网格线即可仅展示一条平均参考线

修改步骤

  1. 在组件内新增平均值计算方法:
/// 计算体重平均值
num _calculateAverageValue() {
  if (seriesList.isEmpty || seriesList.first.data.isEmpty) return 0;
  int total = 0;
  for (var item in seriesList.first.data as List<day_kg>) {
    total += item.kg;
  }
  return total / seriesList.first.data.length;
}
  1. 修改primaryMeasureAxis配置,替换原有对应部分代码即可:
primaryMeasureAxis: new charts.NumericAxisSpec(
    renderSpec:
    charts.GridlineRendererSpec(
        labelOffsetFromAxisPx: 20,
        labelAnchor: charts.TickLabelAnchor.before,
        // 隐藏默认全局网格线
        lineStyle: charts.LineStyleSpec(
          color: charts.MaterialPalette.transparent,
          thickness: 0,
        )
    ),
    tickProviderSpec: new charts.StaticNumericTickProviderSpec(
      <charts.TickSpec<num>>[
        // 保留原有业务刻度
        new charts.TickSpec(50, label: '80 ', style: charts.TextStyleSpec(fontSize: 14)),
        // 新增平均值刻度,不需要显示标签可将label设为空字符串
        new charts.TickSpec(
          _calculateAverageValue(),
          label: '平均体重',
          style: charts.TextStyleSpec(fontSize: 14, color: charts.MaterialPalette.white),
          // 单独配置平均值刻度线为白色
          lineStyle: charts.LineStyleSpec(
            color: charts.MaterialPalette.white,
            thickness: 2,
          ),
        ),
      ],
    )
),

方案2:通过RangeAnnotation实现(通用参考线方案)

如果不需要绑定刻度逻辑,直接添加参考线更推荐该方案,只需要在behaviors列表中新增注解配置即可:

behaviors: [
  new charts.PanAndZoomBehavior(),
  // 新增平均参考线注解
  new charts.RangeAnnotation(
    [
      new charts.LineAnnotationSegment(
        _calculateAverageValue(),
        charts.RangeAnnotationAxisType.measure,
        color: charts.MaterialPalette.white,
        strokeWidthPx: 2,
        // 可选配置参考线标签
        label: '平均体重',
        labelStyle: charts.TextStyleSpec(
          fontSize: 14,
          color: charts.MaterialPalette.white,
        ),
      ),
    ],
  ),
],

内容的提问来源于stack exchange,提问作者Meng Cheng teoh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:57:01