Flutter地图渲染插件mapsforge_flutter的使用

发布于 1周前 作者 nodeper 来自 Flutter

Flutter 地图渲染插件 mapsforge_flutter 的使用

mapsforge_flutter 是一个纯离线的地图库,用于在 Flutter 应用中展示离线地图。它源自于 Java/Android 的 mapsforge 项目 [https://github.com/mapsforge/mapsforge]。

该库的主要功能是从本地存储的 .map 文件读取地图数据,并在用户设备上渲染这些地图,而无需互联网连接。

如果你的用户在查看地图时在线,那么不建议使用此库。虽然可以显示在线地图,但有许多更简单的库可以完成这项任务。

截图

奥地利离线 奥地利卫星视图 室内导航 等高线 城市

示例

开始使用请参考 简化示例

在子目录 示例 中找到更多示例:

  • 白天和黑夜主题
  • 世界地图
  • 室内示例
  • 等高线渲染
  • 右键菜单
  • 标记点
  • 拖拽功能
  • 在线地图
  • 旋转功能

致谢

首先要感谢 mapsforge 项目的作者,他做了出色的工作!

还要感谢 Chemnitz 大学,他们实现了室内地图的支持。

开始使用

前提条件

pubspec.yaml 中包含库:

  mapsforge_flutter: ^3.0.0

注意:开发过程中可以考虑直接从 GitHub 仓库引入。

pubspec.yaml 中包含所有使用的资源文件(参见示例项目的 pubspec 文件):

flutter:
  assets:
    - packages/mapsforge_flutter/assets/patterns/coniferous.svg
    - packages/mapsforge_flutter/assets/patterns/coniferous_and_deciduous.svg
    - packages/mapsforge_flutter/assets/patterns/deciduous.svg
  ...

初始化 mapsforge

加载包含 OpenStreetMap 数据的 .map 文件:

MapFile mapFile = await MapFile.from(filename, null, null);

MapFile mapFile = await MapFile.using(content, null, null);

注意:如果不再需要,调用 dispose() 方法销毁 mapFile

创建符号缓存,用于存储小图标:

SymbolCache symbolCache = FileSymbolCache();

创建显示模型,定义和保存视图设置,如最大缩放级别:

DisplayModel displayModel = DisplayModel();

注意:为了获得更清晰的地图,可以将 deviceScaleFactor 设置为更高的值,例如 2。

创建渲染主题,指定如何渲染地图信息:

RenderTheme renderTheme = await
RenderThemeBuilder.create(displayModel, "assets/render_themes/defaultrender.xml");

创建渲染器:

JobRenderer jobRenderer = MapDataStoreRenderer(mapFile, renderTheme, symbolCache, true);

或者使用在线渲染器提供 OpenStreetMap 图片:

JobRenderer jobRenderer = MapOnlineRenderer();

可选地,创建一个位图缓存来存储地图瓦片。瓦片将在重启后继续存在,但可能会占用磁盘空间:

TileBitmapCache bitmapCache = await FileTileBitmapCache.create(jobRenderer.getRenderKey());

注意:如果不希望将瓦片存储在文件系统中,也可以使用 MemoryTileBitmapCache

将所有组件组合在一起,形成两个模型:

MapModel mapModel = MapModel(
  displayModel: displayModel,
  renderer: jobRenderer,
  symbolCache: symbolCache,
  tileBitmapCache: bitmapCache,
);

ViewModel viewModel = ViewModel(displayModel: displayModel);

build() 方法中包含 MapView

return FlutterMapView(mapModel: mapModel, viewModel: viewModel);

这样就完成了。

更改位置

可以通过调用 viewModel 来更改地图的位置:

viewModel.setMapViewPosition(48.0901926 , 16.308939);

类似的方法可用于缩放。

示例代码

以下是一个完整的示例代码:

import 'package:flutter/material.dart';
import 'package:mapsforge_example/map-list.dart';

/// 全局变量,包含一系列地图文件。
///
/// 数据可以是包含不同地点的文件,也可以是大型区域的一部分。
final List<MapFileData> MAP_FILE_DATA_LIST = [
  new MapFileData.online(
    displayedName: "Online Austria (支持网页)",
    initialPositionLat: 48.089415,
    initialPositionLong: 16.311374,
    initialZoomLevel: 12,
  ),
  new MapFileData.onlineSatellite(
    displayedName: "Online Austria 卫星视图 (支持网页)",
    initialPositionLat: 48.089415,
    initialPositionLong: 16.311374,
    initialZoomLevel: 12,
  ),
  const MapFileData(
    url: "https://dailyflightbuddy.com/mapsforge_examples/Chemnitz Uni.map",
    fileName: "Chemnitz Uni.map",
    displayedName: "Chemnitz - 大学 (室内)",
    initialPositionLat: 50.81348,
    initialPositionLong: 12.92936,
    initialZoomLevel: 18,
    indoorZoomOverlay: true,
    indoorLevels: {1: 'OG', 0: 'EG', -1: 'UG'},
  ),
  // 其他地图文件...
];

void main() {
  runApp(MyApp());
}

/// 应用程序的入口点。
class MyApp extends StatelessWidget {
  MyApp() {
    _initLogging();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Mapsforge 示例应用',
      home: MapList(MAP_FILE_DATA_LIST),
    );
  }

  /// 设置日志记录器以记录调试消息。
  void _initLogging() {
    // 打印输出到控制台。
    Logger.root.onRecord.listen((LogRecord r) {
      print('${r.time}\t${r.loggerName}\t[${r.level.name}]:\t${r.message}');
    });

    // 日志记录器级别。
    Logger.root.level = Level.FINEST;
  }
}

