Flutter地图展示插件mapbox_flutter的使用

Flutter地图展示插件mapbox_flutter的使用

本项目灵感来源于 Mapbox_gl,并且集成了 Null Safety(空安全)。

我们欢迎 反馈 和贡献。

mapbox.PNG

运行示例应用

  1. 安装 Flutter 并通过运行 flutter doctor 验证安装。
  2. 使用以下命令克隆仓库:git clone git@github.com:BorisGautier/mapbox_flutter.git
  3. 在示例应用中添加一个公开的 Mapbox 访问令牌(见下一节)。
  4. 添加一个用于下载 SDK 的秘密 Mapbox 访问令牌。
  5. 连接移动设备或启动模拟器、仿真器或 Chrome。
  6. 使用 flutter devices 查找设备 ID。
  7. 使用以下命令运行应用:cd mapbox_flutter/example && flutter packages get && flutter run -d {device_id}

添加 Mapbox 访问令牌

本项目使用 Mapbox 矢量瓦片,这需要一个 Mapbox 账户和 Mapbox 访问令牌。在您的 Mapbox 账户页面 获取免费访问令牌。

即使您不使用 Mapbox 矢量瓦片,而是从其他来源(如自托管瓦片)使用此插件,您仍然需要指定一个非空字符串作为访问令牌!

通过 MapboxFlutterMap 构造函数推荐的方式

推荐的方法是通过 MapboxFlutterMap 构造函数的 accessToken 参数提供访问令牌。请注意,您应该在整个应用程序中始终使用相同的令牌。

final MapboxFlutterMap mapboxFlutterMap = MapboxFlutterMap(
  accessToken: 'YOUR_ACCESS_TOKEN_HERE',
);

通过平台特定文件设置旧方法

对于早期版本,您需要通过平台特定文件设置访问令牌,如下面所述。此方法在 v0.8 上也将作为后备继续工作。您不应同时通过构造函数参数和平台特定文件设置访问令牌!

Android

在应用清单文件中添加 Mapbox 访问令牌配置:

<manifest ...
  <application ...
    <meta-data android:name="com.mapbox.token" android:value="YOUR_TOKEN_HERE" />
</manifest>

iOS

在应用 Info.plist 文件中添加 Mapbox 访问令牌配置:

<key>io.flutter.embedded_views_preview</key>
<true/>
<key>MGLMapboxAccessToken</key>
<string>YOUR_TOKEN_HERE</string>

Web

index.html 文件中添加 Mapbox 访问令牌配置:

<body>
  ...
  <script>
    mapboxgl.accessToken = 'YOUR_TOKEN_HERE';
  </script>
</body>

SDK 下载令牌

您还必须配置具有 Download: read 范围的秘密访问令牌。如果未进行此配置,在 iOS 构建期间会出现类似以下错误:

[!] Error installing Mapbox-iOS-SDK
curl: (22) The requested URL returned error: 401 Unauthorized

避免 Android UnsatisfiedLinkError

android\app\build.gradle 中更新构建类型:

buildTypes {
    release {
        // 其他配置
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a','x86_64', 'x86'
        }
    }
}

在项目中使用 SDK

该项目可在 pub.dev 上找到,按照 文档 中的说明将包集成到您的 Flutter 应用程序中。对于平台特定的集成,请参考示例文件夹下的 flutter 应用程序。

支持的 API

功能 Android iOS Web
样式
相机
手势
用户位置
符号
圆形
线条
填充

地图样式

可以通过在 MapOptions 中设置 styleString 来提供地图样式。支持以下格式:

  1. 传递地图样式的 URL。可以是内置的地图样式,也可以是通过 MapboxStyles 提供的样式,或者是一个通过 URL 开头为 'http(s)://''mapbox://' 提供的远程服务的自定义地图样式。
  2. 将样式作为本地资产传递。在 assets 中创建一个 JSON 文件,并在 pubspec.yml 中添加引用。将样式字符串设置为该资产的相对路径以加载到地图中。
  3. 将样式作为本地文件传递。在应用程序目录(例如 ApplicationDocumentsDirectory)中创建一个 JSON 文件。将样式字符串设置为此 JSON 文件的绝对路径。
  4. 将地图样式的原始 JSON 传递。仅在 Android 上受支持。

离线侧加载

通过“侧加载”所需的地图瓦片并将其包含在 assets 文件夹中,可以实现离线地图支持。

  1. 按照 此处 提供的指南创建您的瓦片包。
  2. 将步骤一生成的 tiles.db 文件放置在您的 assets 目录中,并在 pubspec.yml 文件中添加引用。
assets:
  - assets/cache.db
  1. 在应用程序启动时调用 installOfflineMapTiles 以将瓦片复制到 Mapbox 可以访问的位置。注意:此方法应在 Map 小部件加载之前调用,以防止在复制文件时发生冲突。
