Flutter 股票 分时线、K线 实现

借鉴自flutter_k_chart

公司项目中有涉及到股票类K线及分时线,原先使用flutter_k_chart,但是由于样式及数据方面的问题,决定自己从头开始画一个。

移动端、WEB端都支持。
现有指标有MACDKDJBOLL

废话不多说。先上图

分时线

K线

点击K线图,VOL窗口进行切换指标。


切换指标
MACD
KDJ
BOLL

HOW TO USE

demo 地址

https://github.com/GitHubYhb/HBLineChart

demo

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:HBLineChart/hb_kline_chart/hb_chart_data_util.dart';
import 'package:HBLineChart/hb_kline_chart/hb_k_line_chart.dart';
import 'package:HBLineChart/hb_kline_chart/hb_minute_line_chart.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'HBLineChart Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: TestPage(),
    );
  }
}

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  List datas = [];
  List klineDatas = [];

  @override
  void initState() {
    // getData();
    getMockMinuteData();
    getMockKlineData();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("组件测试"),
      ),
      body: ListView(
        children: <Widget>[
          HBMinuteLineChart(datas: datas),
          HBKLineChart(datas: klineDatas,)
        ],
      ),
    );
  }

  getMockMinuteData() {
    rootBundle
        .loadString('lib/hb_kline_chart/mock_data/minute_line.json')
        .then((result) {
      List dataList = jsonDecode(result);
      List newData = [];
      double maxPrice = 0, minPrice = double.infinity;
      double sumPirce = 0;
      double avePirce = 0;
      int maxv = 0;
      for (var i = 0; i < dataList.length; i++) {
        double prePrice =
            HBDataUtil.valueToNum(i == 0 ? "0" : dataList[i - 1]["price"])
                .toDouble();
        double price = HBDataUtil.valueToNum(dataList[i]["price"]).toDouble();
        int vol = HBDataUtil.valueToNum(dataList[i]["vol"]).toInt();
        // //涨跌状态
        bool upDown = price > prePrice;
        sumPirce += price;
        avePirce = sumPirce / (i + 1);
        if (price > maxPrice) {
          maxPrice = price;
        }
        if (price < minPrice) {
          minPrice = price;
        }
        if (vol > maxv) {
          maxv = vol;
        }
        Map m = {
          "price": price,
          "vol": vol,
          "time": dataList[i]["time"],
          "upDown": upDown,
          "ave": avePirce
        };
        newData.add(m);
      }
      datas = newData;
      setState(() {});
    });
  }

  getMockKlineData() async {
    rootBundle
        .loadString('lib/hb_kline_chart/mock_data/k_line.json')
        .then((result) {
      List dataList = jsonDecode(result);
      List data = [];
      for (var i = 0; i < dataList.length; i++) {
        Map m = dataList[I];
        Map newMap = {
          "open": HBDataUtil.valueToNum(m["open"]).toDouble(),
          "high": HBDataUtil.valueToNum(m["high"]).toDouble(),
          "low": HBDataUtil.valueToNum(m["low"]).toDouble(),
          "close": HBDataUtil.valueToNum(m["close"]).toDouble(),
          "vol": HBDataUtil.valueToNum(m["vol"]).toDouble(),
          "date": m["date"],
        };
        data.add(newMap);
      }
      klineDatas = data;
      //计算各种指标
      HBDataUtil.calculate(klineDatas);
      setState(() {});
    });
  }
}

数据

分时线

[
    {
        "price": 4542,
        "vol": 49722,
        "time": "20:00"
    },
    {
        "price": 4540,
        "vol": 26100,
        "time": "20:01"
    },
]

重要提示:

分时线需要提前在/lib/hb_chart_config.dart中设置好整体长度lineChartCount,否则可能会出现显示错误的问题。

image.png


K线

[
    {
        "open": "270.31",
        "high": "272.38",
        "low": "269.95",
        "close": "271.89",
        "vol": "66164",
        "date": "20170117"
    },
    {
        "open": "272.59",
        "high": "272.59",
        "low": "270.8",
        "close": "270.98",
        "vol": "71134",
        "date": "20170118"
    },
]

UI

在文件/lib/hb_chart_config.dart中,有各种颜色、宽度、长度等等。

import 'package:flutter/material.dart';

//分时线数据总长度
int lineChartCount = 781;
//柱状图最大宽度
double colMaxWidth = 5;

//蜡烛间隔
double candleSpace = 10;
//蜡烛宽度
double candleWidth = 8.5;
//蜡烛中间线的宽度
double candleLineWidth = 1.5;

//长按字体底色
Color timePriceTextColor = Colors.white;
//长按背景底色
Color timePriceMarkColor = Colors.blue;

//涨颜色
Color upColor = Colors.red;
//跌颜色
Color dnColor = Colors.green;

//交叉线宽度
double crossLineWidth = 0.5;
//交叉线颜色
Color crossLineColor = Colors.black;
//交叉线中心颜色
Color dotColor = Colors.red;

//分时线均线颜色
Color aveColor = Colors.purple;

//现价颜色
Color currentPriceColor = Colors.black87;
//均价颜色
Color avePriceColor = Colors.brown;

//各种指标线 三种颜色
Color kValue1Color = Colors.brown;
Color kValue2Color = Colors.blue;
Color kValue3Color = Colors.purple;

double leftFontSize = 12.0;
double topFontSize = 12.0;
double bottomFontSize = 10.0;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335