💄 Better graph card
This commit is contained in:
		| @@ -1,5 +1,7 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:fl_chart/fl_chart.dart'; | ||||
| import 'package:google_fonts/google_fonts.dart'; | ||||
| import 'package:latext/latext.dart'; | ||||
| import 'package:simple_math_calc/parser.dart'; | ||||
| import 'package:simple_math_calc/calculator.dart'; | ||||
| import 'package:simple_math_calc/solver.dart'; | ||||
| @@ -25,6 +27,7 @@ class GraphCard extends StatefulWidget { | ||||
|  | ||||
| class _GraphCardState extends State<GraphCard> { | ||||
|   final SolverService _solverService = SolverService(); | ||||
|   FlSpot? _currentTouchedPoint; | ||||
|  | ||||
|   /// 生成函数图表的点 | ||||
|   List<FlSpot> _generatePlotPoints(String expression, double zoomFactor) { | ||||
| @@ -145,6 +148,19 @@ class _GraphCardState extends State<GraphCard> { | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   String _formatAxisValue(double value) { | ||||
|     if (value.abs() < 1e-10) return "0"; | ||||
|     if ((value - value.roundToDouble()).abs() < 1e-10) { | ||||
|       return value.round().toString(); | ||||
|     } | ||||
|     double absVal = value.abs(); | ||||
|     if (absVal >= 100) return value.toStringAsFixed(0); | ||||
|     if (absVal >= 10) return value.toStringAsFixed(1); | ||||
|     if (absVal >= 1) return value.toStringAsFixed(2); | ||||
|     if (absVal >= 0.1) return value.toStringAsFixed(3); | ||||
|     return value.toStringAsFixed(4); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return ListView( | ||||
| @@ -212,23 +228,53 @@ class _GraphCardState extends State<GraphCard> { | ||||
|                             leftTitles: AxisTitles( | ||||
|                               sideTitles: SideTitles( | ||||
|                                 showTitles: true, | ||||
|                                 reservedSize: 80, | ||||
|                                 reservedSize: 60, | ||||
|                                 interval: (bounds.maxY - bounds.minY) / 8, | ||||
|                                 getTitlesWidget: (value, meta) => | ||||
|                                     SideTitleWidget( | ||||
|                                       axisSide: meta.axisSide, | ||||
|                                       child: Text(value.toStringAsFixed(2)), | ||||
|                                       child: Text( | ||||
|                                         _formatAxisValue(value), | ||||
|                                         style: GoogleFonts.robotoFlex(), | ||||
|                                       ), | ||||
|                                     ), | ||||
|                               ), | ||||
|                             ), | ||||
|                             bottomTitles: AxisTitles( | ||||
|                               sideTitles: SideTitles( | ||||
|                                 showTitles: true, | ||||
|                                 reservedSize: 24, | ||||
|                                 getTitlesWidget: (value, meta) => | ||||
|                                     SideTitleWidget( | ||||
|                                       axisSide: meta.axisSide, | ||||
|                                       child: Text(value.toStringAsFixed(2)), | ||||
|                                     ), | ||||
|                                 reservedSize: 80, | ||||
|                                 interval: (bounds.maxX - bounds.minX) / 10, | ||||
|                                 getTitlesWidget: (value, meta) => SideTitleWidget( | ||||
|                                   axisSide: meta.axisSide, | ||||
|                                   child: Column( | ||||
|                                     mainAxisSize: MainAxisSize.min, | ||||
|                                     children: _formatAxisValue(value) | ||||
|                                         .split('') | ||||
|                                         .map( | ||||
|                                           (char) => ['-', '.'].contains(char) | ||||
|                                               ? Transform.rotate( | ||||
|                                                   angle: pi / 2, | ||||
|                                                   child: Text( | ||||
|                                                     char, | ||||
|                                                     style: | ||||
|                                                         GoogleFonts.robotoFlex( | ||||
|                                                           height: char == '.' | ||||
|                                                               ? 0.7 | ||||
|                                                               : 0.9, | ||||
|                                                         ), | ||||
|                                                   ), | ||||
|                                                 ) | ||||
|                                               : Text( | ||||
|                                                   char, | ||||
|                                                   style: GoogleFonts.robotoFlex( | ||||
|                                                     height: 0.9, | ||||
|                                                   ), | ||||
|                                                 ), | ||||
|                                         ) | ||||
|                                         .toList(), | ||||
|                                   ), | ||||
|                                 ), | ||||
|                               ), | ||||
|                             ), | ||||
|                             topTitles: AxisTitles( | ||||
| @@ -246,6 +292,17 @@ class _GraphCardState extends State<GraphCard> { | ||||
|                           ), | ||||
|                           lineTouchData: LineTouchData( | ||||
|                             enabled: true, | ||||
|                             touchCallback: (event, response) { | ||||
|                               if (response != null && | ||||
|                                   response.lineBarSpots != null && | ||||
|                                   response.lineBarSpots!.isNotEmpty) { | ||||
|                                 setState(() { | ||||
|                                   _currentTouchedPoint = | ||||
|                                       response.lineBarSpots!.first; | ||||
|                                 }); | ||||
|                               } | ||||
|                               // Keep the last touched point visible | ||||
|                             }, | ||||
|                             touchTooltipData: LineTouchTooltipData( | ||||
|                               getTooltipItems: (touchedSpots) { | ||||
|                                 return touchedSpots.map((spot) { | ||||
| @@ -276,6 +333,28 @@ class _GraphCardState extends State<GraphCard> { | ||||
|                     }, | ||||
|                   ), | ||||
|                 ), | ||||
|                 if (_currentTouchedPoint != null) | ||||
|                   Container( | ||||
|                     margin: const EdgeInsets.only(top: 16), | ||||
|                     padding: const EdgeInsets.all(12), | ||||
|                     decoration: BoxDecoration( | ||||
|                       color: Theme.of( | ||||
|                         context, | ||||
|                       ).colorScheme.surfaceContainerHighest, | ||||
|                       borderRadius: BorderRadius.circular(8), | ||||
|                     ), | ||||
|                     child: Column( | ||||
|                       mainAxisAlignment: MainAxisAlignment.center, | ||||
|                       children: [ | ||||
|                         LaTexT( | ||||
|                           laTeXCode: Text( | ||||
|                             '\$\$x = ${_currentTouchedPoint!.x.toStringAsFixed(4)},\\quad y = ${_currentTouchedPoint!.y.toStringAsFixed(4)}\$\$', | ||||
|                             style: Theme.of(context).textTheme.bodyLarge, | ||||
|                           ), | ||||
|                         ), | ||||
|                       ], | ||||
|                     ), | ||||
|                   ), | ||||
|               ], | ||||
|             ), | ||||
|           ), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user