flutter自定义系列之简单的K线图绘制

news/2024/11/28 21:48:27/

上篇文章讲了flutter自定义的相关流程,

今天继续练习下flutter的自定义K线:

我们可以通过自定义Painter来实现一个简单的K线图界面:

  1. 创建一个自定义的Painter,用于绘制K线图:
import 'dart:ui';import 'package:flutter/material.dart';class KLinePainter extends CustomPainter {final List<dynamic> data;final double itemWidth;final double scaleFactor;KLinePainter({required this.data, required this.itemWidth, required this.scaleFactor});@overridevoid paint(Canvas canvas, Size size) {// 设置画笔final linePaint = Paint()..color = Colors.grey..strokeWidth = 0.5;final textPainter = TextPainter(textDirection: TextDirection.ltr, textAlign: TextAlign.left);// 计算价格范围和最大成交量num highestPrice = double.minPositive;num lowestPrice = double.maxFinite;num highestVolume = double.minPositive;for (var item in data) {if (item['high'] > highestPrice) {highestPrice = item['high'];}if (item['low'] < lowestPrice) {lowestPrice = item['low'];}if (item['vol'] > highestVolume) {highestVolume = item['vol'];}}// 计算价格和成交量的缩放比例double priceScale = (size.height - 20) / (highestPrice - lowestPrice);double volumeScale = size.height * 0.2 / highestVolume;// 绘制K线图for (int i = 0; i < data.length; i++) {var item = data[i];double open = (item['open'] - lowestPrice) * priceScale;double close = (item['close'] - lowestPrice) * priceScale;double high = (item['high'] - lowestPrice) * priceScale;double low = (item['low'] - lowestPrice) * priceScale;double vol = item['vol'] * volumeScale;// 设置画笔颜色linePaint.color = close >= open ? Colors.green : Colors.red;// 绘制实体double halfWidth = itemWidth * scaleFactor / 2;double centerX = i * itemWidth * scaleFactor + halfWidth;canvas.drawRect(Rect.fromCenter(center: Offset(centerX, size.height - (open + close) / 2 - 10),width: itemWidth * scaleFactor,height: (open - close).abs(),),linePaint,);// 绘制上下影线canvas.drawLine(Offset(centerX, size.height - high - 10), Offset(centerX, size.height - low - 10), linePaint);}}@overridebool shouldRepaint(CustomPainter oldDelegate) {return true;}
}
  1. 创建一个StatefulWidget,用于处理缩放和滚动:
class KLineChart extends StatefulWidget {final List<dynamic> data;KLineChart({required this.data});@override_KLineChartState createState() => _KLineChartState();
}class _KLineChartState extends State<KLineChart> {double _scaleFactor = 1.0;double _itemWidth = 10.0;late double _baseScaleFactor;@overridevoid initState() {super.initState();_baseScaleFactor = _scaleFactor;}@overrideWidget build(BuildContext context) {return GestureDetector(onScaleStart: (details) {_baseScaleFactor = _scaleFactor;},onScaleUpdate: (details) {setState(() {// 修改这里,减小缩放速度_scaleFactor = _baseScaleFactor * (1.0 + (details.scale - 1.0) / 2);});},child: SingleChildScrollView(scrollDirection: Axis.horizontal,child: CustomPaint(size: Size(widget.data.length * _itemWidth * _scaleFactor, MediaQuery.of(context).size.height),painter: KLinePainter(data: widget.data, itemWidth: _itemWidth, scaleFactor: _scaleFactor),),),);}
}
  1. 在需要使用K线图的地方,调用KLineChart组件并传入K线数据:
List<dynamic> kLineData = [// 你的K线数据
];KLineChart(data: kLineData);

这样,你就可以实现一个简单的可左右滑动、放大缩小的K线界面。

这里我们看看实现的效果:
我先模拟了一些K线数据:

List<dynamic> generateKLineData(int count) {List<dynamic> data = [];Random random = Random();double open = 100.0;double close, high, low;num volume;for (int i = 0; i < count; i++) {close = open + random.nextDouble() * 20 - 10;high = max(open, close) + random.nextDouble() * 5;low = min(open, close) - random.nextDouble() * 5;volume = random.nextInt(10000) + 1000;data.add({'open': open,'close': close,'high': high,'low': low,'vol': volume,});open = close;}return data;
}

之后直接引用:

SliverToBoxAdapter(child: SizedBox(height: 300.w,child: KLineChart(data: generateKLineData(100)),),
)

运行后如下效果:

图片.png

可左右滑动,可伸缩,仅包含基本功能,真正的需要分时图,各种的指标,甚至是自定义的指标绘制等等,你可以根据需求进一步完善和优化。

技术人日拱一卒,共勉!


http://www.ppmy.cn/news/340035.html

相关文章

华为OD机试真题 JavaScript 实现【勾股数元组】【2022Q4 100分】,附详细解题思路

一、题目描述 如果三个正整数A、B、C ,ABC则为勾股数 如果ABC之间两两互质&#xff0c;即A与B&#xff0c;A与C&#xff0c;B与C均互质没有公约数&#xff0c; 则称 其为勾股数元组。 请求出给定n~m范围内所有的勾股数元组。 二、输入描述 起始范围 1 < n < 10000 n &…

Mysql中explain的用法详解

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

Python内存管理与垃圾回收深度解析

Python的内存管理和垃圾回收是一项基础但至关重要的技术。理解Python如何管理内存可以帮助我们写出更优化、更高效的代码&#xff0c;同时也可以帮助我们更好地理解Python运行时的一些行为。在本文中&#xff0c;我们将深入探讨Python的内存管理和垃圾回收机制。 一、Python的…

20230612 set1打卡

哈希表理论基础 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

人工智能体系和实战指南

前言 人工智能是一个庞大的研究领域。虽然我们已经在人工智能的理论研究和算法开发方面取得了一定的进展&#xff0c;但是我们目前掌握的能力仍然非常有限。机器学习是人工智能的一个重要领域&#xff0c;它研究计算机如何模拟或实现人类的学习行为&#xff0c;以获取新的知识或…

ios实现wifi搜索连接_苹果IOS设备常见无线连接问题

由于苹果设备良好的操作体验&#xff0c;越来越多的家庭用户开始购置IPAD、IPhone、IPod Touch等苹果&#xff0c;它们都具备一个共同点&#xff1a;支持Wi-Fi连接&#xff0c;这无疑为广大用户连接互联网的提供了最大的便利&#xff0c;但与此同时&#xff0c;越来越多的无线连…

苹果手机连到电脑后找不到服务器,iPhone手机热点明明打开了,可是电脑就是连不上怎么办?...

解决方法一&#xff1a; 很有可能是网络连接的问题&#xff0c;先关闭iPhone手机的热点&#xff0c;然后再重新打开&#xff0c;然后重启电脑&#xff0c;再重新进行连接尝试一下。 解决方法二&#xff1a; iPhone手机的热点打开了&#xff0c;但是电脑连不上&#xff0c;还有可…

WiFi状态不存在 连不上无线网

最近遇到一个很烦的事情&#xff0c;就是笔记本电脑的WiFi老是突然就不见了那种&#xff0c;打开WLAN&#xff0c;任务栏的网络图标变成一个地球的图案&#xff0c;点开了是这个情况 点开网络和Internet设置&#xff0c;下图中红框圈中的部分甚至都没有显示 在系统服务里面也…