You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter加载大尺寸导航地图时崩溃的问题求助(需保留地图分辨率与绘图功能)

Flutter加载大尺寸导航地图时崩溃的问题求助(需保留地图分辨率与绘图功能)

各位Flutter开发的朋友们,我最近碰到个头疼的问题,想请大家帮忙支招!

我做了一个Flutter应用,里面要加载机器人导航用的地图。现在的情况是:只要加载大于2MB的地图(其中一张分辨率高达6906 × 8679,而小尺寸的地图只有711 × 489),要么放大到一定程度就崩溃,要么如果默认启动加载的是大地图,直接启动就崩。

我已经试过各种能想到的办法了,但有个硬性要求:绝对不能降低地图的尺寸或者分辨率,因为这张地图同时要给自主机器人做导航用,而且我还需要在地图上绘制路径和标记点。

下面是我处理地图显示的核心代码,麻烦大家帮我看看问题可能出在哪:

import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:ui' as ui;
import 'dart:ui';
// 其他导入省略...

class MapPage extends ConsumerStatefulWidget {
  const MapPage({super.key, required this.mapSelected});
  final Directory? mapSelected;

  @override
  ConsumerState<ConsumerStatefulWidget> createState() => MapPageState();
}

class MapPageState extends ConsumerState<MapPage> {
  final viewTransformationController = TransformationController();

  Future<List<ui.Image>> init() async {
    var file = File(
      path.join(
        widget.mapSelected?.path ?? '',
        FolderConstants.editedAreaMap,
      ),
    );
    if (!file.existsSync()) {
      file = File(
        path.join(
          widget.mapSelected?.path ?? '',
          FolderConstants.mapPath,
        ),
      );
    }
    final bytesMap = file.readAsBytesSync();
    final robotId = ref.read(robotConnectControllerProvider);
    final typeRobot = RobotTypeToId.getRobotType(robotId ?? '').toString();
    late Uint8List bytesRobject;
    bytesRobject = Uint8List.view(
      (await rootBundle.load(Assets.images.robjectRobot.path)).buffer,
    );
    
    final mapImage = await loadImage(bytesMap);
    final robjectImage = await loadImage(bytesRobject);
    return [mapImage, robjectImage];
  }

  Future<ui.Image> loadImage(Uint8List img) async {
    final completer = Completer<ui.Image>();
    ui.decodeImageFromList(img, completer.complete);
    return completer.future;
  }

  void zoomCenterFitView(BoxConstraints constraint, double zoomFactor) {
    final xTrans = (constraint.maxWidth / 2) * (zoomFactor - 1);
    final yTrans = (constraint.maxHeight / 2) * (zoomFactor - 1);
    viewTransformationController.value.setEntry(0, 0, zoomFactor);
    viewTransformationController.value.setEntry(1, 1, zoomFactor);
    viewTransformationController.value.setEntry(2, 2, zoomFactor);
    viewTransformationController.value.setEntry(0, 3, -xTrans);
    viewTransformationController.value.setEntry(1, 3, -yTrans);
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      ref.read(zoomValueControllerProvider.notifier).value = zoomFactor;
    });
  }

  void zoomRobot(Offset? robotPostion, Offset rectSize, double zoomFactor) {
    if (robotPostion == null) {
      return;
    }
    final scaledPose = scalePoint(robotPostion, rectSize, zoomFactor);
    final xTrans = scaledPose.dx * (zoomFactor - 1);
    final yTrans = scaledPose.dy * (zoomFactor - 1);
    viewTransformationController.value.setEntry(0, 0, zoomFactor);
    viewTransformationController.value.setEntry(1, 1, zoomFactor);
    viewTransformationController.value.setEntry(2, 2, zoomFactor);
    viewTransformationController.value.setEntry(0, 3, -xTrans);
    viewTransformationController.value.setEntry(1, 3, -yTrans);
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      ref.read(zoomValueControllerProvider.notifier).value = zoomFactor;
    });
  }

  Offset scalePoint(Offset point, Offset rectSize, double zoomFactor) {
    final origin = rectSize / 2;
    final pointInRect = point - origin;
    final pointScaled = pointInRect * (1 + 1 / (zoomFactor - 1));
    return pointScaled + origin;
  }

  double fittedRatio(Offset screenOffset, Offset rectOffset) {
    final widthRatio = screenOffset.dx / rectOffset.dx;
    final heightRatio = screenOffset.dy / rectOffset.dy;
    return min(widthRatio, heightRatio);
  }

  Offset fitPoint(Offset point, Offset screenOffset, Offset rectOffset) {
    final ratio = fittedRatio(screenOffset, rectOffset);
    final fittedPoint = point * ratio;
    final spaceDelta = screenOffset - rectOffset * ratio;
    return fittedPoint + (spaceDelta / 2);
  }

  @override
  Widget build(BuildContext context) {
    ref
      ..watch(pathControllerProvider)
      ..watch(pointControllerProvider)
      ..watch(zoneControllerProvider)
      ..watch(loadDataFromLocalControllerProvider);
    final robotPostions = ref.watch(robotPositionsControllerProvider);
    final mapActions = ref.watch(mapActionControllerProvider);
    final settingsData = ref.watch(displaySettingControllerProvider);
    final zoomRatio = ref.watch(zoomValueControllerProvider);
    final step = scaleStep.lowerBound(zoomRatio);

    return widget.mapSelected == null
        ? Container()
        : Stack(
            children: [
              FutureBuilder(
                future: init(),
                builder: (context, snapshot) {
                  if (snapshot.hasError) {
                    return const SizedBox();
                  }
                  switch (snapshot.hasData) {
                    case true:
                      return LayoutBuilder(
                        builder: (context, constraint) {
                          const zoomFactor = 1.0;
                          final screenOffset = Offset(
                            constraint.maxWidth,
                            constraint.maxHeight,
                          );
                          final rectOffset = Offset(
                            snapshot.data!.first.width.toDouble(),
                            snapshot.data!.first.height.toDouble(),
                          );
                          // 后续WidgetBinding及地图绘制相关代码省略...
                        },
                      );
                    default:
                      return const CircularProgressIndicator();
                  }
                },
              ),
              // 路径、标记点绘制等Stack子组件省略...
            ],
          );
  }
}

真心希望大家能帮我分析下问题根源,或者给一些不降低地图分辨率前提下的优化建议,谢谢大家!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 10:53:08