Flutter图表绘制与深度分析插件k_chart_plus_deeping的使用
Flutter图表绘制与深度分析插件k_chart_plus_deeping的使用
K Chart Plus Package Deeping
功能特性
- 2024-08-01 更新:显示双量
- 2024-07-18 更新:手势缩放功能|科学计数法支持
- 2024-07-17 更新:添加EMA指标
- 2024-07-16 更新:骨架屏功能
这个可能是Flutter中最好的K线图。支持拖拽、缩放、长按和滑动,并且易于使用。
Example1 | Example2 |
---|---|
安装
首先,在pubspec.yaml
文件中添加k_chart_plus_deeping
作为依赖项:
dependencies:
k_chart_plus_deeping: ^1.0.0-tomo+2
如果不需要支持选择多个次要状态,可以使用以下配置:
flutter_k_chat_plus:
git:
url: https://github.com/sawwas/flutter_k_chat_plus
ref: single # 分支名称
使用方法
数据处理
当你更改数据时,必须调用以下函数:
DataUtil.calculate(datas); // 此函数有一些可选参数:n 是 BOLL N 天收盘价。k 是 BOLL 参数。
使用K线图
KChartWidget(
chartStyle, // 必填,用于样式设置
chartColors, // 必填,用于样式设置
datas, // 必填,数据必须是有序列表(历史->现在)
mBaseHeight: 360, // 图表高度(不包含成交量和副图)
isLine: isLine, // 决定是否为K线或分时图
mainState: _mainState, // 决定主视图显示内容
secondaryStateLi: _secondaryStateLi, // 决定副视图显示内容
fixedLength: 2, // 显示的小数精度
timeFormat: TimeFormat.YEAR_MONTH_DAY,
onLoadMore: (bool a) {}, // 当数据滚动到末尾时调用。a 为 true 表示用户拉到了数据右侧末尾;a 为 false 表示用户拉到了数据左侧末尾。
maDayList: [5, 10, 20], // MA 显示,此参数必须等于 DataUtil.calculate 的 maDayList
volHidden: false, // 隐藏成交量
showNowPrice: true, // 显示当前价格
isOnDrag: (isDrag) {}, // 拖拽时为 true。拖拽时不加载数据。
isTrendLine: false, // 设置为 true 后,可以通过长按并移动手指使用趋势线
xFrontPadding: 100 // 前部填充
),
使用深度图
DepthChart(_bids, _asks, chartColors) // 注意:数据必须是有序列表
深色/浅色主题
ChartColor
用于设置图表颜色。你需要根据主题配置灵活调整以确保UI效果。
如果你需要应用多主题,至少需要更改与文本、边框、网格和背景颜色相关的颜色。
late ThemeData themeData = Theme.of(context);
late ChartColors chartColors = ChartColors(
bgColor: themeData.colorScheme.background,
defaultTextColor: themeData.textTheme.labelMedium?.color ?? Colors.grey,
gridColor: themeData.dividerColor,
hCrossColor: themeData.textTheme.bodyMedium?.color ?? Colors.white,
vCrossColor: themeData.disabledColor.withOpacity(.1),
crossTextColor: themeData.textTheme.bodyMedium?.color ?? Colors.white,
selectBorderColor: themeData.textTheme.bodyMedium?.color ?? Colors.black54,
selectFillColor: themeData.colorScheme.background,
infoWindowTitleColor: themeData.textTheme.labelMedium?.color ?? Colors.grey,
infoWindowNormalColor: themeData.textTheme.bodyMedium?.color ?? Colors.white,
);
应用于K线图:
KChartWidget(
data,
ChartStyle(),
ChartColors().init(), /// 自定义图表颜色
chartTranslations: ChartTranslations(
date: 'Date',
open: 'Open',
high: 'High',
low: 'Low',
close: 'Close',
changeAmount: 'Change',
change: 'Change%',
amount: 'Amount',
vol: 'Volume',
),
mBaseHeight: 360,
isTrendLine: false,
mainState: mainState,
secondaryStateLi: secondaryStates,
fixedLength: 2,
timeFormat: TimeFormat.YEAR_MONTH_DAY,
);
示例代码
以下是完整的示例代码,展示了如何在Flutter项目中使用k_chart_plus_deeping
插件。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:k_chart_plus_deeping/k_chart_plus.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, this.title}) : super(key: key);
final String? title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<KLineEntity>? datas;
bool showLoading = true;
bool _volHidden = false;
MainState _mainState = MainState.mA;
final List<SecondaryState> _secondaryStateLi = [];
List<DepthEntity>? _bids, _asks;
ChartStyle chartStyle = ChartStyle();
ChartColors chartColors = ChartColors();
@override
void initState() {
super.initState();
getData('1day');
rootBundle.loadString('assets/depth.json').then((result) {
final parseJson = json.decode(result);
final tick = parseJson['tick'] as Map<String, dynamic>;
final List<DepthEntity> bids = (tick['bids'] as List<dynamic>)
.map<DepthEntity>(
(item) => DepthEntity(item[0] as double, item[1] as double))
.toList();
final List<DepthEntity> asks = (tick['asks'] as List<dynamic>)
.map<DepthEntity>(
(item) => DepthEntity(item[0] as double, item[1] as double))
.toList();
initDepth(bids, asks);
});
}
void initDepth(List<DepthEntity>? bids, List<DepthEntity>? asks) {
if (bids == null || asks == null || bids.isEmpty || asks.isEmpty) return;
_bids = [];
_asks = [];
double amount = 0.0;
bids.sort((left, right) => left.price.compareTo(right.price));
for (var item in bids.reversed) {
amount += item.vol;
item.vol = amount;
_bids!.insert(0, item);
}
amount = 0.0;
asks.sort((left, right) => left.price.compareTo(right.price));
for (var item in asks) {
amount += item.vol;
item.vol = amount;
_asks!.add(item);
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
shrinkWrap: true,
children: [
const SafeArea(bottom: false, child: SizedBox(height: 10)),
Stack(children: [
KChartWidget(
datas,
chartStyle,
chartColors,
mBaseHeight: 360,
isTrendLine: false,
mainState: _mainState,
volHidden: _volHidden,
secondaryStateLi: _secondaryStateLi.toSet(),
fixedLength: 2,
timeFormat: TimeFormat.yearMONTHDAY,
),
if (showLoading)
Container(
width: double.infinity,
height: 450,
alignment: Alignment.center,
child: const CircularProgressIndicator(),
),
]),
_buildTitle(context, 'VOL'),
buildVolButton(),
_buildTitle(context, 'Main State'),
buildMainButtons(),
_buildTitle(context, 'Secondary State'),
buildSecondButtons(),
const SizedBox(height: 30),
if (_bids != null && _asks != null)
Container(
color: Colors.white,
height: 320,
width: double.infinity,
child: DepthChart(
_bids!,
_asks!,
chartColors,
),
)
],
),
);
}
Widget _buildTitle(BuildContext context, String title) {
return Padding(
padding: const EdgeInsets.fromLTRB(16, 20, 12, 15),
child: Text(
title,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
);
}
Widget buildVolButton() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Align(
alignment: Alignment.centerLeft,
child: _buildButton(
context: context,
title: 'VOL',
isActive: !_volHidden,
onPress: () {
_volHidden = !_volHidden;
setState(() {});
}),
),
);
}
Widget buildMainButtons() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Wrap(
alignment: WrapAlignment.start,
spacing: 10,
runSpacing: 10,
children: MainState.values.map((e) {
return _buildButton(
context: context,
title: e.name,
isActive: _mainState == e,
onPress: () => _mainState = e,
);
}).toList(),
),
);
}
Widget buildSecondButtons() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Wrap(
alignment: WrapAlignment.start,
spacing: 10,
runSpacing: 5,
children: SecondaryState.values.map((e) {
bool isActive = _secondaryStateLi.contains(e);
return _buildButton(
context: context,
title: e.name,
isActive: _secondaryStateLi.contains(e),
onPress: () {
if (isActive) {
_secondaryStateLi.remove(e);
} else {
_secondaryStateLi.add(e);
}
},
);
}).toList(),
),
);
}
Widget _buildButton({
required BuildContext context,
required String title,
required bool isActive,
required Function onPress,
}) {
late Color? bgColor, txtColor;
if (isActive) {
bgColor = Theme.of(context).primaryColor.withOpacity(.15);
txtColor = Theme.of(context).primaryColor;
} else {
bgColor = Colors.transparent;
txtColor =
Theme.of(context).textTheme.bodyMedium?.color?.withOpacity(.75);
}
return InkWell(
onTap: () {
onPress();
setState(() {});
},
child: Container(
decoration: BoxDecoration(
color: bgColor,
borderRadius: BorderRadius.circular(6),
),
constraints: const BoxConstraints(minWidth: 60),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: Text(
title,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: txtColor,
),
textAlign: TextAlign.center,
),
),
);
}
void getData(String period) {
final Future<String> future = getChatDataFromInternet(period);
future.then((String result) {
solveChatData(result);
}).catchError((_) {
showLoading = false;
setState(() {});
debugPrint('### datas error $_');
});
}
Future<String> getChatDataFromInternet(String? period) async {
var url =
'https://api.huobi.br.com/market/history/kline?period=${period ?? '1day'}&size=300&symbol=btcusdt';
late String result;
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
result = response.body;
} else {
debugPrint('Failed getting IP address');
}
return result;
}
Future<String> getChatDataFromJson() async {
return rootBundle.loadString('assets/chatData.json');
}
void solveChatData(String result) {
final Map parseJson = json.decode(result) as Map<dynamic, dynamic>;
final list = parseJson['data'] as List<dynamic>;
datas = list
.map((item) => KLineEntity.fromJson(item as Map<String, dynamic>))
.toList()
.reversed
.toList()
.cast<KLineEntity>();
DataUtil.calculate(datas!);
showLoading = false;
setState(() {});
}
}
致谢
感谢以下项目的贡献:
希望这些信息能帮助你在Flutter项目中成功使用k_chart_plus_deeping
插件。如果你有任何问题或需要进一步的帮助,请随时提问!
更多关于Flutter图表绘制与深度分析插件k_chart_plus_deeping的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图表绘制与深度分析插件k_chart_plus_deeping的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,k_chart_plus_deeping
是一个用于绘制图表并进行深度分析的插件。虽然我不能直接提供该插件的官方实现细节或源代码(因为这通常受版权和分发协议的限制),但我可以展示一个基本的Flutter项目结构以及如何使用类似图表绘制库的通用方法。请注意,以下代码是一个假设性的示例,因为具体的 k_chart_plus_deeping
API 细节并未公开。
首先,确保你已经在 pubspec.yaml
文件中添加了 k_chart_plus_deeping
依赖(假设它已经在Pub仓库中可用):
dependencies:
flutter:
sdk: flutter
k_chart_plus_deeping: ^x.y.z # 替换为实际的版本号
然后,运行 flutter pub get
来获取依赖。
接下来,是一个基本的Flutter页面示例,展示如何使用一个假设的图表绘制库来绘制图表:
import 'package:flutter/material.dart';
import 'package:k_chart_plus_deeping/k_chart_plus_deeping.dart'; // 假设这是库的导入路径
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Chart Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ChartScreen(),
);
}
}
class ChartScreen extends StatefulWidget {
@override
_ChartScreenState createState() => _ChartScreenState();
}
class _ChartScreenState extends State<ChartScreen> {
// 假设的数据源
final List<Map<String, dynamic>> chartData = [
{'x': 'A', 'y': 10},
{'x': 'B', 'y': 20},
{'x': 'C', 'y': 15},
{'x': 'D', 'y': 25},
{'x': 'E', 'y': 30},
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('K-Chart Plus Deeping Example'),
),
body: Center(
child: KChartPlusDeeping(
data: chartData, // 假设库接受这种格式的数据
xAxisLabel: 'X Axis',
yAxisLabel: 'Y Axis',
title: 'Sample Chart',
// 其他可能的配置选项
// depthAnalysis: true, // 假设有一个深度分析的开关
// 其他深度分析相关的配置...
),
),
);
}
}
// 假设的 KChartPlusDeeping 组件定义(实际使用时请参考官方文档)
class KChartPlusDeeping extends StatelessWidget {
final List<Map<String, dynamic>> data;
final String xAxisLabel;
final String yAxisLabel;
final String title;
// 其他可能的配置参数...
const KChartPlusDeeping({
Key? key,
required this.data,
required this.xAxisLabel,
required this.yAxisLabel,
required this.title,
// 其他配置参数默认值...
}) : super(key: key);
@override
Widget build(BuildContext context) {
// 这里应该包含实际的图表绘制逻辑
// 但由于我们不知道具体的库实现,所以仅返回一个占位Text
return Text('K-Chart Plus Deeping Chart Placeholder');
}
}
注意:
- 上述代码中的
KChartPlusDeeping
是一个假设的组件,用于说明如何在Flutter中使用一个图表绘制库。实际使用时,你需要参考k_chart_plus_deeping
的官方文档和API。 chartData
的格式和内容也是基于假设的,你需要根据k_chart_plus_deeping
插件的实际要求来调整数据格式。- 深度分析功能(如
depthAnalysis: true
)和其他配置选项也是假设性的,你需要查阅官方文档以了解如何启用和配置这些功能。
建议直接访问 k_chart_plus_deeping
的官方仓库或文档页面,以获取最准确和最新的使用指南和示例代码。