Commit 58eb882eb2c2de6e197c11e85be5e166304c2edf

Authored by 常守达
1 parent aaf9f668

fix(today):实时压力拖动,首尾吸附

... ... @@ -389,6 +389,9 @@ class TodayHrvChartCard extends StatelessWidget {
fontSize: 14,
color: _getColorByState(state),
fontWeight: FontWeight.bold,
inherit: false,
fontFamilyFallback: null,
fontFamily: '',
),
),
TextSpan(
... ... @@ -412,6 +415,9 @@ class TodayHrvChartCard extends StatelessWidget {
color: Color(0xFF78787D),
fontSize: 14,
fontWeight: FontWeight.bold,
inherit: false,
fontFamilyFallback: null,
fontFamily: '',
),
),
TextSpan(
... ... @@ -430,6 +436,9 @@ class TodayHrvChartCard extends StatelessWidget {
TextSpan(
text: '○ ',
style: TextStyle(
inherit: false,
fontFamilyFallback: null,
fontFamily: '',
color: _getColorByState(state),
// fontWeight: FontWeight.bold,
fontSize: 14,
... ... @@ -453,6 +462,9 @@ class TodayHrvChartCard extends StatelessWidget {
TextSpan(
text: '♥ ',
style: const TextStyle(
inherit: false,
fontFamilyFallback: null,
fontFamily: '',
color: Color(0xFF78787D),
fontSize: 14,
fontWeight: FontWeight.bold,
... ... @@ -953,11 +965,58 @@ class _StressBarChartState extends State<_StressBarChart> {
event is FlPointerHoverEvent ||
event is FlPointerEnterEvent) {
_stressTooltipTimer?.cancel();
if (touchResponse != null &&
touchResponse.spot != null) {
// 优先用触摸坐标直接定位最近的有数据的柱子
// 不依赖 fl_chart 的 spot 检测(touchExtraThreshold 会导致总是找到 spot)
final dx = event.localPosition?.dx;
if (dx != null && slotStateMap.isNotEmpty) {
final stepWidth = barWidth + groupsSpace;
final touchedSlotSec =
(dx / stepWidth).round() * slotSec;
final sortedSlots = slotStateMap.keys.toList()
..sort();
final firstSlot = sortedSlots.first;
final lastSlot = sortedSlots.last;
int? targetIndex;
if (touchedSlotSec <= firstSlot) {
// 超出左侧边界 → 吸附到第一条数据
targetIndex = (firstSlot / slotSec)
.round()
.clamp(0, slotCount - 1);
} else if (touchedSlotSec >= lastSlot) {
// 超出右侧边界 → 吸附到最后一条数据(最新)
targetIndex = (lastSlot / slotSec)
.round()
.clamp(0, slotCount - 1);
} else {
// 在数据范围内:仅在距最近数据点 ≤ 5 个槽(30min)时才吸附
const snapThresholdSlots = 5;
final nearestSlot = sortedSlots.reduce(
(a, b) => (a - touchedSlotSec).abs() <
(b - touchedSlotSec).abs()
? a
: b,
);
final distanceSlots =
(nearestSlot - touchedSlotSec).abs() ~/ slotSec;
if (distanceSlots <= snapThresholdSlots) {
targetIndex = (nearestSlot / slotSec)
.round()
.clamp(0, slotCount - 1);
}
// 超过阈值(大片空白区域)→ targetIndex 保持 null,不显示
}
setState(() {
_stressTouchedGroupIndex = targetIndex;
});
} else if (touchResponse?.spot != null) {
// localPosition 不可用时降级到 fl_chart 的 spot
setState(() {
_stressTouchedGroupIndex =
touchResponse.spot!.touchedBarGroupIndex;
touchResponse!.spot!.touchedBarGroupIndex;
});
} else {
setState(() {
... ...