Showing
1 changed file
with
62 additions
and
3 deletions
| @@ -389,6 +389,9 @@ class TodayHrvChartCard extends StatelessWidget { | @@ -389,6 +389,9 @@ class TodayHrvChartCard extends StatelessWidget { | ||
| 389 | fontSize: 14, | 389 | fontSize: 14, |
| 390 | color: _getColorByState(state), | 390 | color: _getColorByState(state), |
| 391 | fontWeight: FontWeight.bold, | 391 | fontWeight: FontWeight.bold, |
| 392 | + inherit: false, | ||
| 393 | + fontFamilyFallback: null, | ||
| 394 | + fontFamily: '', | ||
| 392 | ), | 395 | ), |
| 393 | ), | 396 | ), |
| 394 | TextSpan( | 397 | TextSpan( |
| @@ -412,6 +415,9 @@ class TodayHrvChartCard extends StatelessWidget { | @@ -412,6 +415,9 @@ class TodayHrvChartCard extends StatelessWidget { | ||
| 412 | color: Color(0xFF78787D), | 415 | color: Color(0xFF78787D), |
| 413 | fontSize: 14, | 416 | fontSize: 14, |
| 414 | fontWeight: FontWeight.bold, | 417 | fontWeight: FontWeight.bold, |
| 418 | + inherit: false, | ||
| 419 | + fontFamilyFallback: null, | ||
| 420 | + fontFamily: '', | ||
| 415 | ), | 421 | ), |
| 416 | ), | 422 | ), |
| 417 | TextSpan( | 423 | TextSpan( |
| @@ -430,6 +436,9 @@ class TodayHrvChartCard extends StatelessWidget { | @@ -430,6 +436,9 @@ class TodayHrvChartCard extends StatelessWidget { | ||
| 430 | TextSpan( | 436 | TextSpan( |
| 431 | text: '○ ', | 437 | text: '○ ', |
| 432 | style: TextStyle( | 438 | style: TextStyle( |
| 439 | + inherit: false, | ||
| 440 | + fontFamilyFallback: null, | ||
| 441 | + fontFamily: '', | ||
| 433 | color: _getColorByState(state), | 442 | color: _getColorByState(state), |
| 434 | // fontWeight: FontWeight.bold, | 443 | // fontWeight: FontWeight.bold, |
| 435 | fontSize: 14, | 444 | fontSize: 14, |
| @@ -453,6 +462,9 @@ class TodayHrvChartCard extends StatelessWidget { | @@ -453,6 +462,9 @@ class TodayHrvChartCard extends StatelessWidget { | ||
| 453 | TextSpan( | 462 | TextSpan( |
| 454 | text: '♥ ', | 463 | text: '♥ ', |
| 455 | style: const TextStyle( | 464 | style: const TextStyle( |
| 465 | + inherit: false, | ||
| 466 | + fontFamilyFallback: null, | ||
| 467 | + fontFamily: '', | ||
| 456 | color: Color(0xFF78787D), | 468 | color: Color(0xFF78787D), |
| 457 | fontSize: 14, | 469 | fontSize: 14, |
| 458 | fontWeight: FontWeight.bold, | 470 | fontWeight: FontWeight.bold, |
| @@ -953,11 +965,58 @@ class _StressBarChartState extends State<_StressBarChart> { | @@ -953,11 +965,58 @@ class _StressBarChartState extends State<_StressBarChart> { | ||
| 953 | event is FlPointerHoverEvent || | 965 | event is FlPointerHoverEvent || |
| 954 | event is FlPointerEnterEvent) { | 966 | event is FlPointerEnterEvent) { |
| 955 | _stressTooltipTimer?.cancel(); | 967 | _stressTooltipTimer?.cancel(); |
| 956 | - if (touchResponse != null && | ||
| 957 | - touchResponse.spot != null) { | 968 | + // 优先用触摸坐标直接定位最近的有数据的柱子 |
| 969 | + // 不依赖 fl_chart 的 spot 检测(touchExtraThreshold 会导致总是找到 spot) | ||
| 970 | + final dx = event.localPosition?.dx; | ||
| 971 | + if (dx != null && slotStateMap.isNotEmpty) { | ||
| 972 | + final stepWidth = barWidth + groupsSpace; | ||
| 973 | + final touchedSlotSec = | ||
| 974 | + (dx / stepWidth).round() * slotSec; | ||
| 975 | + | ||
| 976 | + final sortedSlots = slotStateMap.keys.toList() | ||
| 977 | + ..sort(); | ||
| 978 | + final firstSlot = sortedSlots.first; | ||
| 979 | + final lastSlot = sortedSlots.last; | ||
| 980 | + | ||
| 981 | + int? targetIndex; | ||
| 982 | + | ||
| 983 | + if (touchedSlotSec <= firstSlot) { | ||
| 984 | + // 超出左侧边界 → 吸附到第一条数据 | ||
| 985 | + targetIndex = (firstSlot / slotSec) | ||
| 986 | + .round() | ||
| 987 | + .clamp(0, slotCount - 1); | ||
| 988 | + } else if (touchedSlotSec >= lastSlot) { | ||
| 989 | + // 超出右侧边界 → 吸附到最后一条数据(最新) | ||
| 990 | + targetIndex = (lastSlot / slotSec) | ||
| 991 | + .round() | ||
| 992 | + .clamp(0, slotCount - 1); | ||
| 993 | + } else { | ||
| 994 | + // 在数据范围内:仅在距最近数据点 ≤ 5 个槽(30min)时才吸附 | ||
| 995 | + const snapThresholdSlots = 5; | ||
| 996 | + final nearestSlot = sortedSlots.reduce( | ||
| 997 | + (a, b) => (a - touchedSlotSec).abs() < | ||
| 998 | + (b - touchedSlotSec).abs() | ||
| 999 | + ? a | ||
| 1000 | + : b, | ||
| 1001 | + ); | ||
| 1002 | + final distanceSlots = | ||
| 1003 | + (nearestSlot - touchedSlotSec).abs() ~/ slotSec; | ||
| 1004 | + if (distanceSlots <= snapThresholdSlots) { | ||
| 1005 | + targetIndex = (nearestSlot / slotSec) | ||
| 1006 | + .round() | ||
| 1007 | + .clamp(0, slotCount - 1); | ||
| 1008 | + } | ||
| 1009 | + // 超过阈值(大片空白区域)→ targetIndex 保持 null,不显示 | ||
| 1010 | + } | ||
| 1011 | + | ||
| 1012 | + setState(() { | ||
| 1013 | + _stressTouchedGroupIndex = targetIndex; | ||
| 1014 | + }); | ||
| 1015 | + } else if (touchResponse?.spot != null) { | ||
| 1016 | + // localPosition 不可用时降级到 fl_chart 的 spot | ||
| 958 | setState(() { | 1017 | setState(() { |
| 959 | _stressTouchedGroupIndex = | 1018 | _stressTouchedGroupIndex = |
| 960 | - touchResponse.spot!.touchedBarGroupIndex; | 1019 | + touchResponse!.spot!.touchedBarGroupIndex; |
| 961 | }); | 1020 | }); |
| 962 | } else { | 1021 | } else { |
| 963 | setState(() { | 1022 | setState(() { |
-
Please register or login to post a comment