如何用 flutter 绘制烛台

Alb*_*rto 3 candlestick-chart flutter flutter-web

使用flutter和charts_flutter包我想绘制一个烛台图以及其他线(例如macd)和底部的交易量。不幸的是,我无法理解如何与图表的其余部分一起绘制蜡烛。有人愿意向我展示有关如何执行此操作的示例代码吗?蜡烛甚至可以用一条垂直线及其顶部的矩形来表示。

可以在这里看到几个示例图

多谢

chu*_*han 7

您可以复制粘贴运行下面的完整代码
\n您可以使用包https://pub.dev/packages/k_chart\n
要运行演示代码,您还需要设置资产https://github.com/OpenFlutter/k_chart/blob/主/示例/资产/深度.json

\n

工作演示

\n

在此输入图像描述

\n

完整代码

\n
import \'dart:convert\';\n\nimport \'package:flutter/material.dart\';\nimport \'package:flutter/services.dart\';\nimport \'package:k_chart/flutter_k_chart.dart\';\nimport \'package:k_chart/k_chart_widget.dart\';\nimport \'package:http/http.dart\' as http;\n\nvoid main() => runApp(MyApp());\n\nclass MyApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \'Flutter Demo\',\n      theme: ThemeData(\n        primarySwatch: Colors.green,\n      ),\n      home: MyHomePage(title: \'Flutter Demo Home Page\'),\n    );\n  }\n}\n\nclass MyHomePage extends StatefulWidget {\n  MyHomePage({Key key, this.title}) : super(key: key);\n\n  final String title;\n\n  @override\n  _MyHomePageState createState() => _MyHomePageState();\n}\n\nclass _MyHomePageState extends State<MyHomePage> {\n  List<KLineEntity> datas;\n  bool showLoading = true;\n  MainState _mainState = MainState.MA;\n  bool _volHidden = false;\n  SecondaryState _secondaryState = SecondaryState.MACD;\n  bool isLine = true;\n  bool isChinese = true;\n  List<DepthEntity> _bids, _asks;\n\n  @override\n  void initState() {\n    super.initState();\n    getData(\'1day\');\n    rootBundle.loadString(\'assets/depth.json\').then((result) {\n      final parseJson = json.decode(result);\n      Map tick = parseJson[\'tick\'];\n      var bids = tick[\'bids\']\n          .map((item) => DepthEntity(item[0], item[1]))\n          .toList()\n          .cast<DepthEntity>();\n      var asks = tick[\'asks\']\n          .map((item) => DepthEntity(item[0], item[1]))\n          .toList()\n          .cast<DepthEntity>();\n      initDepth(bids, asks);\n    });\n  }\n\n  void initDepth(List<DepthEntity> bids, List<DepthEntity> asks) {\n    if (bids == null || asks == null || bids.isEmpty || asks.isEmpty) return;\n    _bids = List();\n    _asks = List();\n    double amount = 0.0;\n    bids?.sort((left, right) => left.price.compareTo(right.price));\n    //\xe7\xb4\xaf\xe5\x8a\xa0\xe4\xb9\xb0\xe5\x85\xa5\xe5\xa7\x94\xe6\x89\x98\xe9\x87\x8f\n    bids.reversed.forEach((item) {\n      amount += item.vol;\n      item.vol = amount;\n      _bids.insert(0, item);\n    });\n\n    amount = 0.0;\n    asks?.sort((left, right) => left.price.compareTo(right.price));\n    //\xe7\xb4\xaf\xe5\x8a\xa0\xe5\x8d\x96\xe5\x87\xba\xe5\xa7\x94\xe6\x89\x98\xe9\x87\x8f\n    asks?.forEach((item) {\n      amount += item.vol;\n      item.vol = amount;\n      _asks.add(item);\n    });\n    setState(() {});\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      backgroundColor: Color(0xff17212F),\n//      appBar: AppBar(title: Text(widget.title)),\n      body: ListView(\n        children: <Widget>[\n          Stack(children: <Widget>[\n            Container(\n              height: 450,\n              width: double.infinity,\n              child: KChartWidget(\n                datas,\n                isLine: isLine,\n                mainState: _mainState,\n                volHidden: _volHidden,\n                secondaryState: _secondaryState,\n                fixedLength: 2,\n                timeFormat: TimeFormat.YEAR_MONTH_DAY,\n                isChinese: isChinese,\n              ),\n            ),\n            if (showLoading)\n              Container(\n                  width: double.infinity,\n                  height: 450,\n                  alignment: Alignment.center,\n                  child: CircularProgressIndicator()),\n          ]),\n          buildButtons(),\n          Container(\n            height: 230,\n            width: double.infinity,\n            child: DepthChart(_bids, _asks),\n          )\n        ],\n      ),\n    );\n  }\n\n  Widget buildButtons() {\n    return Wrap(\n      alignment: WrapAlignment.spaceEvenly,\n      children: <Widget>[\n        button("\xe5\x88\x86\xe6\x97\xb6", onPressed: () => isLine = true),\n        button("k\xe7\xba\xbf", onPressed: () => isLine = false),\n        button("MA", onPressed: () => _mainState = MainState.MA),\n        button("BOLL", onPressed: () => _mainState = MainState.BOLL),\n        button("\xe9\x9a\x90\xe8\x97\x8f", onPressed: () => _mainState = MainState.NONE),\n        button("MACD", onPressed: () => _secondaryState = SecondaryState.MACD),\n        button("KDJ", onPressed: () => _secondaryState = SecondaryState.KDJ),\n        button("RSI", onPressed: () => _secondaryState = SecondaryState.RSI),\n        button("WR", onPressed: () => _secondaryState = SecondaryState.WR),\n        button("\xe9\x9a\x90\xe8\x97\x8f\xe5\x89\xaf\xe8\xa7\x86\xe5\x9b\xbe", onPressed: () => _secondaryState = SecondaryState.NONE),\n        button(_volHidden ? "\xe6\x98\xbe\xe7\xa4\xba\xe6\x88\x90\xe4\xba\xa4\xe9\x87\x8f" : "\xe9\x9a\x90\xe8\x97\x8f\xe6\x88\x90\xe4\xba\xa4\xe9\x87\x8f",\n            onPressed: () => _volHidden = !_volHidden),\n        button("\xe5\x88\x87\xe6\x8d\xa2\xe4\xb8\xad\xe8\x8b\xb1\xe6\x96\x87", onPressed: () => isChinese = !isChinese),\n      ],\n    );\n  }\n\n  Widget button(String text, {VoidCallback onPressed}) {\n    return FlatButton(\n        onPressed: () {\n          if (onPressed != null) {\n            onPressed();\n            setState(() {});\n          }\n        },\n        child: Text("$text"),\n        color: Colors.blue);\n  }\n\n  void getData(String period) {\n    Future<String> future = getIPAddress(\'$period\');\n    future.then((result) {\n      Map parseJson = json.decode(result);\n      List list = parseJson[\'data\'];\n      datas = list\n          .map((item) => KLineEntity.fromJson(item))\n          .toList()\n          .reversed\n          .toList()\n          .cast<KLineEntity>();\n      DataUtil.calculate(datas);\n      showLoading = false;\n      setState(() {});\n    }).catchError((_) {\n      showLoading = false;\n      setState(() {});\n      print(\'\xe8\x8e\xb7\xe5\x8f\x96\xe6\x95\xb0\xe6\x8d\xae\xe5\xa4\xb1\xe8\xb4\xa5\');\n    });\n  }\n\n  //\xe8\x8e\xb7\xe5\x8f\x96\xe7\x81\xab\xe5\xb8\x81\xe6\x95\xb0\xe6\x8d\xae\xef\xbc\x8c\xe9\x9c\x80\xe8\xa6\x81\xe7\xbf\xbb\xe5\xa2\x99\n  Future<String> getIPAddress(String period) async {\n    var url =\n        \'https://api.huobi.br.com/market/history/kline?period=${period ?? \'1day\'}&size=300&symbol=btcusdt\';\n    String result;\n    var response = await http.get(url);\n    if (response.statusCode == 200) {\n      result = response.body;\n    } else {\n      print(\'Failed getting IP address\');\n    }\n    return result;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n


use*_*613 6

我最近需要这个,所以我从头开始做了一个。

用法:

Padding(
  padding: const EdgeInsets.all(24.0),
  child: InteractiveChart(candles: _data),
)
Run Code Online (Sandbox Code Playgroud)

来源:

您可以查看我的存储库并根据您的需要进行修改。

或者您可以直接从 pub 使用该包

GitHub 页面中还有更多屏幕截图/gif 演示。

烛台图演示

它很容易使用,但它还没有公开很多设置,因此如果您想修改内容,您可能必须克隆存储库并修改核心CustomPaint中的内容。