try {
  await installOfflineMapTiles(join("assets", "cache.db"));
} catch (err) {
  print(err);
}

下载离线区域

离线区域是地图上定义的一个区域,可用于在网络连接有限或无网络的情况下使用。通过 Mapbox SDK 的适当方法从选定区域、样式和精度下载瓦片,并存储在应用程序的缓存中。

  1. 注意选择较大的区域,因为大小可能会显著增加。您可以使用在线估算器 https://docs.mapbox.com/playground/offline-estimator/
  2. 使用预定义的 OfflineRegion 调用 downloadOfflineRegionStream,并在回调函数中可选地跟踪进度。
final Function(DownloadRegionStatus event) onEvent = (DownloadRegionStatus status) {
  if (status.runtimeType == Success) {
    // ...
  } else if (status.runtimeType == InProgress) {
    int progress = (status as InProgress).progress.round();
    // ...
  } else if (status.runtimeType == Error) {
    // ...
  }
};

final OfflineRegion offlineRegion = OfflineRegion(
  bounds: LatLngBounds(
    northeast: LatLng(52.5050648, 13.3915634),
    southwest: LatLng(52.4943073, 13.4055383),
  ),
  id: 1,
  minZoom: 6,
  maxZoom: 18,
  mapStyleUrl: 'mapbox://styles/mapbox/streets-v11',
);

downloadOfflineRegionStream(offlineRegion, onEvent);

位置功能

Android

在应用清单文件中添加 <uses-permission> 来启用位置功能:

<manifest ...
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>

从 Android API 级别 23 开始,您还需要在运行时请求权限。此插件不会为您处理此操作。示例应用使用了 flutter 的 'location' 插件来处理此问题。

iOS

要在 iOS 应用中启用位置功能:

如果您访问用户的位置,还应在 ios/Runner/Info.plist 中添加以下键,以解释为什么需要访问其位置数据:

<key>NSLocationWhenInUseUsageDescription</key>
<string>[Your explanation here]</string>

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

1 回复

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


mapbox_flutter 是一个用于在 Flutter 应用中集成 Mapbox 地图的插件。它允许你在应用中显示地图、添加标记、绘制路线等。以下是如何在 Flutter 项目中使用 mapbox_flutter 的基本步骤。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 mapbox_flutter 插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  mapbox_gl: ^0.16.0  # 请检查最新版本

然后运行 flutter pub get 来获取依赖。

2. 获取 Mapbox 访问令牌

你需要在 Mapbox 官网上注册一个账户并创建一个项目,以获取访问令牌(Access Token)。访问令牌将用于在你的应用中加载 Mapbox 地图。

3. 配置 Android 和 iOS

Android 配置

android/app/src/main/AndroidManifest.xml 文件中添加以下代码:

<meta-data
    android:name="com.mapbox.token"
    android:value="YOUR_MAPBOX_ACCESS_TOKEN" />

iOS 配置

ios/Runner/Info.plist 文件中添加以下代码:

<key>MGLMapboxAccessToken</key>
<string>YOUR_MAPBOX_ACCESS_TOKEN</string>

4. 使用 Mapbox 地图

在你的 Flutter 代码中,你可以使用 MapboxMap 组件来显示地图。以下是一个简单的示例:

import 'package:flutter/material.dart';
import 'package:mapbox_gl/mapbox_gl.dart';

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> {
  MapboxMapController mapController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Mapbox Flutter'),
      ),
      body: MapboxMap(
        accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
        onMapCreated: _onMapCreated,
        initialCameraPosition: CameraPosition(
          target: LatLng(37.7749, -122.4194),  // 旧金山坐标
          zoom: 12.0,
        ),
      ),
    );
  }

  void _onMapCreated(MapboxMapController controller) {
    setState(() {
      mapController = controller;
    });
  }
}

5. 添加标记、绘制路线等

你可以使用 mapController 来添加标记、绘制路线等。以下是一些常见的操作:

添加标记

void addMarker() {
  mapController.addSymbol(
    SymbolOptions(
      geometry: LatLng(37.7749, -122.4194),  // 标记的位置
      iconImage: 'marker-icon',  // 图标
    ),
  );
}

绘制路线

void drawRoute() {
  mapController.addLine(
    LineOptions(
      geometry: [
        LatLng(37.7749, -122.4194),
        LatLng(37.7849, -122.4294),
      ],
      lineColor: '#FF0000',  // 路线颜色
      lineWidth: 3.0,        // 路线宽度
    ),
  );
}

6. 处理用户交互

你可以通过 onMapClick 等回调来处理用户与地图的交互。例如:

MapboxMap(
  accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
  onMapCreated: _onMapCreated,
  initialCameraPosition: CameraPosition(
    target: LatLng(37.7749, -122.4194),  // 旧金山坐标
    zoom: 12.0,
  ),
  onMapClick: (point, coordinates) {
    print('Map clicked at: $coordinates');
  },
),
回到顶部