magnetSnap method

Offset magnetSnap(
  1. Offset point,
  2. List<KLineEntity>? datas,
  3. double scaleX,
  4. double scrollX,
  5. double getX(
    1. double
    ),
  6. double getY(
    1. double
    ),
  7. Rect chartRect,
)

磁铁吸附功能 - 将点吸附到最近的K线数据点

Implementation

Offset magnetSnap(
  Offset point,
  List<KLineEntity>? datas,
  double scaleX,
  double scrollX,
  double Function(double) getX,
  double Function(double) getY,
  Rect chartRect,
) {
  if (!_isMagnetMode || datas == null || datas.isEmpty) {
    return point;
  }

  try {
    // 计算最近的K线索引
    double chartWidth = chartRect.width;
    double pointWidth = chartWidth / (datas.length * scaleX);
    int dataIndex =
        ((point.dx - chartRect.left) / pointWidth + scrollX).round();

    // 确保索引在有效范围内
    dataIndex = dataIndex.clamp(0, datas.length - 1);

    if (dataIndex < 0 || dataIndex >= datas.length) {
      return point;
    }

    KLineEntity kLine = datas[dataIndex];

    // 计算K线的各个价格点在屏幕上的Y坐标
    double openY = getY(kLine.open);
    double closeY = getY(kLine.close);
    double highY = getY(kLine.high);
    double lowY = getY(kLine.low);

    // 计算K线在屏幕上的X坐标
    double kLineX = getX(dataIndex.toDouble());

    // 找到距离点击点最近的价格点
    List<Offset> pricePoints = [
      Offset(kLineX, openY), // 开盘价
      Offset(kLineX, closeY), // 收盘价
      Offset(kLineX, highY), // 最高价
      Offset(kLineX, lowY), // 最低价
    ];

    // 计算距离并找到最近的点
    double minDistance = double.infinity;
    Offset snapPoint = point;

    for (Offset pricePoint in pricePoints) {
      double distance = (point - pricePoint).distance;
      if (distance < minDistance) {
        minDistance = distance;
        snapPoint = pricePoint;
      }
    }

    // 只有在合理距离内才吸附(比如50像素内)
    const double snapThreshold = 50.0;
    if (minDistance <= snapThreshold) {
      debugPrint(
          '磁铁吸附: 从 $point 吸附到 $snapPoint (距离: ${minDistance.toStringAsFixed(1)})');
      return snapPoint;
    }
  } catch (e) {
    debugPrint('磁铁吸附计算错误: $e');
  }

  return point;
}