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
相关产品推荐
相关产品推荐