更多关于Flutter地图渲染插件mapsforge_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地图渲染插件mapsforge_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用mapsforge_flutter插件来渲染地图的示例代码。这个插件允许你使用Mapsforge的离线地图渲染功能。

首先,你需要在你的Flutter项目中添加mapsforge_flutter依赖。打开你的pubspec.yaml文件,并在dependencies部分添加以下行:

dependencies:
  flutter:
    sdk: flutter
  mapsforge_flutter: ^最新版本号  # 请替换为当前最新版本号

然后运行flutter pub get来安装依赖。

接下来,我们需要一些Mapsforge的离线地图文件(通常是.map文件)。你可以从Mapsforge的官方网站或其他资源下载这些文件,并将它们放在你的设备或应用的本地存储中。

以下是一个完整的Flutter应用示例,展示了如何使用mapsforge_flutter插件来渲染地图:

import 'package:flutter/material.dart';
import 'package:mapsforge_flutter/mapsforge_flutter.dart';
import 'dart:io';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MapScreen(),
    );
  }
}

class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  late MapsforgeController _mapsforgeController;

  @override
  void initState() {
    super.initState();
    // 假设你的.map文件在应用的本地存储中
    final mapFilePath = File('path/to/your/mapfile.map').absolute.path;

    _mapsforgeController = MapsforgeController(
      mapFilePath: mapFilePath,
      // 你可以设置其他配置,比如初始缩放级别、中心点等
      initialZoomLevel: 14.0,
      initialCenter: LatLng(你的初始纬度, 你的初始经度),
    );

    // 监听地图加载完成事件(可选)
    _mapsforgeController.mapLoaded.listen((_) {
      print('Map loaded successfully');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Mapsforge Flutter Example'),
      ),
      body: MapsforgeView(
        controller: _mapsforgeController,
      ),
    );
  }

  @override
  void dispose() {
    _mapsforgeController.dispose();
    super.dispose();
  }
}

在这个示例中,我们做了以下几件事:

  1. pubspec.yaml中添加了mapsforge_flutter依赖。
  2. 创建了一个Flutter应用,其中包含一个MapScreen页面。
  3. MapScreen页面的initState方法中,我们初始化了MapsforgeController,并指定了地图文件的路径和其他一些可选的配置。
  4. 使用MapsforgeView组件来渲染地图,并将MapsforgeController传递给它。
  5. dispose方法中释放了MapsforgeController,以避免内存泄漏。

请注意,你需要将path/to/your/mapfile.map替换为你实际的地图文件路径,并将你的初始纬度你的初始经度替换为你希望地图初始显示的中心点的经纬度。

这个示例只是一个基本的入门示例,mapsforge_flutter插件还提供了许多其他功能和配置选项,你可以根据需要进行进一步的探索和使用。

回到顶部