💄 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,22 +228,52 @@ 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(
|
||||
reservedSize: 80,
|
||||
interval: (bounds.maxX - bounds.minX) / 10,
|
||||
getTitlesWidget: (value, meta) => SideTitleWidget(
|
||||
axisSide: meta.axisSide,
|
||||
child: Text(value.toStringAsFixed(2)),
|
||||
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(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -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