绘制:
1.在pubspec.yaml中引入:fl_chart: 0.55.2
2.绘制:
import 'package:jade/utils/JadeColors.dart';
import 'package:util/easy_loading_util.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';class MyLineChart extends StatefulWidget {const MyLineChart({Key key}) : super(key: key);State<MyLineChart> createState() => _MyLineChartState();
}class _MyLineChartState extends State<MyLineChart> with TickerProviderStateMixin{List<String> _tabs = ['近7日','近1月','近3月'];TabController _tabController;List<Color> gradientColors = [Colors.yellow,Colors.yellow,];//进入后默认显示指示竖线和轨迹球的点FlSpot _defaultShowFlSpot = FlSpot(8, 4);//进入页面时默认显示的点上的竖线显隐开关bool _showSpotLine = true;List<String> get weekDays => const ['10.21', '10.22', '10.23', '10.24', '10.25', '10.26', '10.27'];void initState() {// TODO: implement initStatesuper.initState();_tabController = TabController(length: _tabs.length,vsync: this);}void dispose() {// TODO: implement dispose_tabController.dispose();super.dispose();}Widget build(BuildContext context) {return Container(child: Column(children: <Widget>[_tabBarView(),_lineChartWidget()],),);}//选项卡_tabBarView(){return Container(width: double.infinity,height: 120.w,margin: EdgeInsets.only(bottom: 20.w),decoration: BoxDecoration(color: JadeColors.lightGrey,borderRadius: BorderRadius.circular(5)),child: Column(children: [Container(height: 70.w,child: TabBar(isScrollable: false,labelPadding: EdgeInsets.symmetric(horizontal: 0),indicator: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(5),border: Border.all(width: 2,color: JadeColors.lightGrey)),labelColor: Color(0xff333333),labelStyle: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w600,),unselectedLabelColor: JadeColors.grey,unselectedLabelStyle: TextStyle(fontSize: 30.sp,fontWeight: FontWeight.w300),indicatorSize: TabBarIndicatorSize.tab,controller: _tabController,tabs: _tabs.map((value) => Container(width: double.infinity,height: double.infinity,padding: EdgeInsets.symmetric(horizontal: 20.w),alignment: Alignment.center,decoration: BoxDecoration(borderRadius: BorderRadius.only(topLeft: value == _tabs.first? Radius.circular(5): Radius.circular(0),bottomLeft: value == _tabs.first? Radius.circular(5): Radius.circular(0),topRight: value == _tabs.last? Radius.circular(5): Radius.circular(0),bottomRight: value == _tabs.last? Radius.circular(5): Radius.circular(0),),border: Border.all(width: 1.w,color: JadeColors.grey_4)),child: Text(value))).toList(),onTap: (index) {esLoadingToast('点击${_tabs[index]}');},)),Expanded(child: Container(margin: EdgeInsets.only(left: 40.w,right: 40.w),child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text('2023-10-30',style: TextStyle(color: JadeColors.grey_2,fontSize: 22.sp,fontWeight: FontWeight.bold),),Text.rich(TextSpan(children: [TextSpan(text: '核销数:',style: TextStyle(color: JadeColors.grey_3,fontSize: 22.sp)),TextSpan(text: '5',style: TextStyle(color: JadeColors.orange,fontSize: 22.sp))]))],),))],),);}//折线图表_lineChartWidget(){return AspectRatio(aspectRatio: 1.70,child: Padding(padding: EdgeInsets.only(right: 40.w,),child: LineChart(mainData())),);}LineChartData mainData() {return LineChartData(//网格gridData: FlGridData(show: true,drawVerticalLine: false,horizontalInterval: 1,verticalInterval: 1,getDrawingHorizontalLine: (value) {return FlLine(color: JadeColors.lightGrey,strokeWidth: 1,);},getDrawingVerticalLine: (value) {return FlLine(color: Colors.red,strokeWidth: 1,);},),titlesData: FlTitlesData(show: true,rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false),),topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false),),bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: true,reservedSize: 30,interval: 2,getTitlesWidget: bottomTitleWidgets,),),leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: true,interval: 1,getTitlesWidget: leftTitleWidgets,reservedSize: 30,),),),borderData: FlBorderData(show: true,// border: Border.symmetric(horizontal: BorderSide(color: JadeColors.lightGrey, width: 1)),border: Border.fromBorderSide( BorderSide(color: JadeColors.lightGrey, width: 1)),),minX: 0,maxX: 12,minY: 0,maxY: 6,lineBarsData: [LineChartBarData(spots: const [FlSpot(0, 0),FlSpot(2.6, 4),FlSpot(4.9, 5),FlSpot(6.8, 3.1),FlSpot(8, 4),FlSpot(9.5, 3),FlSpot(12, 6),],isCurved: false,gradient: LinearGradient(colors: gradientColors,),barWidth: 2,dotData: FlDotData(show: _showSpotLine,getDotPainter: (spot, percent, barData, index) {//当点是默认要显示的点时if(spot == _defaultShowFlSpot){return FlDotCirclePainter(strokeWidth: 1,strokeColor: const Color(0xffF27800),radius: 2,color: Colors.white,);}return FlDotCirclePainter(strokeWidth: 0,strokeColor: Colors.yellow,radius: 1,color: Colors.yellow,);}),belowBarData: BarAreaData(show: true,gradient: LinearGradient(colors: [Colors.yellow,Colors.white].map((color) => color.withOpacity(0.3)).toList(),begin: Alignment.topCenter, end: Alignment.bottomCenter),spotsLine: BarAreaSpotsLine(show: _showSpotLine,flLineStyle: FlLine(color: const Color(0xffF27800),strokeWidth: 1,),checkToShowSpotLine: (spot) {if (spot == _defaultShowFlSpot) {return true;}return false;},),),aboveBarData: BarAreaData(show: _showSpotLine,gradient: LinearGradient(colors: [Colors.white,Colors.white].map((color) => color.withOpacity(0.3)).toList(),begin: Alignment.topCenter, end: Alignment.bottomCenter),spotsLine: BarAreaSpotsLine(show: true,flLineStyle: FlLine(color: const Color(0xffF27800),strokeWidth: 1,),checkToShowSpotLine: (spot) {if (spot == _defaultShowFlSpot) {return true;}return false;},),),),],lineTouchData: LineTouchData(enabled: true,getTouchLineEnd: (data, index) => double.infinity,getTouchedSpotIndicator: (LineChartBarData barData, List<int> spotIndexes) {return spotIndexes.map((spotIndex) {return TouchedSpotIndicatorData(//接触点竖线FlLine(color: const Color(0xffF27800), strokeWidth: 1),FlDotData(//设置接触点 轨迹球画笔getDotPainter: (spot, percent, barData, index) =>FlDotCirclePainter(strokeWidth: 1,strokeColor: const Color(0xffF27800),radius: 2,color: Colors.white,),),);}).toList();},touchTooltipData: LineTouchTooltipData(tooltipBgColor:Colors.black26),touchCallback: (FlTouchEvent event,LineTouchResponse response){if(event!= null){bool isInteractions = event.isInterestedForInteractions; //手指是否和图表交互(手指和图标交互时隐藏默认显示的点的指示线和轨迹球,手指离开时则隐藏)setState(() {_showSpotLine = !isInteractions;});}if(response != null){TouchLineBarSpot touchLineBarSpot = response?.lineBarSpots?.first;int spotIndex = touchLineBarSpot?.spotIndex;LineChartBarData lineChartBarData = touchLineBarSpot?.bar;if(lineChartBarData != null && spotIndex != null){FlSpot flSpot = lineChartBarData.spots[spotIndex];// print('spotIndex= ${touchLineBarSpot?.spotIndex}'); //接触的是折线的第几个圆点// print('barIndex= ${touchLineBarSpot?.barIndex}'); //接触的是第几条折线// print('flSpot.x= ${flSpot?.x}');print('flSpot.y= ${flSpot?.y}');// print('spotIndex= ${touchLineBarSpot?.props}');}}}));}Widget bottomTitleWidgets(double value, TitleMeta meta) {TextStyle style = TextStyle(fontWeight: FontWeight.w600,fontSize: 22.sp,);Widget text;switch (value.toInt()) {case 0:text = Text('10.25', style: style);break;case 2:text = Text(' 10.26 ', style: style);break;case 4:text = Text(' 10.27 ', style: style);break;case 6:text = Text(' 10.28 ', style: style);break;case 8:text = Text(' 10.29 ', style: style);break;case 10:text = Text(' 10.30 ', style: style);break;case 12:text = Text(' 10.31 ', style: style);break;default:text = Text('', style: style);break;}return SideTitleWidget(axisSide: meta.axisSide,child: text,);}Widget leftTitleWidgets(double value, TitleMeta meta) {TextStyle style = TextStyle(fontWeight: FontWeight.w600,fontSize: 22.sp,);String text;switch (value.toInt()) {case 0:text = '0';break;case 1:text = '2';break;case 2:text = '4';break;case 3:text = '6';break;case 4:text = '8';break;case 5:text = '10';break;default:return Container();}return Text(text, style: style, textAlign: TextAlign.center);}
}
切换的选项卡没有绘制。对应的数据和坐标点之间的换算没做,要根据后台给的数据操作,现在这个只是单纯的绘制。