返回

Flutter股票分时线,K线,WEB,移动端支持

见解分享

公司项目中有涉及到股票类K线及分时线,原先使用flutter_k_chart,但是由于样式及数据方面的问题,决定自己从头开始画一个。 移动端、WEB端都支持。 废话不多说。先上图
[图片]

点击K线图,VOL窗口进行切换指标。
分时线需要提前在/lib/hb_chart_config.dart中配置好指标。
[图片]

实现原理

一般K线和分时线的数据接口都是带时序的,所以使用flutter中的CustomPaint来画图时需要注意将时序数据与屏幕坐标系对应起来。

  1. 将K线,分时线数据转化为Rect,这样就可以使用canvas.drawRect()来画矩形。

  2. 将最高点,最低点,开盘价,收盘价转化为屏幕坐标系中的y坐标。这样就可以使用canvas.drawLine()来画线。

  3. 将成交量数据转化为Rect,这样就可以使用canvas.drawRect()来画矩形。

  4. 将时间数据转化为屏幕坐标系中的x坐标。这样就可以使用canvas.drawText()来画文字。

注意:

  1. K线和分时线的数据需要按照时间顺序排列。

  2. K线和分时线的数据需要包含最高点,最低点,开盘价,收盘价,成交量等信息。

代码实现

1. 定义数据模型

class KLineData {
  DateTime time;
  double open;
  double high;
  double low;
  double close;
  double volume;

  KLineData(this.time, this.open, this.high, this.low, this.close, this.volume);
}

2. 定义画笔

class KLinePainter extends CustomPainter {
  List<KLineData> data;

  KLinePainter(this.data);

  @override
  void paint(Canvas canvas, Size size) {
    // 将K线数据转化为Rect
    List<Rect> rects = [];
    for (var i = 0; i < data.length; i++) {
      var kLineData = data[i];
      var rect = Rect.fromLTWH(
          i * size.width / data.length,
          size.height - (kLineData.high - kLineData.low) / (kLineData.high - kLineData.low) * size.height,
          size.width / data.length,
          (kLineData.high - kLineData.low) / (kLineData.high - kLineData.low) * size.height);
      rects.add(rect);
    }

    // 使用canvas.drawRect()来画矩形
    for (var i = 0; i < rects.length; i++) {
      var rect = rects[i];
      if (data[i].close > data[i].open) {
        canvas.drawRect(rect, Paint()..color = Colors.red);
      } else {
        canvas.drawRect(rect, Paint()..color = Colors.green);
      }
    }

    // 将最高点,最低点,开盘价,收盘价转化为屏幕坐标系中的y坐标
    List<double> yAxis = [];
    for (var i = 0; i < data.length; i++) {
      var kLineData = data[i];
      yAxis.add(size.height - (kLineData.high - kLineData.low) / (kLineData.high - kLineData.low) * size.height);
    }

    // 使用canvas.drawLine()来画线
    for (var i = 0; i < yAxis.length - 1; i++) {
      canvas.drawLine(Offset(i * size.width / data.length, yAxis[i]),
          Offset((i + 1) * size.width / data.length, yAxis[i + 1]),
          Paint()..color = Colors.black);
    }

    // 将成交量数据转化为Rect
    List<Rect> volumeRects = [];
    for (var i = 0; i < data.length; i++) {
      var kLineData = data[i];
      var rect = Rect.fromLTWH(
          i * size.width / data.length,
          size.height - kLineData.volume / kLineData.volume * size.height,
          size.width / data.length,
          kLineData.volume / kLineData.volume * size.height);
      volumeRects.add(rect);
    }

    // 使用canvas.drawRect()来画矩形
    for (var i = 0; i < volumeRects.length; i++) {
      var rect = volumeRects[i];
      canvas.drawRect(rect, Paint()..color = Colors.blue);
    }

    // 将时间数据转化为屏幕坐标系中的x坐标
    List<double> xAxis = [];
    for (var i = 0; i < data.length; i++) {
      var kLineData = data[i];
      xAxis.add(i * size.width / data.length);
    }

    // 使用canvas.drawText()来画文字
    for (var i = 0; i < xAxis.length; i++) {
      var x = xAxis[i];
      var y = size.height - 20;
      var text = data[i].time.toString();
      canvas.drawText(text, Offset(x, y), Paint()..color = Colors.black);
    }
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

3. 使用CustomPaint来画图

class KLineChart extends StatelessWidget {
  List<KLineData> data;

  KLineChart(this.data);

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: KLinePainter(data),
    );
  }
}

总结

本文详细介绍了如何在Flutter中实现股票分时线和K线图,支持移动端和WEB端。本文提供了详细的步骤和示例代码,帮助您快速入门。