如何绘制圆角边框饼图

问题描述 投票:0回答:2

我正在尝试构建一个如下所示的饼图:

Image

我已经尝试过

Flutter_Charts
FL_Chart
,但它们似乎都不支持圆角和饼图中的间隔项目。

有谁知道实现饼图这种设计的最佳方法是什么?

谢谢!

flutter dart charts flutter-layout flutter-dependencies
2个回答
1
投票

使用 CustomPaint 小部件可以轻松实现与图表非常相似的版本。

这是结果图表
Resulting chart

要实现这一点,您只需要一个非常基本的 CustomPainter 来在画布上绘制弧线。 舍入效果是通过用于绘制笔划的 PaintlinesCap 属性来实现的。遗憾的是 StrokeCap 仅支持 圆形和方形笔画结尾。
这样是无法实现像你截图那样的圆角矩形效果的。
颜色是通过为每个笔划使用单独的 Paint 来实现的。

// this is used to pass data about chart values to the widget
class PieChartData {
  const PieChartData(this.color, this.percent);

  final Color color;
  final double percent;
}

// our pie chart widget
class PieChart extends StatelessWidget {
  PieChart({
    required this.data,
    required this.radius,
    this.strokeWidth = 8,
    this.child,
    Key? key,
  })  : // make sure sum of data is never ovr 100 percent
        assert(data.fold<double>(0, (sum, data) => sum + data.percent) <= 100),
        super(key: key);

  final List<PieChartData> data;
  // radius of chart
  final double radius;
  // width of stroke
  final double strokeWidth;
  // optional child; can be used for text for example
  final Widget? child;

  @override
  Widget build(context) {
    return CustomPaint(
      painter: _Painter(strokeWidth, data),
      size: Size.square(radius),
      child: SizedBox.square(
        // calc diameter
        dimension: radius * 2,
        child: Center(
          child: child,
        ),
      ),
    );
  }
}

// responsible for painting our chart
class _PainterData {
  const _PainterData(this.paint, this.radians);

  final Paint paint;
  final double radians;
}

class _Painter extends CustomPainter {
  _Painter(double strokeWidth, List<PieChartData> data) {
    // convert chart data to painter data
    dataList = data
        .map((e) => _PainterData(
              Paint()
                ..color = e.color
                ..style = PaintingStyle.stroke
                ..strokeWidth = strokeWidth
                ..strokeCap = StrokeCap.round,
              // remove padding from stroke
              (e.percent - _padding) * _percentInRadians,
            ))
        .toList();
  }

  static const _percentInRadians = 0.062831853071796;
  // this is the gap between strokes in percent
  static const _padding = 4;
  static const _paddingInRadians = _percentInRadians * _padding;
  // 0 radians is to the right, but since we want to start from the top
  // we'll use -90 degrees in radians
  static const _startAngle = -1.570796 + _paddingInRadians / 2;

  late final List<_PainterData> dataList;

  @override
  void paint(Canvas canvas, Size size) {
    final rect = Offset.zero & size;
    // keep track of start angle for next stroke
    double startAngle = _startAngle;

    for (final data in dataList) {
      final path = Path()..addArc(rect, startAngle, data.radians);

      startAngle += data.radians + _paddingInRadians;

      canvas.drawPath(path, data.paint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}

您可以查看 dartpad 来尝试一个工作示例。

我确信您在该图片中提供的相同图表可以 使用 CustomPainter 实现,但这会复杂得多。


0
投票

您好,请根据您的要求尝试这个。 Flutter 圆形图表中的甜甜圈图(SfCircularChart)。 “https://help.syncfusion.com/flutter/circular-charts/chart-types/doughnut-chart”

© www.soinside.com 2019 - 2024. All rights reserved.